Skip to content

Commit f880edd

Browse files
committed
fix(metadata): _format broken bc promise on #5080
1 parent 6e2f920 commit f880edd

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed

src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php

+13-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
*/
2828
final class UriTemplateResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface
2929
{
30+
private $triggerLegacyFormatOnce = [];
31+
3032
public function __construct(private readonly LinkFactoryInterface $linkFactory, private readonly PathSegmentNameGeneratorInterface $pathSegmentNameGenerator, private readonly ?ResourceMetadataCollectionFactoryInterface $decorated = null)
3133
{
3234
}
@@ -96,6 +98,15 @@ private function generateUriTemplate(HttpOperation $operation): string
9698
$uriTemplate = $operation->getUriTemplate() ?? sprintf('/%s', $this->pathSegmentNameGenerator->getSegmentName($operation->getShortName()));
9799
$uriVariables = $operation->getUriVariables() ?? [];
98100

101+
if (str_ends_with($uriTemplate, '{._format}') || ($legacyFormat = str_ends_with($uriTemplate, '.{_format}'))) {
102+
$uriTemplate = substr($uriTemplate, 0, -10);
103+
}
104+
105+
if ($legacyFormat && ($this->triggerLegacyFormatOnce[$operation->getClass()] ?? true)) {
106+
$this->triggerLegacyFormatOnce[$operation->getClass()] = false;
107+
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()));
108+
}
109+
99110
if ($parameters = array_keys($uriVariables)) {
100111
foreach ($parameters as $parameterName) {
101112
$part = sprintf('/{%s}', $parameterName);
@@ -105,7 +116,7 @@ private function generateUriTemplate(HttpOperation $operation): string
105116
}
106117
}
107118

108-
return sprintf('%s{._format}', $uriTemplate);
119+
return sprintf('%s%s', $uriTemplate, $legacyFormat ? '.{_format}' : '{._format}');
109120
}
110121

111122
private function configureUriVariables(ApiResource|HttpOperation $operation): ApiResource|HttpOperation
@@ -144,7 +155,7 @@ private function configureUriVariables(ApiResource|HttpOperation $operation): Ap
144155
}
145156
$operation = $operation->withUriVariables($uriVariables);
146157

147-
if (str_ends_with($uriTemplate, '{._format}')) {
158+
if (str_ends_with($uriTemplate, '{._format}') || str_ends_with($uriTemplate, '.{_format}')) {
148159
$uriTemplate = substr($uriTemplate, 0, -10);
149160
}
150161

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResourceNotLoaded;
15+
16+
use ApiPlatform\Metadata\ApiResource;
17+
18+
#[ApiResource('/format_not_rfc.{_format}')]
19+
class SymfonyFormatParameterLegacy
20+
{
21+
}

tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php

+25
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,26 @@
2323
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
2424
use ApiPlatform\Metadata\Property\PropertyNameCollection;
2525
use ApiPlatform\Metadata\Put;
26+
use ApiPlatform\Metadata\Resource\Factory\AttributesResourceMetadataCollectionFactory;
2627
use ApiPlatform\Metadata\Resource\Factory\LinkFactory;
2728
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
2829
use ApiPlatform\Metadata\Resource\Factory\UriTemplateResourceMetadataCollectionFactory;
2930
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
3031
use ApiPlatform\Operation\PathSegmentNameGeneratorInterface;
32+
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResourceNotLoaded\SymfonyFormatParameterLegacy;
3133
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource;
3234
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy;
3335
use PHPUnit\Framework\TestCase;
3436
use Prophecy\Argument;
3537
use Prophecy\PhpUnit\ProphecyTrait;
38+
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
3639

3740
/**
3841
* @author Antoine Bluchet <[email protected]>
3942
*/
4043
class UriTemplateResourceMetadataCollectionFactoryTest extends TestCase
4144
{
45+
use ExpectDeprecationTrait;
4246
use ProphecyTrait;
4347

4448
public function testCreate(): void
@@ -169,4 +173,25 @@ class: AttributeResource::class,
169173
$uriTemplateResourceMetadataCollectionFactory->create(AttributeResource::class)
170174
);
171175
}
176+
177+
/**
178+
* @group legacy
179+
*/
180+
public function testCreateWithLegacyFormat(): void
181+
{
182+
$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.');
183+
184+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
185+
$propertyNameCollectionFactoryProphecy->create(Argument::cetera())->willReturn(new PropertyNameCollection());
186+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
187+
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
188+
$linkFactory = new LinkFactory($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal());
189+
$pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class);
190+
$pathSegmentNameGeneratorProphecy->getSegmentName('SymfonyFormatParameterLegacy')->willReturn('attribute_resources');
191+
$resourceCollectionMetadataFactoryProphecy = new AttributesResourceMetadataCollectionFactory();
192+
193+
$linkFactory = new LinkFactory($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal());
194+
$uriTemplateResourceMetadataCollectionFactory = new UriTemplateResourceMetadataCollectionFactory($linkFactory, $pathSegmentNameGeneratorProphecy->reveal(), $resourceCollectionMetadataFactoryProphecy);
195+
$uriTemplateResourceMetadataCollectionFactory->create(SymfonyFormatParameterLegacy::class);
196+
}
172197
}

0 commit comments

Comments
 (0)