Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom metadata strategy data not available in language templates #380

Closed
1 task done
robbieaverill opened this issue Dec 6, 2021 · 3 comments · Fixed by #381
Closed
1 task done

Custom metadata strategy data not available in language templates #380

robbieaverill opened this issue Dec 6, 2021 · 3 comments · Fixed by #381

Comments

@robbieaverill
Copy link
Contributor

What happened?

  1. Create a custom metadata strategy
<?php

namespace App;

use Knuckles\Camel\Extraction\ExtractedEndpointData;
use Knuckles\Camel\Extraction\Metadata;

class CustomMetadata extends Metadata
{
    public function __invoke(ExtractedEndpointData $endpointData, array $routeRules): array
    {
        return ['customMetadata' => true];
    }
}
  1. Configure it:
    /**
     * The strategies Scribe will use to extract information about your routes at each stage.
     * If you create or install a custom strategy, add it here.
     */
    'strategies' => [
        'metadata' => [
            Strategies\Metadata\GetFromDocBlocks::class,
            \App\CustomMetadata::class,
        ],
  1. Override Javascript language template:
# File: resources/views/vendor/scribe/partials/example-requests/javascript.blade.php
@php
    use Knuckles\Scribe\Tools\WritingUtils as u;
    /** @var  Knuckles\Camel\Output\OutputEndpointData $endpoint */

    dd($endpoint->metadata);
@endphp
  1. Run php artisan scribe:generate

I expect to see customMetadata: true in the dumped endpoint metadata, however it's not there:

Knuckles\Camel\Extraction\Metadata^ {#967
  +groupName: null
  +beforeGroup: null
  +afterGroup: null
  +groupDescription: null
  +title: ""
  +description: ""
  +authenticated: false
  #exceptKeys: []
  #onlyKeys: []
}

My environment:

  • PHP version (from php -v): 8.0.5
  • Framework (Laravel/Lumen): Laravel
  • Laravel/Lumen version (from composer show laravel/framework or composer show laravel/lumen-framework): v8.74.0
  • Scribe version (from composer show knuckleswtf/scribe): 3.18.0

My Scribe config (minus the comments):

<?php

use App\CustomMetadata;
use Knuckles\Scribe\Extracting\Strategies;

return [
    'strategies' => [
        'metadata' => [
            Strategies\Metadata\GetFromDocBlocks::class,
            CustomMetadata::class,
        ],
        'urlParameters' => [
            Strategies\UrlParameters\GetFromLaravelAPI::class,
            Strategies\UrlParameters\GetFromLumenAPI::class,
            Strategies\UrlParameters\GetFromUrlParamTag::class,
        ],
        'queryParameters' => [
            Strategies\QueryParameters\GetFromFormRequest::class,
            Strategies\QueryParameters\GetFromInlineValidator::class,
            Strategies\QueryParameters\GetFromQueryParamTag::class,
        ],
        'headers' => [
            Strategies\Headers\GetFromRouteRules::class,
            Strategies\Headers\GetFromHeaderTag::class,
        ],
        'bodyParameters' => [
            Strategies\BodyParameters\GetFromFormRequest::class,
            Strategies\BodyParameters\GetFromInlineValidator::class,
            Strategies\BodyParameters\GetFromBodyParamTag::class,
        ],
        'responses' => [
            Strategies\Responses\UseTransformerTags::class,
            Strategies\Responses\UseApiResourceTags::class,
            Strategies\Responses\UseResponseTag::class,
            Strategies\Responses\UseResponseFileTag::class,
            Strategies\Responses\ResponseCalls::class,
        ],
        'responseFields' => [
            Strategies\ResponseFields\GetFromResponseFieldTag::class,
        ],
    ],
    'database_connections_to_transact' => []
];

Additional info:

This is with a vanilla Laravel installation and one controller method:

<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    /**
     * Return metadata
     *
     * Testing custom strategies.
     */
    public function metadata()
    {
        return response(['test' => 'content']);
    }
}
@robbieaverill robbieaverill added the bug Something isn't working label Dec 6, 2021
@shalvah
Copy link
Contributor

shalvah commented Dec 6, 2021

Yes, customMetadata is an arbitrary key you're returning. That property doesn't exist on the Metadata object, so it's discarded.

This seems to be a useful feature, so I'm willing to accept a PR to add support for that. On the other hand, if you want a workaround, your custom strategy is also given an instance of the ExtractedEndpointData class, and you can modify it directly (although you generally shouldn't). Something like this::

class MyCustomMetadata extends Metadata
{
    public $custom = false;
}

class CustomMetadataStrategy extends MetadataStrategy
{
    public function __invoke(ExtractedEndpointData $endpointData, array $routeRules): array
    {
        $endpointData->metadata = new MyCustomMetadata($endpointData->metadata->toArray());
        $endpointData->metadata->custom = true;
    }
}

A simpler, but dirtier approach (which may not work):

class CustomMetadataStrategy extends MetadataStrategy
{
    public function __invoke(ExtractedEndpointData $endpointData, array $routeRules): array
    {
        // PHP (for now) allows you to add arbitrary properties to any object
        $endpointData->metadata->custom = true;
    }
}

But, yeah, PRs welcome. It would be a simple fix: add a $custom property to the Metadata class that users can set to anything they want.

@shalvah shalvah added feature-request and removed bug Something isn't working labels Dec 6, 2021
@robbieaverill
Copy link
Contributor Author

Thanks @shalvah, the laravel-apidoc-generator package supported this so I had assumed it was a bug, I will make a PR to add it though.

@shalvah
Copy link
Contributor

shalvah commented Dec 6, 2021

It was supported by accident in previous versions of this package, where the $extractedEndpointData was a plain array, but in v3, it was changed to a value object (which is generally better).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants