Skip to content

Add support for PATCH, refactor formats detection #2895

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

Merged
merged 22 commits into from
Jul 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Api/FormatsProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* {@inheritdoc}
*
* @author Anthony GRASSIOT <antograssiot@free.fr>
*
* @deprecated since API Platform 2.5, use the "formats" attribute instead
*/
final class FormatsProvider implements FormatsProviderInterface, OperationAwareFormatsProviderInterface
{
Expand All @@ -28,6 +30,8 @@ final class FormatsProvider implements FormatsProviderInterface, OperationAwareF

public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, array $configuredFormats)
{
@trigger_error(sprintf('The "%s" class is deprecated since API Platform 2.5, use the "formats" attribute instead.', __CLASS__), E_USER_DEPRECATED);

$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->configuredFormats = $configuredFormats;
}
Expand Down
2 changes: 2 additions & 0 deletions src/Api/FormatsProviderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* Extracts formats for a given operation according to the retrieved Metadata.
*
* @author Anthony GRASSIOT <antograssiot@free.fr>
*
* @deprecated since API Platform 2.5, use the "formats" attribute instead
*/
interface FormatsProviderInterface
{
Expand Down
2 changes: 2 additions & 0 deletions src/Api/OperationAwareFormatsProviderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* Extracts formats for a given operation according to the retrieved Metadata.
*
* @author Anthony GRASSIOT <antograssiot@free.fr>
*
* @deprecated since API Platform 2.5, use the "formats" attribute instead
*/
interface OperationAwareFormatsProviderInterface extends FormatsProviderInterface
{
Expand Down
2 changes: 2 additions & 0 deletions src/Api/OperationMethodResolverInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* Resolves the uppercased HTTP method associated with an operation.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*
* @deprecated since API Platform 2.5, use the "method" attribute instead
*/
interface OperationMethodResolverInterface
{
Expand Down
38 changes: 17 additions & 21 deletions src/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

use ApiPlatform\Core\Api\FormatsProviderInterface;
use ApiPlatform\Core\Documentation\Documentation;
use ApiPlatform\Core\Exception\InvalidArgumentException;
use ApiPlatform\Core\Exception\RuntimeException;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
Expand All @@ -42,7 +41,7 @@ final class SwaggerUiAction
private $description;
private $version;
private $showWebby;
private $formats = [];
private $formats;
private $oauthEnabled;
private $oauthClientId;
private $oauthClientSecret;
Expand All @@ -56,10 +55,7 @@ final class SwaggerUiAction
private $reDocEnabled;
private $graphqlEnabled;

/**
* @throws InvalidArgumentException
*/
public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, NormalizerInterface $normalizer, TwigEnvironment $twig, UrlGeneratorInterface $urlGenerator, string $title = '', string $description = '', string $version = '', /* FormatsProviderInterface */ $formatsProvider = [], $oauthEnabled = false, $oauthClientId = '', $oauthClientSecret = '', $oauthType = '', $oauthFlow = '', $oauthTokenUrl = '', $oauthAuthorizationUrl = '', $oauthScopes = [], bool $showWebby = true, bool $swaggerUiEnabled = false, bool $reDocEnabled = false, bool $graphqlEnabled = false)
public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, NormalizerInterface $normalizer, TwigEnvironment $twig, UrlGeneratorInterface $urlGenerator, string $title = '', string $description = '', string $version = '', $formats = [], $oauthEnabled = false, $oauthClientId = '', $oauthClientSecret = '', $oauthType = '', $oauthFlow = '', $oauthTokenUrl = '', $oauthAuthorizationUrl = '', $oauthScopes = [], bool $showWebby = true, bool $swaggerUiEnabled = false, bool $reDocEnabled = false, bool $graphqlEnabled = false)
{
$this->resourceNameCollectionFactory = $resourceNameCollectionFactory;
$this->resourceMetadataFactory = $resourceMetadataFactory;
Expand All @@ -82,32 +78,33 @@ public function __construct(ResourceNameCollectionFactoryInterface $resourceName
$this->reDocEnabled = $reDocEnabled;
$this->graphqlEnabled = $graphqlEnabled;

if (\is_array($formatsProvider)) {
if ($formatsProvider) {
// Only trigger notification for non-default argument
@trigger_error('Using an array as formats provider is deprecated since API Platform 2.3 and will not be possible anymore in API Platform 3', E_USER_DEPRECATED);
}
$this->formats = $formatsProvider;
if (\is_array($formats)) {
$this->formats = $formats;

return;
}
if (!$formatsProvider instanceof FormatsProviderInterface) {
throw new InvalidArgumentException(sprintf('The "$formatsProvider" argument is expected to be an implementation of the "%s" interface.', FormatsProviderInterface::class));
}

$this->formatsProvider = $formatsProvider;
@trigger_error(sprintf('Passing an array or an instance of "%s" as 5th parameter of the constructor of "%s" is deprecated since API Platform 2.5, pass an array instead', FormatsProviderInterface::class, __CLASS__), E_USER_DEPRECATED);
$this->formatsProvider = $formats;
}

public function __invoke(Request $request)
{
$attributes = RequestAttributesExtractor::extractAttributes($request);

// BC check to be removed in 3.0
if (null !== $this->formatsProvider) {
$this->formats = $this->formatsProvider->getFormatsFromAttributes(RequestAttributesExtractor::extractAttributes($request));
if (null === $this->formatsProvider) {
$formats = $attributes ? $this
->resourceMetadataFactory
->create($attributes['resource_class'])
->getOperationAttribute($attributes, 'output_formats', [], true) : $this->formats;
} else {
$formats = $this->formatsProvider->getFormatsFromAttributes($attributes);
}

$documentation = new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version, $this->formats);
$documentation = new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version);

return new Response($this->twig->render('@ApiPlatform/SwaggerUi/index.html.twig', $this->getContext($request, $documentation)));
return new Response($this->twig->render('@ApiPlatform/SwaggerUi/index.html.twig', $this->getContext($request, $documentation) + ['formats' => $formats]));
}

/**
Expand All @@ -118,7 +115,6 @@ private function getContext(Request $request, Documentation $documentation): arr
$context = [
'title' => $this->title,
'description' => $this->description,
'formats' => $this->formats,
'showWebby' => $this->showWebby,
'swaggerUiEnabled' => $this->swaggerUiEnabled,
'reDocEnabled' => $this->reDocEnabled,
Expand Down
6 changes: 5 additions & 1 deletion src/Bridge/Symfony/Bundle/Command/SwaggerCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final class SwaggerCommand extends Command
private $apiVersion;
private $apiFormats;

public function __construct(NormalizerInterface $normalizer, ResourceNameCollectionFactoryInterface $resourceNameCollection, string $apiTitle, string $apiDescription, string $apiVersion, array $apiFormats)
public function __construct(NormalizerInterface $normalizer, ResourceNameCollectionFactoryInterface $resourceNameCollection, string $apiTitle, string $apiDescription, string $apiVersion, array $apiFormats = null)
{
$this->normalizer = $normalizer;
$this->resourceNameCollectionFactory = $resourceNameCollection;
Expand All @@ -49,6 +49,10 @@ public function __construct(NormalizerInterface $normalizer, ResourceNameCollect
$this->apiVersion = $apiVersion;
$this->apiFormats = $apiFormats;

if (null !== $apiFormats) {
@trigger_error(sprintf('Passing a 6th parameter to the constructor of "%s" is deprecated since API Platform 2.5', __CLASS__), E_USER_DEPRECATED);
}

parent::__construct();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,15 @@ public function load(array $configs, ContainerBuilder $container): void
$config = $this->processConfiguration($configuration, $configs);

$formats = $this->getFormats($config['formats']);
$patchFormats = $this->getFormats($config['patch_formats']);
$errorFormats = $this->getFormats($config['error_formats']);

$this->registerCommonConfiguration($container, $config, $loader, $formats, $errorFormats);
// Backward Compatibility layer
if (isset($formats['jsonapi']) && !isset($patchFormats['jsonapi'])) {
Copy link
Contributor

@teohhanhui teohhanhui Jul 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really think we should deprecate specifying the format keys, and just use the mime type directly.

EDIT: Hmm... I see it's more complicated than that.

$patchFormats['jsonapi'] = ['application/vnd.api+json'];
}

$this->registerCommonConfiguration($container, $config, $loader, $formats, $patchFormats, $errorFormats);
$this->registerMetadataConfiguration($container, $config, $loader);
$this->registerOAuthConfiguration($container, $config);
$this->registerSwaggerConfiguration($container, $config, $loader);
Expand Down Expand Up @@ -127,7 +133,7 @@ public function load(array $configs, ContainerBuilder $container): void
}
}

private function registerCommonConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader, array $formats, array $errorFormats): void
private function registerCommonConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader, array $formats, array $patchFormats, array $errorFormats): void
{
$loader->load('api.xml');
$loader->load('data_persister.xml');
Expand All @@ -146,6 +152,7 @@ private function registerCommonConfiguration(ContainerBuilder $container, array
$container->setParameter('api_platform.show_webby', $config['show_webby']);
$container->setParameter('api_platform.exception_to_status', $config['exception_to_status']);
$container->setParameter('api_platform.formats', $formats);
$container->setParameter('api_platform.patch_formats', $patchFormats);
$container->setParameter('api_platform.error_formats', $errorFormats);
$container->setParameter('api_platform.allow_plain_identifiers', $config['allow_plain_identifiers']);
$container->setParameter('api_platform.eager_loading.enabled', $this->isConfigEnabled($container, $config['eager_loading']));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ public function getConfigTreeBuilder()
'json' => ['mime_types' => ['application/json']], // Swagger support
'html' => ['mime_types' => ['text/html']], // Swagger UI support
]);
$this->addFormatSection($rootNode, 'patch_formats', []);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem like a good default?

$this->addFormatSection($rootNode, 'error_formats', [
'jsonproblem' => ['mime_types' => ['application/problem+json']],
'jsonld' => ['mime_types' => ['application/ld+json']],
Expand Down
13 changes: 9 additions & 4 deletions src/Bridge/Symfony/Bundle/Resources/config/api.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<service id="api_platform.operation_method_resolver" class="ApiPlatform\Core\Bridge\Symfony\Routing\OperationMethodResolver" public="false">
<argument type="service" id="api_platform.router" />
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
<deprecated>The "%service_id%" service is deprecated since API Platform 2.5.</deprecated>
</service>

<service id="api_platform.route_name_resolver" class="ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameResolver" public="false">
Expand Down Expand Up @@ -68,13 +69,18 @@
<service id="api_platform.formats_provider" class="ApiPlatform\Core\Api\FormatsProvider">
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
<argument>%api_platform.formats%</argument>
<deprecated>The "%service_id%" service is deprecated since API Platform 2.5.</deprecated>
</service>

<service id="ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface" alias="api_platform.formats_provider">
<deprecated>The "%alias_id%" alias is deprecated since API Platform 2.5.</deprecated>
</service>
<service id="ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface" alias="api_platform.formats_provider" />

<!-- Serializer -->

<service id="api_platform.serializer.context_builder" class="ApiPlatform\Core\Serializer\SerializerContextBuilder" public="false">
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
<argument>%api_platform.patch_formats%</argument>
</service>
<service id="ApiPlatform\Core\Serializer\SerializerContextBuilderInterface" alias="api_platform.serializer.context_builder" />

Expand Down Expand Up @@ -150,7 +156,8 @@
<!-- kernel.request priority must be < 8 to be executed after the Firewall -->
<service id="api_platform.listener.request.add_format" class="ApiPlatform\Core\EventListener\AddFormatListener">
<argument type="service" id="api_platform.negotiator" />
<argument type="service" id="api_platform.formats_provider" />
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
<argument>%api_platform.formats%</argument>

<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="7" />
</service>
Expand All @@ -177,7 +184,6 @@
<service id="api_platform.listener.request.deserialize" class="ApiPlatform\Core\EventListener\DeserializeListener">
<argument type="service" id="api_platform.serializer" />
<argument type="service" id="api_platform.serializer.context_builder" />
<argument type="service" id="api_platform.formats_provider" />
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />

<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="2" />
Expand Down Expand Up @@ -231,7 +237,6 @@
<argument>%api_platform.title%</argument>
<argument>%api_platform.description%</argument>
<argument>%api_platform.version%</argument>
<argument type="service" id="api_platform.formats_provider" />
</service>

<service id="api_platform.action.exception" class="ApiPlatform\Core\Action\ExceptionAction" public="true">
Expand Down
2 changes: 1 addition & 1 deletion src/Bridge/Symfony/Bundle/Resources/config/hydra.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<argument type="service" id="api_platform.metadata.property.name_collection_factory" />
<argument type="service" id="api_platform.metadata.property.metadata_factory" />
<argument type="service" id="api_platform.resource_class_resolver" />
<argument type="service" id="api_platform.operation_method_resolver" />
<argument>null</argument>
<argument type="service" id="api_platform.router" />
<argument type="service" id="api_platform.subresource_operation_factory" />
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@

<service id="api_platform.metadata.resource.metadata_factory.operation" class="ApiPlatform\Core\Metadata\Resource\Factory\OperationResourceMetadataFactory" decorates="api_platform.metadata.resource.metadata_factory" decoration-priority="10" public="false">
<argument type="service" id="api_platform.metadata.resource.metadata_factory.operation.inner" />
<argument>%api_platform.patch_formats%</argument>
</service>

<service id="api_platform.metadata.resource.metadata_factory.formats" class="ApiPlatform\Core\Metadata\Resource\Factory\FormatsResourceMetadataFactory" decorates="api_platform.metadata.resource.metadata_factory" decoration-priority="5" public="false">
<argument type="service" id="api_platform.metadata.resource.metadata_factory.formats.inner" />
<argument>%api_platform.formats%</argument>
<argument>%api_platform.patch_formats%</argument>
</service>

<service id="api_platform.metadata.resource.metadata_factory.cached" class="ApiPlatform\Core\Metadata\Resource\Factory\CachedResourceMetadataFactory" decorates="api_platform.metadata.resource.metadata_factory" decoration-priority="-10" public="false">
Expand Down
2 changes: 1 addition & 1 deletion src/Bridge/Symfony/Bundle/Resources/config/swagger-ui.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<argument>%api_platform.title%</argument>
<argument>%api_platform.description%</argument>
<argument>%api_platform.version%</argument>
<argument type="service" id="api_platform.formats_provider" />
<argument>%api_platform.formats%</argument>
<argument>%api_platform.oauth.enabled%</argument>
<argument>%api_platform.oauth.clientId%</argument>
<argument>%api_platform.oauth.clientSecret%</argument>
Expand Down
5 changes: 2 additions & 3 deletions src/Bridge/Symfony/Bundle/Resources/config/swagger.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<argument type="service" id="api_platform.metadata.property.name_collection_factory" />
<argument type="service" id="api_platform.metadata.property.metadata_factory" />
<argument type="service" id="api_platform.resource_class_resolver" />
<argument type="service" id="api_platform.operation_method_resolver" />
<argument>null</argument>
<argument type="service" id="api_platform.operation_path_resolver" />
<argument>null</argument>
<argument type="service" id="api_platform.filter_locator" />
Expand All @@ -28,7 +28,7 @@
<argument>%api_platform.collection.pagination.page_parameter_name%</argument>
<argument>%api_platform.collection.pagination.client_items_per_page%</argument>
<argument>%api_platform.collection.pagination.items_per_page_parameter_name%</argument>
<argument type="service" id="api_platform.formats_provider" on-invalid="ignore" />
<argument>%api_platform.formats%</argument>
<argument>%api_platform.collection.pagination.client_enabled%</argument>
<argument>%api_platform.collection.pagination.enabled_parameter_name%</argument>
<tag name="serializer.normalizer" priority="-790" />
Expand All @@ -45,7 +45,6 @@
<argument>%api_platform.title%</argument>
<argument>%api_platform.description%</argument>
<argument>%api_platform.version%</argument>
<argument>%api_platform.formats%</argument>
<tag name="console.command" />
</service>

Expand Down
4 changes: 4 additions & 0 deletions src/Bridge/Symfony/Routing/ApiLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ private function addRoute(RouteCollection $routeCollection, string $resourceClas
$resourceShortName = $resourceMetadata->getShortName();

if (isset($operation['route_name'])) {
if (!isset($operation['method'])) {
@trigger_error(sprintf('Not setting the "method" attribute is deprecated and will not be supported anymore in API Platform 3.0, set it for the %s operation "%s" of the class "%s".', OperationType::COLLECTION === $operationType ? 'collection' : 'item', $operationName, $resourceClass), E_USER_DEPRECATED);
}

return;
}

Expand Down
4 changes: 4 additions & 0 deletions src/Bridge/Symfony/Routing/OperationMethodResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
*
* @author Kévin Dunglas <dunglas@gmail.com>
* @author Teoh Han Hui <teohhanhui@gmail.com>
*
* @deprecated since API Platform 2.5, use the "method" attribute instead
*/
final class OperationMethodResolver implements OperationMethodResolverInterface
{
Expand All @@ -33,6 +35,8 @@ final class OperationMethodResolver implements OperationMethodResolverInterface

public function __construct(RouterInterface $router, ResourceMetadataFactoryInterface $resourceMetadataFactory)
{
@trigger_error(sprintf('The "%s" class is deprecated since API Platform 2.5, use the "method" attribute instead.', __CLASS__), E_USER_DEPRECATED);

$this->router = $router;
$this->resourceMetadataFactory = $resourceMetadataFactory;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
* Resolves the HTTP method associated with an operation, extended for Symfony routing.
*
* @author Teoh Han Hui <teohhanhui@gmail.com>
*
* @deprecated since API Platform 2.5, use the "method" attribute instead
*/
interface OperationMethodResolverInterface extends BaseOperationMethodResolverInterface
{
Expand Down
Loading