Skip to content

Commit

Permalink
fix(metadata): _format broken bc promise on #5080 (#5187)
Browse files Browse the repository at this point in the history
* fix(metadata): _format broken bc promise on #5080

* add deprecation contracts

* fix phpstan
  • Loading branch information
soyuka authored Nov 15, 2022
1 parent 148442c commit 45b5526
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 2 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"doctrine/inflector": "^1.0 || ^2.0",
"psr/cache": "^1.0 || ^2.0 || ^3.0",
"psr/container": "^1.0 || ^2.0",
"symfony/deprecation-contracts": "^3.1",
"symfony/http-foundation": "^6.1",
"symfony/http-kernel": "^6.1",
"symfony/property-access": "^6.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
*/
final class UriTemplateResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface
{
private $triggerLegacyFormatOnce = [];

public function __construct(private readonly LinkFactoryInterface $linkFactory, private readonly PathSegmentNameGeneratorInterface $pathSegmentNameGenerator, private readonly ?ResourceMetadataCollectionFactoryInterface $decorated = null)
{
}
Expand Down Expand Up @@ -95,6 +97,16 @@ private function generateUriTemplate(HttpOperation $operation): string
{
$uriTemplate = $operation->getUriTemplate() ?? sprintf('/%s', $this->pathSegmentNameGenerator->getSegmentName($operation->getShortName()));
$uriVariables = $operation->getUriVariables() ?? [];
$legacyFormat = null;

if (str_ends_with($uriTemplate, '{._format}') || ($legacyFormat = str_ends_with($uriTemplate, '.{_format}'))) {
$uriTemplate = substr($uriTemplate, 0, -10);
}

if ($legacyFormat && ($this->triggerLegacyFormatOnce[$operation->getClass()] ?? true)) {
$this->triggerLegacyFormatOnce[$operation->getClass()] = false;
trigger_deprecation('api-platform/core', '3.0', sprintf('The special Symfony parameter ".{_format}" in your URI Template is deprecated, use an RFC6570 variable "{._format}" on the class "%s" instead. We will only use the RFC6570 compatible variable in 4.0.', $operation->getClass()));
}

if ($parameters = array_keys($uriVariables)) {
foreach ($parameters as $parameterName) {
Expand All @@ -105,7 +117,7 @@ private function generateUriTemplate(HttpOperation $operation): string
}
}

return sprintf('%s{._format}', $uriTemplate);
return sprintf('%s%s', $uriTemplate, $legacyFormat ? '.{_format}' : '{._format}');
}

private function configureUriVariables(ApiResource|HttpOperation $operation): ApiResource|HttpOperation
Expand Down Expand Up @@ -144,7 +156,7 @@ private function configureUriVariables(ApiResource|HttpOperation $operation): Ap
}
$operation = $operation->withUriVariables($uriVariables);

if (str_ends_with($uriTemplate, '{._format}')) {
if (str_ends_with($uriTemplate, '{._format}') || str_ends_with($uriTemplate, '.{_format}')) {
$uriTemplate = substr($uriTemplate, 0, -10);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResourceNotLoaded;

use ApiPlatform\Metadata\ApiResource;

#[ApiResource('/format_not_rfc.{_format}')]
class SymfonyFormatParameterLegacy
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,26 @@
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
use ApiPlatform\Metadata\Property\PropertyNameCollection;
use ApiPlatform\Metadata\Put;
use ApiPlatform\Metadata\Resource\Factory\AttributesResourceMetadataCollectionFactory;
use ApiPlatform\Metadata\Resource\Factory\LinkFactory;
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
use ApiPlatform\Metadata\Resource\Factory\UriTemplateResourceMetadataCollectionFactory;
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
use ApiPlatform\Operation\PathSegmentNameGeneratorInterface;
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResourceNotLoaded\SymfonyFormatParameterLegacy;
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource;
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;

/**
* @author Antoine Bluchet <[email protected]>
*/
class UriTemplateResourceMetadataCollectionFactoryTest extends TestCase
{
use ExpectDeprecationTrait;
use ProphecyTrait;

public function testCreate(): void
Expand Down Expand Up @@ -169,4 +173,25 @@ class: AttributeResource::class,
$uriTemplateResourceMetadataCollectionFactory->create(AttributeResource::class)
);
}

/**
* @group legacy
*/
public function testCreateWithLegacyFormat(): void
{
$this->expectDeprecation('Since api-platform/core 3.0: The special Symfony parameter ".{_format}" in your URI Template is deprecated, use an RFC6570 variable "{._format}" on the class "ApiPlatform\Tests\Fixtures\TestBundle\ApiResourceNotLoaded\SymfonyFormatParameterLegacy" instead. We will only use the RFC6570 compatible variable in 4.0.');

$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
$propertyNameCollectionFactoryProphecy->create(Argument::cetera())->willReturn(new PropertyNameCollection());
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
$linkFactory = new LinkFactory($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal());
$pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class);
$pathSegmentNameGeneratorProphecy->getSegmentName('SymfonyFormatParameterLegacy')->willReturn('attribute_resources');
$resourceCollectionMetadataFactoryProphecy = new AttributesResourceMetadataCollectionFactory();

$linkFactory = new LinkFactory($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal());
$uriTemplateResourceMetadataCollectionFactory = new UriTemplateResourceMetadataCollectionFactory($linkFactory, $pathSegmentNameGeneratorProphecy->reveal(), $resourceCollectionMetadataFactoryProphecy);
$uriTemplateResourceMetadataCollectionFactory->create(SymfonyFormatParameterLegacy::class);
}
}

0 comments on commit 45b5526

Please sign in to comment.