Use parameter in API platform annotation

Viewed 1319

I am looking how to add a dynamic variable into an API Platform @ApiProperty annotation. I found that Symfony allows that but it does not seem to work in API Platform annotations. For example :

/**
 * Redirection URL.
 *
 * @Groups({"authorization_code_login_write", "authorization_code_logout_write"})
 * @ApiProperty(
 *     attributes={
 *         "openapi_context"={
 *             "type"="string",
 *             "example"="%app.auth.default.redirect%"
 *         }
 *     }
 * )
 */
protected ?string $redirectionUrl = null;

%app.auth.default.redirect% is not replaced by the container parameter with the same name. How should I do ?

2 Answers

At first sight, I see here only the one way - to create your own attribute in openapi_context, let's say my_redirect_example.

Smth like this, in example:

"openapi_context"={
    "type"="string",
    "my_redirect_example"=true
}

Then you need to decorate like in documentation

Smth, like that:

public function normalize($object, $format = null, array $context = [])
{
    $docs = $this->decorated->normalize($object, $format, $context);


    $redirectUrl = .... # your own logic to get this dynamical value

    foreach ($docs['paths'] as $pathName => $path) {
        foreach ($path as $operationName => $operation) {
            if ($operation['my_redirect_example'] ?? false) {
                $docs['paths'][$pathName][$operationName]['example'] = $redirectUrl;
            }
        }
    }

    return $docs;
}

It should work. Anyway - it is just an example (I didn't test it), just to understanding how you can handle it.

Sure, you can replace true value with your own and use it inside the if statement to get it depending on some yours own logic.

The way to go is to follow the documentation to decorate the Swagger Open API generator service (https://api-platform.com/docs/core/swagger/#overriding-the-openapi-specification).

Add your own service :

# api/config/services.yaml
services:
    'App\Swagger\SwaggerDecorator':
        decorates: 'api_platform.swagger.normalizer.api_gateway'
        arguments: [ '@App\Swagger\SwaggerDecorator.inner' ]
        autoconfigure: false

Then create you service class :

<?php

namespace App\Swagger;

use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

/**
 * Custom Swagger decorator to remove/edit some API documentation information.
 */
final class SwaggerDecorator implements NormalizerInterface
{

    /**
     * Decorated base Swagger normalizer.
     *
     * @var NormalizerInterface
     */
    protected NormalizerInterface $decorated;

    /**
     * SwaggerDecorator constructor.
     *
     * @param NormalizerInterface $decorated
     */
    public function __construct(NormalizerInterface $decorated)
    {
        $this->decorated = $decorated;
    }

    /**
     * {@inheritDoc}
     */
    public function normalize($object, string $format = null, array $context = [])
    {
        $docs = $this->decorated->normalize($object, $format, $context);
        $docs['components']['schemas']['authorization-authorization_code_login_write']['properties']['redirectionUrl']['example'] = 'https://example.com/my-dynamic-redirection';
        $docs['components']['schemas']['authorization:jsonld-authorization_code_login_write']['properties']['redirectionUrl']['example'] = 'https://example.com/my-dynamic-redirection';

        return $docs;
    }

    /**
     * {@inheritDoc}
     */
    public function supportsNormalization($data, string $format = null)
    {
        return $this->decorated->supportsNormalization($data, $format);
    }
}

You'll just have to find which keys to use, browsing the schemas can help on your Swagger UI. In my example, authorization is the short name of my API resource entity and authorization_code_login_write is the denormalization context value of the operation.

And here you go :

enter image description here

Of course, the ideal solution will iterate over all schemas and replace found configuration parameters with their real values. Maybe this feature could be done in API Platform itself (Follow issue : https://github.com/api-platform/api-platform/issues/1711)

Related