From 4680724b6134f1414137c67f6dddbffb70fd9cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Chru=C5=9Bciel?= Date: Fri, 16 Sep 2022 11:23:07 +0200 Subject: [PATCH 01/17] fix(metadata): resource name collection missing deprecation (#4953) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(metadata): resource name collection missing deprecation * fix(metadata): [Minor] Removal of empty lines and adding class to exclusion Co-authored-by: Loïc Frémont --- phpstan.neon.dist | 1 + .../Resource/ResourceNameCollection.php | 22 +++++++++++++++++++ src/deprecation.php | 2 ++ 3 files changed, 25 insertions(+) create mode 100644 src/Core/Metadata/Resource/ResourceNameCollection.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index eae1ca0c827..b41b12b961a 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -178,6 +178,7 @@ parameters: - src/Core/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php - src/Core/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php - src/Core/Metadata/Property/PropertyNameCollection.php + - src/Core/Metadata/Resource/ResourceNameCollection.php - src/Core/OpenApi/Model/Components.php - src/Core/OpenApi/Model/Contact.php - src/Core/OpenApi/Model/Encoding.php diff --git a/src/Core/Metadata/Resource/ResourceNameCollection.php b/src/Core/Metadata/Resource/ResourceNameCollection.php new file mode 100644 index 00000000000..ee4ae7df636 --- /dev/null +++ b/src/Core/Metadata/Resource/ResourceNameCollection.php @@ -0,0 +1,22 @@ + + * + * 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\Core\Metadata\Resource; + +class_exists(\ApiPlatform\Metadata\Resource\ResourceNameCollection::class); + +if (false) { + final class ResourceNameCollection extends \ApiPlatform\Metadata\Resource\ResourceNameCollection + { + } +} diff --git a/src/deprecation.php b/src/deprecation.php index d809589016b..b129c5e1eb8 100644 --- a/src/deprecation.php +++ b/src/deprecation.php @@ -39,6 +39,8 @@ class_alias($interfaceName, $oldInterfaceName); ApiPlatform\Core\Metadata\Property\Factory\CachedPropertyNameCollectionFactory::class => ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory::class, ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory::class => ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory::class, + ApiPlatform\Core\Metadata\Resource\ResourceNameCollection::class => ApiPlatform\Metadata\Resource\ResourceNameCollection::class, + // Test cases ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase::class => ApiPlatform\Symfony\Bundle\Test\ApiTestCase::class, ApiPlatform\Core\Test\DoctrineMongoDbOdmFilterTestCase::class => ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase::class, From e3e81fb576e954a73fb86432bbf2422c6f73ac0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 16 Sep 2022 11:25:07 +0200 Subject: [PATCH 02/17] docs: minor changelog fixes (#4949) --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15ef6caba4c..6332c8d29c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -102,7 +102,7 @@ Doctrine: new interfaces for Filters and Extensions ready, switch to the `ApiPla * Swagger UI: Add `usePkceWithAuthorizationCodeGrant` to Swagger UI initOAuth (#4649) * **BC**: `mapping.paths` in configuration should override bundles configuration (#4465) -* GraphQL: Add ability to use different pagination types for the queries of a resource (#4453) +* GraphQL: Add the ability to use different pagination types for the queries of a resource (#4453) * Security: **BC** Fix `ApiProperty` `security` attribute expression being passed a class string for the `object` variable on updates/creates - null is now passed instead if the object is not available (#4184) * Security: `ApiProperty` now supports a `security_post_denormalize` attribute, which provides access to the `object` variable for the object being updated/created and `previous_object` for the object before it was updated (#4184) * Maker: Add `make:data-provider` and `make :data-persister` commands to generate a data provider / persister (#3850) @@ -136,7 +136,7 @@ Doctrine: new interfaces for Filters and Extensions ready, switch to the `ApiPla * Metadata: deprecation of `ApiPlatform\Core\Annotation` (#4351) * Metadata: `ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface` is deprecated in favor of `ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface` (#4351) * Metadata: item and collection prefixes for operations are deprecated, as well as the `ApiPlatform\Core\Api\OperationType` class (#4351) -* Graphql: `ApiPlatform\Metadata\GraphQl` follow the same metadata conventions (a Subscription operation is available and isn't hidden behind an update Mutation anymore), interfaces got simplified (beeing @experimental) (#4351) +* Graphql: `ApiPlatform\Metadata\GraphQl` follow the same metadata conventions (a Subscription operation is available and isn't hidden behind an update Mutation anymore), interfaces got simplified (being @experimental) (#4351) * IriConverter: new interface for `ApiPlatform\Bridge\Symfony\Routing\IriConverter` that adds an operationName, same for `ApiPlatform\Api\IdentifiersExtractor` (#4351) * DataProvider: new `ApiPlatform\State\ProviderInterface` that replaces DataProviders (#4351) * DataPersister: new `ApiPlatform\State\ProcessorInterface` that replaces DataPersisters (#4351) From 4092a8d87ce8ecfbc5c133cabb5af260e2be9620 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 16 Sep 2022 11:26:13 +0200 Subject: [PATCH 03/17] chore: drop dependency on fig/link-util (#4945) --- composer.json | 1 - src/Hydra/EventListener/AddLinkHeaderListener.php | 4 ++-- src/Symfony/EventListener/AddLinkHeaderListener.php | 4 ++-- src/Symfony/EventListener/SerializeListener.php | 4 ++-- tests/Hydra/EventListener/AddLinkHeaderListenerTest.php | 4 ++-- tests/Symfony/EventListener/AddLinkHeaderListenerTest.php | 4 ++-- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index a5ddcde857a..0d06269f253 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,6 @@ "require": { "php": ">=7.1", "doctrine/inflector": "^1.0 || ^2.0", - "fig/link-util": "^1.0", "psr/cache": "^1.0 || ^2.0 || ^3.0", "psr/container": "^1.0 || ^2.0", "symfony/http-foundation": "^4.4 || ^5.1 || ^6.0", diff --git a/src/Hydra/EventListener/AddLinkHeaderListener.php b/src/Hydra/EventListener/AddLinkHeaderListener.php index 18b100a3873..2c1d7f70e07 100644 --- a/src/Hydra/EventListener/AddLinkHeaderListener.php +++ b/src/Hydra/EventListener/AddLinkHeaderListener.php @@ -16,9 +16,9 @@ use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\JsonLd\ContextBuilder; use ApiPlatform\Util\CorsTrait; -use Fig\Link\GenericLinkProvider; -use Fig\Link\Link; use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\WebLink\GenericLinkProvider; +use Symfony\Component\WebLink\Link; /** * Adds the HTTP Link header pointing to the Hydra documentation. diff --git a/src/Symfony/EventListener/AddLinkHeaderListener.php b/src/Symfony/EventListener/AddLinkHeaderListener.php index 88f16c383ed..392a4e19c89 100644 --- a/src/Symfony/EventListener/AddLinkHeaderListener.php +++ b/src/Symfony/EventListener/AddLinkHeaderListener.php @@ -18,10 +18,10 @@ use ApiPlatform\Util\CorsTrait; use ApiPlatform\Util\OperationRequestInitiatorTrait; use ApiPlatform\Util\RequestAttributesExtractor; -use Fig\Link\GenericLinkProvider; -use Fig\Link\Link; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\Mercure\Discovery; +use Symfony\Component\WebLink\GenericLinkProvider; +use Symfony\Component\WebLink\Link; /** * Adds the HTTP Link header pointing to the Mercure hub for resources having their updates dispatched. diff --git a/src/Symfony/EventListener/SerializeListener.php b/src/Symfony/EventListener/SerializeListener.php index 00f7de69777..3c132b7f2cc 100644 --- a/src/Symfony/EventListener/SerializeListener.php +++ b/src/Symfony/EventListener/SerializeListener.php @@ -21,14 +21,14 @@ use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Util\OperationRequestInitiatorTrait; use ApiPlatform\Util\RequestAttributesExtractor; -use Fig\Link\GenericLinkProvider; -use Fig\Link\Link; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ViewEvent; use Symfony\Component\Serializer\Encoder\EncoderInterface; use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; use Symfony\Component\Serializer\SerializerInterface; +use Symfony\Component\WebLink\GenericLinkProvider; +use Symfony\Component\WebLink\Link; /** * Serializes data. diff --git a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php index 9f6b19ed729..0a22abe56e2 100644 --- a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php @@ -16,14 +16,14 @@ use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hydra\EventListener\AddLinkHeaderListener; -use Fig\Link\GenericLinkProvider; -use Fig\Link\Link; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\WebLink\GenericLinkProvider; use Symfony\Component\WebLink\HttpHeaderSerializer; +use Symfony\Component\WebLink\Link; /** * @author Kévin Dunglas diff --git a/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php b/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php index da39379cd59..869b89158a8 100644 --- a/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php @@ -18,8 +18,6 @@ use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\AddLinkHeaderListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Fig\Link\GenericLinkProvider; -use Fig\Link\Link; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -29,7 +27,9 @@ use Symfony\Component\Mercure\Hub; use Symfony\Component\Mercure\HubRegistry; use Symfony\Component\Mercure\Jwt\StaticTokenProvider; +use Symfony\Component\WebLink\GenericLinkProvider; use Symfony\Component\WebLink\HttpHeaderSerializer; +use Symfony\Component\WebLink\Link; /** * @author Kévin Dunglas From c037806b4f63521f9389fb38fa08e235fdb63f3e Mon Sep 17 00:00:00 2001 From: Ellis Benjamin Date: Sat, 17 Sep 2022 12:56:31 +0200 Subject: [PATCH 04/17] fix(symfony): missing Elasticsearch DocumentMetadataFactoryInterface alias definition (#4962) --- src/Symfony/Bundle/Resources/config/elasticsearch.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bundle/Resources/config/elasticsearch.xml b/src/Symfony/Bundle/Resources/config/elasticsearch.xml index 2bded5a314d..974d95b0427 100644 --- a/src/Symfony/Bundle/Resources/config/elasticsearch.xml +++ b/src/Symfony/Bundle/Resources/config/elasticsearch.xml @@ -19,6 +19,8 @@ + + %api_platform.elasticsearch.mapping% From d099dd6b02c8ffa86277b539bf85f34d8a2caf32 Mon Sep 17 00:00:00 2001 From: Emmanuel BALLERY Date: Sat, 17 Sep 2022 20:05:05 +0200 Subject: [PATCH 05/17] fix(symfony): upgrade command removes filters (#4970) --- src/Core/Upgrade/UpgradeApiFilterVisitor.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Core/Upgrade/UpgradeApiFilterVisitor.php b/src/Core/Upgrade/UpgradeApiFilterVisitor.php index ba820b1543c..6ed0e374a40 100644 --- a/src/Core/Upgrade/UpgradeApiFilterVisitor.php +++ b/src/Core/Upgrade/UpgradeApiFilterVisitor.php @@ -147,6 +147,7 @@ public function enterNode(Node $node) $reflection = $this->reflectionClass->getProperty($node->props[0]->name->__toString()); } + $filterAttributes = []; foreach ($this->readApiFilters($reflection) as $annotation) { [$filterAnnotation, $isAnnotation] = $annotation; if ($isAnnotation) { @@ -172,12 +173,14 @@ public function enterNode(Node $node) $arguments[$key] = $this->valueToNode($value); } - $node->attrGroups[] = new Node\AttributeGroup([ - new Node\Attribute( - new Node\Name('ApiFilter'), - $this->arrayToArguments($arguments), - ), - ]); + $filterAttributes[] = new Node\Attribute( + new Node\Name('ApiFilter'), + $this->arrayToArguments($arguments), + ); + } + + foreach ($filterAttributes as $filterAttribute) { + $node->attrGroups[] = new Node\AttributeGroup([$filterAttribute]); } } } From 11ed63d94e042f4244227b171537f8de4cce6ddd Mon Sep 17 00:00:00 2001 From: Antoine Bluchet Date: Sat, 17 Sep 2022 20:07:18 +0200 Subject: [PATCH 06/17] fix(symfony): upgrade command requires phpunit (#4968) fixes #4950 --- .../Bundle/Command/UpgradeApiResourceCommand.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php index d7d7c12cfb8..ca9bfb8ef34 100644 --- a/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php +++ b/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php @@ -89,6 +89,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::INVALID; } + if (!class_exists(NodeTraverser::class)) { + $output->writeln('Run `composer require --dev `nikic/php-parser` or install phpunit to use this command.'); + + return Command::FAILURE; + } + $subresources = $this->getSubresources(); $prettyPrinter = new Standard(); @@ -142,6 +148,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int continue; } + if (!class_exists(Differ::class)) { + $output->writeln('Run `composer require --dev sebastian/diff` or install phpunit to print a diff.'); + + return Command::FAILURE; + } + $this->printDiff($oldCode, $newCode, $output); continue; } From fc639ea9b0d095c79d749c72537848e6da464320 Mon Sep 17 00:00:00 2001 From: Vincent Date: Mon, 19 Sep 2022 14:45:58 +0200 Subject: [PATCH 07/17] fix(metadata): do not auto-generate NotExposed operation when using custom operation classes * fix(metadata): do not auto-generate NotExposed operation when using custom operation classes * Update src/Metadata/Resource/Factory/NotExposedOperationResourceMetadataCollectionFactory.php Co-authored-by: Antoine Bluchet --- ...ationResourceMetadataCollectionFactory.php | 3 +- tests/Fixtures/TestBundle/Metadata/Get.php | 28 +++++++++++ ...nResourceMetadataCollectionFactoryTest.php | 50 ++++++++++++++++++- 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 tests/Fixtures/TestBundle/Metadata/Get.php diff --git a/src/Metadata/Resource/Factory/NotExposedOperationResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/NotExposedOperationResourceMetadataCollectionFactory.php index 38e602c0300..e999b6598bf 100644 --- a/src/Metadata/Resource/Factory/NotExposedOperationResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/NotExposedOperationResourceMetadataCollectionFactory.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Metadata\Resource\Factory; use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\NotExposed; @@ -58,7 +59,7 @@ public function create(string $resourceClass): ResourceMetadataCollection foreach ($operations as $operation) { // An item operation has been found, nothing to do anymore in this factory - if ($operation instanceof Get || ($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false)) { + if ((HttpOperation::METHOD_GET === $operation->getMethod() && !$operation instanceof CollectionOperationInterface) || ($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false)) { return $resourceMetadataCollection; } } diff --git a/tests/Fixtures/TestBundle/Metadata/Get.php b/tests/Fixtures/TestBundle/Metadata/Get.php new file mode 100644 index 00000000000..1fa87c75366 --- /dev/null +++ b/tests/Fixtures/TestBundle/Metadata/Get.php @@ -0,0 +1,28 @@ + + * + * 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\Metadata; + +use ApiPlatform\Metadata\HttpOperation; + +#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] +final class Get extends HttpOperation +{ + /** + * {@inheritdoc} + */ + public function __construct(...$args) + { + parent::__construct(self::METHOD_GET, ...$args); + } +} diff --git a/tests/Metadata/Resource/Factory/NotExposedOperationResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/NotExposedOperationResourceMetadataCollectionFactoryTest.php index a2c59090926..89d17740bb0 100644 --- a/tests/Metadata/Resource/Factory/NotExposedOperationResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/NotExposedOperationResourceMetadataCollectionFactoryTest.php @@ -24,6 +24,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource; +use ApiPlatform\Tests\Fixtures\TestBundle\Metadata\Get as CustomGet; use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; @@ -68,8 +69,8 @@ class: AttributeResource::class new ApiResource( shortName: 'AttributeResource', operations: [ - '_api_AttributeResource_get' => new Get(uriVariables: ['id' => new Link(fromClass: AttributeResource::class, identifiers: ['id'])], controller: 'api_platform.action.placeholder', shortName: 'AttributeResource', class: AttributeResource::class), '_api_AttributeResource_get_collection' => new GetCollection(controller: 'api_platform.action.placeholder', shortName: 'AttributeResource', class: AttributeResource::class), + '_api_AttributeResource_get' => new Get(uriVariables: ['id' => new Link(fromClass: AttributeResource::class, identifiers: ['id'])], controller: 'api_platform.action.placeholder', shortName: 'AttributeResource', class: AttributeResource::class), ], uriVariables: ['id' => new Link(fromClass: AttributeResource::class, identifiers: ['id'])], class: AttributeResource::class @@ -88,8 +89,55 @@ class: AttributeResource::class new ApiResource( shortName: 'AttributeResource', operations: [ + '_api_AttributeResource_get_collection' => new GetCollection(controller: 'api_platform.action.placeholder', shortName: 'AttributeResource', class: AttributeResource::class), '_api_AttributeResource_get' => new Get(uriVariables: ['id' => new Link(fromClass: AttributeResource::class, identifiers: ['id'])], controller: 'api_platform.action.placeholder', shortName: 'AttributeResource', class: AttributeResource::class), + ], + uriVariables: ['id' => new Link(fromClass: AttributeResource::class, identifiers: ['id'])], + class: AttributeResource::class + ), + ]), + $factory->create(AttributeResource::class) + ); + } + + public function testItIgnoresResourcesWithAnItemOperationUsingCustomClass() + { + $linkFactoryProphecy = $this->prophesize(LinkFactoryInterface::class); + $linkFactoryProphecy->createLinksFromIdentifiers(Argument::type(HttpOperation::class))->shouldNotBeCalled(); + + $resourceCollectionMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceCollectionMetadataFactoryProphecy->create(AttributeResource::class)->willReturn( + new ResourceMetadataCollection(AttributeResource::class, [ + new ApiResource( + shortName: 'AttributeResource', + operations: [], + class: AttributeResource::class + ), + new ApiResource( + shortName: 'AttributeResource', + operations: [ + '_api_AttributeResource_get_collection' => new GetCollection(controller: 'api_platform.action.placeholder', shortName: 'AttributeResource', class: AttributeResource::class), + '_api_AttributeResource_get' => new CustomGet(uriVariables: ['id' => new Link(fromClass: AttributeResource::class, identifiers: ['id'])], controller: 'api_platform.action.placeholder', shortName: 'AttributeResource', class: AttributeResource::class), + ], + uriVariables: ['id' => new Link(fromClass: AttributeResource::class, identifiers: ['id'])], + class: AttributeResource::class + ), + ]), + ); + + $factory = new NotExposedOperationResourceMetadataCollectionFactory($linkFactoryProphecy->reveal(), $resourceCollectionMetadataFactoryProphecy->reveal()); + $this->assertEquals( + new ResourceMetadataCollection(AttributeResource::class, [ + new ApiResource( + shortName: 'AttributeResource', + operations: [], + class: AttributeResource::class + ), + new ApiResource( + shortName: 'AttributeResource', + operations: [ '_api_AttributeResource_get_collection' => new GetCollection(controller: 'api_platform.action.placeholder', shortName: 'AttributeResource', class: AttributeResource::class), + '_api_AttributeResource_get' => new CustomGet(uriVariables: ['id' => new Link(fromClass: AttributeResource::class, identifiers: ['id'])], controller: 'api_platform.action.placeholder', shortName: 'AttributeResource', class: AttributeResource::class), ], uriVariables: ['id' => new Link(fromClass: AttributeResource::class, identifiers: ['id'])], class: AttributeResource::class From b0730bb6c6565b5763e9c97ce97ef16cb2603636 Mon Sep 17 00:00:00 2001 From: Ellis Benjamin Date: Mon, 19 Sep 2022 17:27:24 +0200 Subject: [PATCH 08/17] =?UTF-8?q?fix(symfony):=20missing=20deprecations=20?= =?UTF-8?q?related=20to=20Ulid=20and=20Uuid=20normalize=E2=80=A6=20(#4963)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(symfony): missing deprecations related to Ulid and Uuid normalizers in constructors and dependency injection * fix(symfony): missing deprecations related to Ulid and Uuid normalizers in constructors and dependency injection * fix tests * test: expect deprecation Co-authored-by: soyuka --- .../Identifier/Normalizer/UuidNormalizer.php | 6 ++++++ .../Symfony/Identifier/Normalizer/UlidNormalizer.php | 6 ++++++ .../Symfony/Identifier/Normalizer/UuidNormalizer.php | 6 ++++++ .../DependencyInjection/ApiPlatformExtension.php | 12 ++++++++++++ .../Identifier/Normalizer/UuidNormalizerTest.php | 10 ++++++++++ .../Identifier/Normalizer/UlidNormalizerTest.php | 10 ++++++++++ .../Identifier/Normalizer/UuidNormalizerTest.php | 11 +++++++++++ 7 files changed, 61 insertions(+) diff --git a/src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php b/src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php index 66ae9012522..a5f7f6c4ee2 100644 --- a/src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php +++ b/src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Bridge\RamseyUuid\Identifier\Normalizer; use ApiPlatform\Exception\InvalidIdentifierException; +use ApiPlatform\RamseyUuid\UriVariableTransformer\UuidUriVariableTransformer; use Ramsey\Uuid\Exception\InvalidUuidStringException; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; @@ -26,6 +27,11 @@ */ final class UuidNormalizer implements DenormalizerInterface { + public function __construct() + { + trigger_deprecation('api-platform/core', '2.7', sprintf('The class "%s" will be replaced by "%s".', self::class, UuidUriVariableTransformer::class)); + } + /** * {@inheritdoc} * diff --git a/src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php b/src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php index 85367d5e7fe..b6a771af6ad 100644 --- a/src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php +++ b/src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer; use ApiPlatform\Exception\InvalidIdentifierException; +use ApiPlatform\Symfony\UriVariableTransformer\UlidUriVariableTransformer; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Uid\Ulid; @@ -22,6 +23,11 @@ */ final class UlidNormalizer implements DenormalizerInterface { + public function __construct() + { + trigger_deprecation('api-platform/core', '2.7', sprintf('The class "%s" will be replaced by "%s".', self::class, UlidUriVariableTransformer::class)); + } + /** * {@inheritdoc} * diff --git a/src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php b/src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php index f84ded89bf0..211d98ba300 100644 --- a/src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php +++ b/src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer; use ApiPlatform\Exception\InvalidIdentifierException; +use ApiPlatform\Symfony\UriVariableTransformer\UuidUriVariableTransformer; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Uid\Uuid; @@ -22,6 +23,11 @@ */ final class UuidNormalizer implements DenormalizerInterface { + public function __construct() + { + trigger_deprecation('api-platform/core', '2.7', sprintf('The class "%s" will be replaced by "%s".', self::class, UuidUriVariableTransformer::class)); + } + /** * {@inheritdoc} * diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 7a4aab08971..6eeef3281c0 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -201,10 +201,22 @@ private function registerCommonConfiguration(ContainerBuilder $container, array if (class_exists(Uuid::class)) { $loader->load('ramsey_uuid.xml'); + if ($container->hasDefinition('api_platform.identifier.uuid_normalizer')) { + $container->getDefinition('api_platform.identifier.uuid_normalizer') + ->setDeprecated(...$this->buildDeprecationArgs('2.7', 'The "%service_id%" service is deprecated since 2.7 and will be removed in 3.0. Use the "api_platform.ramsey_uuid.uri_variables.transformer.uuid" service instead.')); + } } if (class_exists(AbstractUid::class)) { $loader->load('symfony_uid.xml'); + if ($container->hasDefinition('api_platform.identifier.symfony_ulid_normalizer')) { + $container->getDefinition('api_platform.identifier.symfony_ulid_normalizer') + ->setDeprecated(...$this->buildDeprecationArgs('2.7', 'The "%service_id%" service is deprecated since 2.7 and will be removed in 3.0. Use the "api_platform.symfony.uri_variables.transformer.ulid" service instead.')); + } + if ($container->hasDefinition('api_platform.identifier.symfony_uuid_normalizer')) { + $container->getDefinition('api_platform.identifier.symfony_uuid_normalizer') + ->setDeprecated(...$this->buildDeprecationArgs('2.7', 'The "%service_id%" service is deprecated since 2.7 and will be removed in 3.0. Use the "api_platform.symfony.uri_variables.transformer.uuid" service instead.')); + } } $container->setParameter('api_platform.metadata_backward_compatibility_layer', $config['metadata_backward_compatibility_layer']); diff --git a/tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php b/tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php index 3cd3cf99136..f0d43c58f69 100644 --- a/tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php +++ b/tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php @@ -17,11 +17,18 @@ use ApiPlatform\Exception\InvalidIdentifierException; use PHPUnit\Framework\TestCase; use Ramsey\Uuid\Uuid; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; +/** + * @group legacy + */ class UuidNormalizerTest extends TestCase { + use ExpectDeprecationTrait; + public function testDenormalizeUuid() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\RamseyUuid\Identifier\Normalizer\UuidNormalizer" will be replaced by "ApiPlatform\RamseyUuid\UriVariableTransformer\UuidUriVariableTransformer".'); $uuid = Uuid::uuid4(); $normalizer = new UuidNormalizer(); $this->assertTrue($normalizer->supportsDenormalization($uuid->toString(), Uuid::class)); @@ -30,6 +37,7 @@ public function testDenormalizeUuid() public function testNoSupportDenormalizeUuid() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\RamseyUuid\Identifier\Normalizer\UuidNormalizer" will be replaced by "ApiPlatform\RamseyUuid\UriVariableTransformer\UuidUriVariableTransformer".'); $uuid = 'notanuuid'; $normalizer = new UuidNormalizer(); $this->assertFalse($normalizer->supportsDenormalization($uuid, '')); @@ -37,6 +45,7 @@ public function testNoSupportDenormalizeUuid() public function testFailDenormalizeUuid() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\RamseyUuid\Identifier\Normalizer\UuidNormalizer" will be replaced by "ApiPlatform\RamseyUuid\UriVariableTransformer\UuidUriVariableTransformer".'); $this->expectException(InvalidIdentifierException::class); $uuid = 'notanuuid'; @@ -47,6 +56,7 @@ public function testFailDenormalizeUuid() public function testDoNotSupportNotString() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\RamseyUuid\Identifier\Normalizer\UuidNormalizer" will be replaced by "ApiPlatform\RamseyUuid\UriVariableTransformer\UuidUriVariableTransformer".'); $uuid = Uuid::uuid4(); $normalizer = new UuidNormalizer(); $this->assertFalse($normalizer->supportsDenormalization($uuid, Uuid::class)); diff --git a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php b/tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php index 170fab26d65..24e466dfb07 100644 --- a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php +++ b/tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php @@ -16,11 +16,17 @@ use ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UlidNormalizer; use ApiPlatform\Exception\InvalidIdentifierException; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Uid\AbstractUid; use Symfony\Component\Uid\Ulid; +/** + * @group legacy + */ final class UlidNormalizerTest extends TestCase { + use ExpectDeprecationTrait; + protected function setUp(): void { if (!class_exists(AbstractUid::class)) { @@ -30,6 +36,7 @@ protected function setUp(): void public function testDenormalizeUlid() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UlidNormalizer" will be replaced by "ApiPlatform\Symfony\UriVariableTransformer\UlidUriVariableTransformer".'); $ulid = new Ulid(); $normalizer = new UlidNormalizer(); $this->assertTrue($normalizer->supportsDenormalization($ulid->__toString(), Ulid::class)); @@ -38,6 +45,7 @@ public function testDenormalizeUlid() public function testNoSupportDenormalizeUlid() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UlidNormalizer" will be replaced by "ApiPlatform\Symfony\UriVariableTransformer\UlidUriVariableTransformer".'); $ulid = 'notanulid'; $normalizer = new UlidNormalizer(); $this->assertFalse($normalizer->supportsDenormalization($ulid, '')); @@ -45,6 +53,7 @@ public function testNoSupportDenormalizeUlid() public function testFailDenormalizeUlid() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UlidNormalizer" will be replaced by "ApiPlatform\Symfony\UriVariableTransformer\UlidUriVariableTransformer".'); $this->expectException(InvalidIdentifierException::class); $ulid = 'notanulid'; @@ -55,6 +64,7 @@ public function testFailDenormalizeUlid() public function testDoNotSupportNotString() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UlidNormalizer" will be replaced by "ApiPlatform\Symfony\UriVariableTransformer\UlidUriVariableTransformer".'); $ulid = new Ulid(); $normalizer = new UlidNormalizer(); $this->assertFalse($normalizer->supportsDenormalization($ulid, Ulid::class)); diff --git a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php b/tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php index 32c124a72ad..0f1278cf05f 100644 --- a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php +++ b/tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php @@ -16,11 +16,17 @@ use ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UuidNormalizer; use ApiPlatform\Exception\InvalidIdentifierException; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Uid\AbstractUid; use Symfony\Component\Uid\Uuid; +/** + * @group legacy + */ final class UuidNormalizerTest extends TestCase { + use ExpectDeprecationTrait; + protected function setUp(): void { if (!class_exists(AbstractUid::class)) { @@ -30,6 +36,8 @@ protected function setUp(): void public function testDenormalizeUuid() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UuidNormalizer" will be replaced by "ApiPlatform\Symfony\UriVariableTransformer\UuidUriVariableTransformer".'); + $uuid = Uuid::v4(); $normalizer = new UuidNormalizer(); $this->assertTrue($normalizer->supportsDenormalization($uuid->__toString(), Uuid::class)); @@ -38,6 +46,7 @@ public function testDenormalizeUuid() public function testNoSupportDenormalizeUuid() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UuidNormalizer" will be replaced by "ApiPlatform\Symfony\UriVariableTransformer\UuidUriVariableTransformer".'); $uuid = 'notanuuid'; $normalizer = new UuidNormalizer(); $this->assertFalse($normalizer->supportsDenormalization($uuid, '')); @@ -45,6 +54,7 @@ public function testNoSupportDenormalizeUuid() public function testFailDenormalizeUuid() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UuidNormalizer" will be replaced by "ApiPlatform\Symfony\UriVariableTransformer\UuidUriVariableTransformer".'); $this->expectException(InvalidIdentifierException::class); $uuid = 'notanuuid'; @@ -55,6 +65,7 @@ public function testFailDenormalizeUuid() public function testDoNotSupportNotString() { + $this->expectDeprecation('Since api-platform/core 2.7: The class "ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UuidNormalizer" will be replaced by "ApiPlatform\Symfony\UriVariableTransformer\UuidUriVariableTransformer".'); $uuid = Uuid::v4(); $normalizer = new UuidNormalizer(); $this->assertFalse($normalizer->supportsDenormalization($uuid, Uuid::class)); From 8691fdf63454e9fe4d8d3adf893784bc604c1ff7 Mon Sep 17 00:00:00 2001 From: Antoine Bluchet Date: Tue, 20 Sep 2022 11:06:12 +0200 Subject: [PATCH 09/17] chore: commitlint only the Pull Request HEAD (#4983) we only want the first commit to be linted --- .commitlintrc | 2 +- .github/workflows/ci.yml | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.commitlintrc b/.commitlintrc index b9be7d6dc13..acfdca37b54 100644 --- a/.commitlintrc +++ b/.commitlintrc @@ -1,6 +1,6 @@ { "defaultIgnores": true, - "parserPreset": "conventional-changelog-conventionalcommits", + "extends": "@commitlint/config-conventional", "rules": { "scope-enum": [ 2, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1041bb6bc3c..6477fb5bf28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,13 +11,24 @@ env: jobs: commitlint: + if: github.event_name == 'pull_request' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - configFile: .commitlintrc - - uses: wagoid/commitlint-github-action@v5 + - name: Run commitlint + run: | + commit=$(gh api \ + -H "Accept: application/vnd.github+json" \ + /repos/${{ github.repository }}/pulls/${{github.event.number}}/commits \ + | jq -r '.[0].commit.message') + # we can't use npx see https://github.com/conventional-changelog/commitlint/issues/613 + echo '{}' > package.json + npm install --no-fund --no-audit @commitlint/config-conventional @commitlint/cli + echo $commit | ./node_modules/.bin/commitlint -g .commitlintrc php-cs-fixer: name: PHP-cs-fixer (PHP ${{ matrix.php }}) runs-on: ubuntu-latest From 693b03afc1400b7c32b941dfcaf3112c5f1a7c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20de=20Guillebon?= Date: Fri, 23 Sep 2022 17:27:19 +0200 Subject: [PATCH 10/17] fix(symfony): bc layer broken for symfony/console lower than 5.3 (#4990) --- .../Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php index ca9bfb8ef34..95b56a0951e 100644 --- a/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php +++ b/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php @@ -73,7 +73,7 @@ protected function configure() ->setDescription('The "api:upgrade-resource" command upgrades your API Platform metadata from versions below 2.6 to the new metadata from versions above 2.7. Once you executed this script, make sure that the "metadata_backward_compatibility_layer" flag is set to "false" in the API Platform configuration. This will remove "ApiPlatform\Core\Annotation\ApiResource" annotation/attribute and use the "ApiPlatform\Metadata\ApiResource" attribute instead.') - ->addOption('dry-run', '-d', InputOption::VALUE_NEGATABLE, 'Dry mode outputs a diff instead of writing files.', true) + ->addOption('dry-run', '-d', InputOption::VALUE_NONE, 'Dry mode outputs a diff instead of writing files.') ->addOption('silent', '-s', InputOption::VALUE_NONE, 'Silent output.') ->addOption('force', '-f', InputOption::VALUE_NONE, 'Writes the files in place and skips PHP version check.'); } From d26538787192c5a169aeb89dbbe0dd055dfba150 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Tue, 27 Sep 2022 16:32:13 +0200 Subject: [PATCH 11/17] chore: add conflict on elasticsearch >= 8.0 (#5018) --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0d06269f253..0d7cac87381 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,8 @@ "doctrine/common": "<2.7", "doctrine/dbal": "<2.10", "doctrine/mongodb-odm": "<2.2", - "doctrine/persistence": "<1.3" + "doctrine/persistence": "<1.3", + "elasticsearch/elasticsearch": ">=8.0" }, "suggest": { "doctrine/mongodb-odm-bundle": "To support MongoDB. Only versions 4.0 and later are supported.", From 4ca639ccc5b64cc36251ebd76be2db6417d59e32 Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Tue, 27 Sep 2022 16:32:28 +0200 Subject: [PATCH 12/17] fix(symfony): add missing dependency on symfony/deprecation-contracts (#5015) --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 0d7cac87381..dc449da81ca 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "doctrine/inflector": "^1.0 || ^2.0", "psr/cache": "^1.0 || ^2.0 || ^3.0", "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", "symfony/http-foundation": "^4.4 || ^5.1 || ^6.0", "symfony/http-kernel": "^4.4 || ^5.1 || ^6.0", "symfony/property-access": "^3.4.19 || ^4.4 || ^5.1 || ^6.0", From 44ba110b97e9d6f4e244df182a81712dd88f1e99 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Wed, 28 Sep 2022 17:35:10 +0200 Subject: [PATCH 13/17] fix: replace FQCN service names by snake ones (#5019) --- CHANGELOG.md | 4 ++ .../Resources/config/doctrine_mongodb_odm.xml | 16 +++---- .../Bundle/Resources/config/doctrine_orm.xml | 10 +++-- .../Resources/config/v3/doctrine_odm.xml | 10 +++-- .../Resources/config/v3/doctrine_orm.xml | 10 +++-- .../Bundle/Resources/config/v3/state.xml | 4 +- .../ApiPlatformExtensionTest.php | 45 +++++++++++-------- 7 files changed, 56 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6332c8d29c7..4981c8766f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 2.7.1 + +* Replace FQCN service names by snake ones (#5019) + ## 2.7.0 * chore: remove @experimental phpdoc (#4933) diff --git a/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml b/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml index 5fa345f4c85..037ee945b5e 100644 --- a/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml +++ b/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml @@ -25,23 +25,19 @@ - + - + + - + - - - - - - - + + diff --git a/src/Symfony/Bundle/Resources/config/doctrine_orm.xml b/src/Symfony/Bundle/Resources/config/doctrine_orm.xml index 2479d53ad20..bb71a354e5e 100644 --- a/src/Symfony/Bundle/Resources/config/doctrine_orm.xml +++ b/src/Symfony/Bundle/Resources/config/doctrine_orm.xml @@ -9,17 +9,19 @@ - + - + + - + - + + diff --git a/src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml b/src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml index 5986aeeffea..ace96525184 100644 --- a/src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml +++ b/src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml @@ -14,21 +14,23 @@ - + - + + - + - + + diff --git a/src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml b/src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml index fd47b013977..a87fb02eae1 100644 --- a/src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml +++ b/src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml @@ -13,21 +13,23 @@ - + - + + - + - + + diff --git a/src/Symfony/Bundle/Resources/config/v3/state.xml b/src/Symfony/Bundle/Resources/config/v3/state.xml index 6c47d09af37..ea60a54c38a 100644 --- a/src/Symfony/Bundle/Resources/config/v3/state.xml +++ b/src/Symfony/Bundle/Resources/config/v3/state.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + @@ -17,7 +17,7 @@ - + diff --git a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index b99de451c89..c14a7a17394 100644 --- a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -1135,10 +1135,10 @@ public function testDoctrineOrmConfiguration(): void $services = [ // doctrine_orm.xml 'api_platform.doctrine.metadata_factory', - RemoveProcessor::class, - PersistProcessor::class, - CollectionProvider::class, - ItemProvider::class, + 'api_platform.doctrine.orm.state.remove_processor', + 'api_platform.doctrine.orm.state.persist_processor', + 'api_platform.doctrine.orm.state.collection_provider', + 'api_platform.doctrine.orm.state.item_provider', 'api_platform.doctrine.orm.search_filter', 'api_platform.doctrine.orm.order_filter', 'api_platform.doctrine.orm.range_filter', @@ -1161,6 +1161,10 @@ public function testDoctrineOrmConfiguration(): void $aliases = [ // doctrine_orm.xml + RemoveProcessor::class, + PersistProcessor::class, + CollectionProvider::class, + ItemProvider::class, 'ApiPlatform\Doctrine\Orm\Filter\OrderFilter', 'ApiPlatform\Doctrine\Orm\Filter\RangeFilter', 'ApiPlatform\Doctrine\Orm\Filter\DateFilter', @@ -1177,10 +1181,10 @@ public function testDoctrineOrmConfiguration(): void $this->assertContainerHas($services, $aliases); // doctrine_orm.xml - $this->assertServiceHasTags(RemoveProcessor::class, ['api_platform.state_processor']); - $this->assertServiceHasTags(PersistProcessor::class, ['api_platform.state_processor']); - $this->assertServiceHasTags(CollectionProvider::class, ['api_platform.state_provider']); - $this->assertServiceHasTags(ItemProvider::class, ['api_platform.state_provider']); + $this->assertServiceHasTags('api_platform.doctrine.orm.state.remove_processor', ['api_platform.state_processor']); + $this->assertServiceHasTags('api_platform.doctrine.orm.state.persist_processor', ['api_platform.state_processor']); + $this->assertServiceHasTags('api_platform.doctrine.orm.state.collection_provider', ['api_platform.state_provider']); + $this->assertServiceHasTags('api_platform.doctrine.orm.state.item_provider', ['api_platform.state_provider']); $this->assertServiceHasTags('api_platform.doctrine.orm.query_extension.eager_loading', ['api_platform.doctrine.orm.query_extension.item', 'api_platform.doctrine.orm.query_extension.collection']); $this->assertServiceHasTags('api_platform.doctrine.orm.query_extension.filter', ['api_platform.doctrine.orm.query_extension.collection']); $this->assertServiceHasTags('api_platform.doctrine.orm.query_extension.filter_eager_loading', ['api_platform.doctrine.orm.query_extension.collection']); @@ -1201,13 +1205,13 @@ public function testDoctrineMongoDbOdmConfiguration(): void (new ApiPlatformExtension())->load($config, $this->container); $services = [ - // doctrine_mongo_odm.xml + // doctrine_mongodb_odm.xml 'api_platform.doctrine_mongodb.odm.default_document_manager.property_info_extractor', 'api_platform.doctrine.metadata_factory', - RemoveProcessor::class, - PersistProcessor::class, - MongoDbCollectionProvider::class, - MongoDbItemProvider::class, + 'api_platform.doctrine_mongodb.odm.state.remove_processor', + 'api_platform.doctrine_mongodb.odm.state.persist_processor', + 'api_platform.doctrine_mongodb.odm.state.collection_provider', + 'api_platform.doctrine_mongodb.odm.state.item_provider', 'api_platform.doctrine_mongodb.odm.search_filter', 'api_platform.doctrine_mongodb.odm.boolean_filter', 'api_platform.doctrine_mongodb.odm.date_filter', @@ -1232,7 +1236,11 @@ public function testDoctrineMongoDbOdmConfiguration(): void ]; $aliases = [ - // doctrine_mongo_odm.xml + // doctrine_mongodb_odm.xml + RemoveProcessor::class, + PersistProcessor::class, + MongoDbCollectionProvider::class, + MongoDbItemProvider::class, 'ApiPlatform\Doctrine\Odm\Filter\SearchFilter', 'ApiPlatform\Doctrine\Odm\Filter\BooleanFilter', 'ApiPlatform\Doctrine\Odm\Filter\DateFilter', @@ -1247,11 +1255,10 @@ public function testDoctrineMongoDbOdmConfiguration(): void $this->assertContainerHas($services, $aliases); - $this->assertServiceHasTags(RemoveProcessor::class, ['api_platform.state_processor']); - $this->assertServiceHasTags(PersistProcessor::class, ['api_platform.state_processor']); - $this->assertServiceHasTags(MongoDbCollectionProvider::class, ['api_platform.state_provider']); - $this->assertServiceHasTags(MongoDbItemProvider::class, ['api_platform.state_provider']); - // doctrine_mongo_odm.xml + $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.state.remove_processor', ['api_platform.state_processor']); + $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.state.persist_processor', ['api_platform.state_processor']); + $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.state.collection_provider', ['api_platform.state_provider']); + $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.state.item_provider', ['api_platform.state_provider']); $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.default_document_manager.property_info_extractor', ['property_info.list_extractor', 'property_info.type_extractor']); $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.aggregation_extension.filter', ['api_platform.doctrine_mongodb.odm.aggregation_extension.collection']); $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.aggregation_extension.pagination', ['api_platform.doctrine_mongodb.odm.aggregation_extension.collection']); From 603551a7537d446db1fde49a153fb1edc140b98c Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 29 Sep 2022 09:58:37 +0200 Subject: [PATCH 14/17] fix(metadata): fix missing `array` cast for RDF types in `ApiResource` & `ApiProperty` constructors (#5000) --- src/Metadata/ApiProperty.php | 4 +- src/Metadata/ApiResource.php | 89 +++++++++++++++++++----------------- 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/src/Metadata/ApiProperty.php b/src/Metadata/ApiProperty.php index f614b0c46e5..a9641a931c1 100644 --- a/src/Metadata/ApiProperty.php +++ b/src/Metadata/ApiProperty.php @@ -79,7 +79,7 @@ final class ApiProperty private $securityPostDenormalize; /** - * @var string[] + * @var string|string[]|null */ private $types; @@ -171,7 +171,7 @@ public function __construct( $this->security = $security; $this->openapiContext = $openapiContext; $this->securityPostDenormalize = $securityPostDenormalize; - $this->types = $types; + $this->types = null === $types ? null : (array) $types; $this->builtinTypes = $builtinTypes; $this->schema = $schema; $this->initializable = $initializable; diff --git a/src/Metadata/ApiResource.php b/src/Metadata/ApiResource.php index 436bbc0d958..012f7a66d76 100644 --- a/src/Metadata/ApiResource.php +++ b/src/Metadata/ApiResource.php @@ -29,6 +29,9 @@ class ApiResource protected $uriTemplate; protected $shortName; protected $description; + /** + * @var string|string[]|null + */ protected $types; /** * @var array|mixed|string|null @@ -121,48 +124,48 @@ class ApiResource protected $extraProperties; /** - * @param array|null $types The RDF types of this resource - * @param mixed|null $operations - * @param array|string|null $formats https://api-platform.com/docs/core/content-negotiation/#configuring-formats-for-a-specific-resource-or-operation - * @param array|string|null $inputFormats https://api-platform.com/docs/core/content-negotiation/#configuring-formats-for-a-specific-resource-or-operation - * @param array|string|null $outputFormats https://api-platform.com/docs/core/content-negotiation/#configuring-formats-for-a-specific-resource-or-operation - * @param mixed|null $uriVariables - * @param string|null $routePrefix https://api-platform.com/docs/core/operations/#prefixing-all-routes-of-all-operations - * @param string|null $sunset https://api-platform.com/docs/core/deprecations/#setting-the-sunset-http-header-to-indicate-when-a-resource-or-an-operation-will-be-removed - * @param string|null $deprecationReason https://api-platform.com/docs/core/deprecations/#deprecating-resource-classes-operations-and-properties - * @param array|null $cacheHeaders https://api-platform.com/docs/core/performance/#setting-custom-http-cache-headers - * @param array|null $normalizationContext https://api-platform.com/docs/core/serialization/#using-serialization-groups - * @param array|null $denormalizationContext https://api-platform.com/docs/core/serialization/#using-serialization-groups - * @param string[]|null $hydraContext https://api-platform.com/docs/core/extending-jsonld-context/#hydra - * @param array|null $openapiContext https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts - * @param array|null $validationContext https://api-platform.com/docs/core/validation/#using-validation-groups - * @param string[]|null $filters https://api-platform.com/docs/core/filters/#doctrine-orm-and-mongodb-odm-filters - * @param bool|null $elasticsearch https://api-platform.com/docs/core/elasticsearch/ - * @param mixed|null $mercure https://api-platform.com/docs/core/mercure - * @param mixed|null $messenger https://api-platform.com/docs/core/messenger/#dispatching-a-resource-through-the-message-bus - * @param mixed|null $input https://api-platform.com/docs/core/dto/#specifying-an-input-or-an-output-data-representation - * @param mixed|null $output https://api-platform.com/docs/core/dto/#specifying-an-input-or-an-output-data-representation - * @param array|null $order https://api-platform.com/docs/core/default-order/#overriding-default-order - * @param bool|null $fetchPartial https://api-platform.com/docs/core/performance/#fetch-partial - * @param bool|null $forceEager https://api-platform.com/docs/core/performance/#force-eager - * @param bool|null $paginationClientEnabled https://api-platform.com/docs/core/pagination/#for-a-specific-resource-1 - * @param bool|null $paginationClientItemsPerPage https://api-platform.com/docs/core/pagination/#for-a-specific-resource-3 - * @param bool|null $paginationClientPartial https://api-platform.com/docs/core/pagination/#for-a-specific-resource-6 - * @param array|null $paginationViaCursor https://api-platform.com/docs/core/pagination/#cursor-based-pagination - * @param bool|null $paginationEnabled https://api-platform.com/docs/core/pagination/#for-a-specific-resource - * @param bool|null $paginationFetchJoinCollection https://api-platform.com/docs/core/pagination/#controlling-the-behavior-of-the-doctrine-orm-paginator - * @param int|null $paginationItemsPerPage https://api-platform.com/docs/core/pagination/#changing-the-number-of-items-per-page - * @param int|null $paginationMaximumItemsPerPage https://api-platform.com/docs/core/pagination/#changing-maximum-items-per-page - * @param bool|null $paginationPartial https://api-platform.com/docs/core/performance/#partial-pagination - * @param string|null $paginationType https://api-platform.com/docs/core/graphql/#using-the-page-based-pagination - * @param string|null $security https://api-platform.com/docs/core/security - * @param string|null $securityMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message - * @param string|null $securityPostDenormalize https://api-platform.com/docs/core/security/#executing-access-control-rules-after-denormalization - * @param string|null $securityPostDenormalizeMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message - * @param string $securityPostValidation https://api-platform.com/docs/core/security/#executing-access-control-rules-after-validtion - * @param string $securityPostValidationMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message - * @param mixed|null $provider - * @param mixed|null $processor + * @param string|string[]|null $types The RDF types of this resource + * @param mixed|null $operations + * @param array|string|null $formats https://api-platform.com/docs/core/content-negotiation/#configuring-formats-for-a-specific-resource-or-operation + * @param array|string|null $inputFormats https://api-platform.com/docs/core/content-negotiation/#configuring-formats-for-a-specific-resource-or-operation + * @param array|string|null $outputFormats https://api-platform.com/docs/core/content-negotiation/#configuring-formats-for-a-specific-resource-or-operation + * @param mixed|null $uriVariables + * @param string|null $routePrefix https://api-platform.com/docs/core/operations/#prefixing-all-routes-of-all-operations + * @param string|null $sunset https://api-platform.com/docs/core/deprecations/#setting-the-sunset-http-header-to-indicate-when-a-resource-or-an-operation-will-be-removed + * @param string|null $deprecationReason https://api-platform.com/docs/core/deprecations/#deprecating-resource-classes-operations-and-properties + * @param array|null $cacheHeaders https://api-platform.com/docs/core/performance/#setting-custom-http-cache-headers + * @param array|null $normalizationContext https://api-platform.com/docs/core/serialization/#using-serialization-groups + * @param array|null $denormalizationContext https://api-platform.com/docs/core/serialization/#using-serialization-groups + * @param string[]|null $hydraContext https://api-platform.com/docs/core/extending-jsonld-context/#hydra + * @param array|null $openapiContext https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts + * @param array|null $validationContext https://api-platform.com/docs/core/validation/#using-validation-groups + * @param string[]|null $filters https://api-platform.com/docs/core/filters/#doctrine-orm-and-mongodb-odm-filters + * @param bool|null $elasticsearch https://api-platform.com/docs/core/elasticsearch/ + * @param mixed|null $mercure https://api-platform.com/docs/core/mercure + * @param mixed|null $messenger https://api-platform.com/docs/core/messenger/#dispatching-a-resource-through-the-message-bus + * @param mixed|null $input https://api-platform.com/docs/core/dto/#specifying-an-input-or-an-output-data-representation + * @param mixed|null $output https://api-platform.com/docs/core/dto/#specifying-an-input-or-an-output-data-representation + * @param array|null $order https://api-platform.com/docs/core/default-order/#overriding-default-order + * @param bool|null $fetchPartial https://api-platform.com/docs/core/performance/#fetch-partial + * @param bool|null $forceEager https://api-platform.com/docs/core/performance/#force-eager + * @param bool|null $paginationClientEnabled https://api-platform.com/docs/core/pagination/#for-a-specific-resource-1 + * @param bool|null $paginationClientItemsPerPage https://api-platform.com/docs/core/pagination/#for-a-specific-resource-3 + * @param bool|null $paginationClientPartial https://api-platform.com/docs/core/pagination/#for-a-specific-resource-6 + * @param array|null $paginationViaCursor https://api-platform.com/docs/core/pagination/#cursor-based-pagination + * @param bool|null $paginationEnabled https://api-platform.com/docs/core/pagination/#for-a-specific-resource + * @param bool|null $paginationFetchJoinCollection https://api-platform.com/docs/core/pagination/#controlling-the-behavior-of-the-doctrine-orm-paginator + * @param int|null $paginationItemsPerPage https://api-platform.com/docs/core/pagination/#changing-the-number-of-items-per-page + * @param int|null $paginationMaximumItemsPerPage https://api-platform.com/docs/core/pagination/#changing-maximum-items-per-page + * @param bool|null $paginationPartial https://api-platform.com/docs/core/performance/#partial-pagination + * @param string|null $paginationType https://api-platform.com/docs/core/graphql/#using-the-page-based-pagination + * @param string|null $security https://api-platform.com/docs/core/security + * @param string|null $securityMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message + * @param string|null $securityPostDenormalize https://api-platform.com/docs/core/security/#executing-access-control-rules-after-denormalization + * @param string|null $securityPostDenormalizeMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message + * @param string $securityPostValidation https://api-platform.com/docs/core/security/#executing-access-control-rules-after-validtion + * @param string $securityPostValidationMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message + * @param string|callable|null $provider + * @param string|callable|null $processor */ public function __construct( ?string $uriTemplate = null, @@ -233,7 +236,7 @@ public function __construct( $this->uriTemplate = $uriTemplate; $this->shortName = $shortName; $this->description = $description; - $this->types = $types; + $this->types = null === $types ? null : (array) $types; $this->formats = $formats; $this->inputFormats = $inputFormats; $this->outputFormats = $outputFormats; From 07afa77cba94657ba04c436b39da64d00d49271a Mon Sep 17 00:00:00 2001 From: Gigino Chianese Date: Thu, 29 Sep 2022 10:03:44 +0200 Subject: [PATCH 15/17] fix: check fetch joined queries based on all aliases (#4974) fixes #4936 --- .../Bridge/Doctrine/Orm/Util/QueryChecker.php | 20 +++---------------- src/Doctrine/Orm/Util/QueryChecker.php | 20 +++---------------- tests/Doctrine/Orm/Util/QueryCheckerTest.php | 4 ++-- 3 files changed, 8 insertions(+), 36 deletions(-) diff --git a/src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php b/src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php index 568a0ca3523..5d9956e87a5 100644 --- a/src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php +++ b/src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php @@ -93,7 +93,6 @@ public static function hasMaxResults(QueryBuilder $queryBuilder): bool public static function hasOrderByOnFetchJoinedToManyAssociation(QueryBuilder $queryBuilder, ManagerRegistry $managerRegistry): bool { if ( - 0 === \count($selectParts = $queryBuilder->getDQLPart('select')) || 0 === \count($queryBuilder->getDQLPart('join')) || 0 === \count($orderByParts = $queryBuilder->getDQLPart('orderBy')) ) { @@ -102,21 +101,6 @@ public static function hasOrderByOnFetchJoinedToManyAssociation(QueryBuilder $qu $rootAliases = $queryBuilder->getRootAliases(); - $selectAliases = []; - - foreach ($selectParts as $select) { - foreach ($select->getParts() as $part) { - [$alias] = explode('.', $part); - - $selectAliases[] = $alias; - } - } - - $selectAliases = array_diff($selectAliases, $rootAliases); - if (0 === \count($selectAliases)) { - return false; - } - $orderByAliases = []; foreach ($orderByParts as $orderBy) { @@ -134,11 +118,13 @@ public static function hasOrderByOnFetchJoinedToManyAssociation(QueryBuilder $qu return false; } + $allAliases = $queryBuilder->getAllAliases(); + foreach ($orderByAliases as $orderByAlias) { $inToManyContext = false; foreach (QueryBuilderHelper::traverseJoins($orderByAlias, $queryBuilder, $managerRegistry) as $alias => [$metadata, $association]) { - if ($inToManyContext && \in_array($alias, $selectAliases, true)) { + if ($inToManyContext && \in_array($alias, $allAliases, true)) { return true; } diff --git a/src/Doctrine/Orm/Util/QueryChecker.php b/src/Doctrine/Orm/Util/QueryChecker.php index 92fa096b878..74f30f4fd3d 100644 --- a/src/Doctrine/Orm/Util/QueryChecker.php +++ b/src/Doctrine/Orm/Util/QueryChecker.php @@ -92,7 +92,6 @@ public static function hasMaxResults(QueryBuilder $queryBuilder): bool public static function hasOrderByOnFetchJoinedToManyAssociation(QueryBuilder $queryBuilder, ManagerRegistry $managerRegistry): bool { if ( - 0 === \count($selectParts = $queryBuilder->getDQLPart('select')) || 0 === \count($queryBuilder->getDQLPart('join')) || 0 === \count($orderByParts = $queryBuilder->getDQLPart('orderBy')) ) { @@ -101,21 +100,6 @@ public static function hasOrderByOnFetchJoinedToManyAssociation(QueryBuilder $qu $rootAliases = $queryBuilder->getRootAliases(); - $selectAliases = []; - - foreach ($selectParts as $select) { - foreach ($select->getParts() as $part) { - [$alias] = explode('.', $part); - - $selectAliases[] = $alias; - } - } - - $selectAliases = array_diff($selectAliases, $rootAliases); - if (0 === \count($selectAliases)) { - return false; - } - $orderByAliases = []; foreach ($orderByParts as $orderBy) { @@ -133,11 +117,13 @@ public static function hasOrderByOnFetchJoinedToManyAssociation(QueryBuilder $qu return false; } + $allAliases = $queryBuilder->getAllAliases(); + foreach ($orderByAliases as $orderByAlias) { $inToManyContext = false; foreach (QueryBuilderHelper::traverseJoins($orderByAlias, $queryBuilder, $managerRegistry) as $alias => [$metadata, $association]) { - if ($inToManyContext && \in_array($alias, $selectAliases, true)) { + if ($inToManyContext && \in_array($alias, $allAliases, true)) { return true; } diff --git a/tests/Doctrine/Orm/Util/QueryCheckerTest.php b/tests/Doctrine/Orm/Util/QueryCheckerTest.php index d223831272d..ca411727ca0 100644 --- a/tests/Doctrine/Orm/Util/QueryCheckerTest.php +++ b/tests/Doctrine/Orm/Util/QueryCheckerTest.php @@ -175,7 +175,7 @@ public function testHasOrderByOnFetchJoinedToManyAssociationNotFetchJoined() $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($entityManagerProphecy); $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->willReturn($entityManagerProphecy); - $this->assertFalse(QueryChecker::hasOrderByOnFetchJoinedToManyAssociation($queryBuilder, $managerRegistryProphecy->reveal())); + $this->assertTrue(QueryChecker::hasOrderByOnFetchJoinedToManyAssociation($queryBuilder, $managerRegistryProphecy->reveal())); } public function testHasOrderByOnFetchJoinedToManyAssociationWithJoinByAssociation() @@ -277,7 +277,7 @@ public function testHasOrderByOnToManyJoinNotFetchJoined() $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($entityManagerProphecy); $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->willReturn($entityManagerProphecy); - $this->assertFalse(LegacyQueryChecker::hasOrderByOnToManyJoin($queryBuilder, $managerRegistryProphecy->reveal())); + $this->assertTrue(LegacyQueryChecker::hasOrderByOnToManyJoin($queryBuilder, $managerRegistryProphecy->reveal())); } /** From 9895e3494336fced977e82bb282dce3a36915799 Mon Sep 17 00:00:00 2001 From: Antoine Bluchet Date: Thu, 29 Sep 2022 10:27:16 +0200 Subject: [PATCH 16/17] fix(symfony): don't use ArrayAdapter in production #4975 (#5025) --- src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 6eeef3281c0..debc51d3060 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -649,7 +649,7 @@ private function registerCacheConfiguration(ContainerBuilder $container): void @trigger_error('The "api_platform.metadata_cache" parameter is deprecated since version 2.4 and will have no effect in 3.0.', \E_USER_DEPRECATED); // BC - if (!$container->getParameter('api_platform.metadata_cache')) { + if (!$container->getParameter('api_platform.metadata_cache') && $container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug')) { $container->removeDefinition('api_platform.cache_warmer.cache_pool_clearer'); $container->register('api_platform.cache.metadata.property', ArrayAdapter::class); From 10919381762f513f14f20ff149a4354a2703d995 Mon Sep 17 00:00:00 2001 From: Antoine Bluchet Date: Thu, 29 Sep 2022 10:55:11 +0200 Subject: [PATCH 17/17] chore: update swagger ui and javascript libraries (#5028) --- .../Resources/public/fonts/open-sans/400.css | 12 +- .../Resources/public/fonts/open-sans/700.css | 12 +- .../files/open-sans-cyrillic-400-normal.woff2 | Bin 10092 -> 10088 bytes .../files/open-sans-cyrillic-700-normal.woff2 | Bin 9832 -> 9868 bytes .../open-sans-cyrillic-ext-400-normal.woff2 | Bin 17508 -> 17472 bytes .../open-sans-cyrillic-ext-700-normal.woff2 | Bin 16908 -> 16940 bytes .../files/open-sans-greek-400-normal.woff2 | Bin 8948 -> 8876 bytes .../files/open-sans-greek-700-normal.woff2 | Bin 8772 -> 8816 bytes .../open-sans-greek-ext-400-normal.woff2 | Bin 3712 -> 3720 bytes .../open-sans-greek-ext-700-normal.woff2 | Bin 3676 -> 3692 bytes .../files/open-sans-latin-400-normal.woff2 | Bin 16692 -> 16720 bytes .../files/open-sans-latin-700-normal.woff2 | Bin 16408 -> 16360 bytes .../open-sans-latin-ext-400-normal.woff2 | Bin 12956 -> 12956 bytes .../open-sans-latin-ext-700-normal.woff2 | Bin 12760 -> 12700 bytes .../open-sans-vietnamese-400-normal.woff2 | Bin 7196 -> 7136 bytes .../open-sans-vietnamese-700-normal.woff2 | Bin 7080 -> 7056 bytes .../Resources/public/graphiql/graphiql.css | 2281 ++++--------- .../Resources/public/graphiql/graphiql.min.js | 37 +- .../public/react/react-dom.production.min.js | 490 +-- .../public/react/react.production.min.js | 46 +- .../public/redoc/redoc.standalone.js | 975 +++--- yarn.lock | 2828 ++++++++++++----- 22 files changed, 3375 insertions(+), 3306 deletions(-) diff --git a/src/Symfony/Bundle/Resources/public/fonts/open-sans/400.css b/src/Symfony/Bundle/Resources/public/fonts/open-sans/400.css index fbddb938df8..e6c28c969a9 100644 --- a/src/Symfony/Bundle/Resources/public/fonts/open-sans/400.css +++ b/src/Symfony/Bundle/Resources/public/fonts/open-sans/400.css @@ -5,7 +5,7 @@ font-display: swap; font-weight: 400; src: url('./files/open-sans-cyrillic-ext-400-normal.woff2') format('woff2'), url('./files/open-sans-all-400-normal.woff') format('woff'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; + unicode-range: U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F; } /* open-sans-cyrillic-400-normal*/ @font-face { @@ -14,7 +14,7 @@ font-display: swap; font-weight: 400; src: url('./files/open-sans-cyrillic-400-normal.woff2') format('woff2'), url('./files/open-sans-all-400-normal.woff') format('woff'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; + unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116; } /* open-sans-greek-ext-400-normal*/ @font-face { @@ -41,7 +41,7 @@ font-display: swap; font-weight: 400; src: url('./files/open-sans-hebrew-400-normal.woff2') format('woff2'), url('./files/open-sans-all-400-normal.woff') format('woff'); - unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; + unicode-range: U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F; } /* open-sans-vietnamese-400-normal*/ @font-face { @@ -50,7 +50,7 @@ font-display: swap; font-weight: 400; src: url('./files/open-sans-vietnamese-400-normal.woff2') format('woff2'), url('./files/open-sans-all-400-normal.woff') format('woff'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; + unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB; } /* open-sans-latin-ext-400-normal*/ @font-face { @@ -59,7 +59,7 @@ font-display: swap; font-weight: 400; src: url('./files/open-sans-latin-ext-400-normal.woff2') format('woff2'), url('./files/open-sans-all-400-normal.woff') format('woff'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; + unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF; } /* open-sans-latin-400-normal*/ @font-face { @@ -68,5 +68,5 @@ font-display: swap; font-weight: 400; src: url('./files/open-sans-latin-400-normal.woff2') format('woff2'), url('./files/open-sans-all-400-normal.woff') format('woff'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; } diff --git a/src/Symfony/Bundle/Resources/public/fonts/open-sans/700.css b/src/Symfony/Bundle/Resources/public/fonts/open-sans/700.css index 8fe17225155..e8bb937c398 100644 --- a/src/Symfony/Bundle/Resources/public/fonts/open-sans/700.css +++ b/src/Symfony/Bundle/Resources/public/fonts/open-sans/700.css @@ -5,7 +5,7 @@ font-display: swap; font-weight: 700; src: url('./files/open-sans-cyrillic-ext-700-normal.woff2') format('woff2'), url('./files/open-sans-all-700-normal.woff') format('woff'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; + unicode-range: U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F; } /* open-sans-cyrillic-700-normal*/ @font-face { @@ -14,7 +14,7 @@ font-display: swap; font-weight: 700; src: url('./files/open-sans-cyrillic-700-normal.woff2') format('woff2'), url('./files/open-sans-all-700-normal.woff') format('woff'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; + unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116; } /* open-sans-greek-ext-700-normal*/ @font-face { @@ -41,7 +41,7 @@ font-display: swap; font-weight: 700; src: url('./files/open-sans-hebrew-700-normal.woff2') format('woff2'), url('./files/open-sans-all-700-normal.woff') format('woff'); - unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; + unicode-range: U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F; } /* open-sans-vietnamese-700-normal*/ @font-face { @@ -50,7 +50,7 @@ font-display: swap; font-weight: 700; src: url('./files/open-sans-vietnamese-700-normal.woff2') format('woff2'), url('./files/open-sans-all-700-normal.woff') format('woff'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; + unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB; } /* open-sans-latin-ext-700-normal*/ @font-face { @@ -59,7 +59,7 @@ font-display: swap; font-weight: 700; src: url('./files/open-sans-latin-ext-700-normal.woff2') format('woff2'), url('./files/open-sans-all-700-normal.woff') format('woff'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; + unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF; } /* open-sans-latin-700-normal*/ @font-face { @@ -68,5 +68,5 @@ font-display: swap; font-weight: 700; src: url('./files/open-sans-latin-700-normal.woff2') format('woff2'), url('./files/open-sans-all-700-normal.woff') format('woff'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; } diff --git a/src/Symfony/Bundle/Resources/public/fonts/open-sans/files/open-sans-cyrillic-400-normal.woff2 b/src/Symfony/Bundle/Resources/public/fonts/open-sans/files/open-sans-cyrillic-400-normal.woff2 index bb36c230e2de06f4f784268467ade2a5e78a74ab..ff7f269b848d1a4cc9a9164675831942be4b081f 100644 GIT binary patch literal 10088 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 K@+Xx60000UV1!Em literal 10092 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 O390VW*gkT3C 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 yM+QALIZCA!C390VW*gkT3C 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 OhvhH)IQ+)mRSN*#I^Gcg diff --git a/src/Symfony/Bundle/Resources/public/fonts/open-sans/files/open-sans-cyrillic-ext-400-normal.woff2 b/src/Symfony/Bundle/Resources/public/fonts/open-sans/files/open-sans-cyrillic-ext-400-normal.woff2 index 221d57af43df64877958a7f9fc30b863aadf796b..9377c57e8fc9f5c67354884cb7e6bbd01a2c2975 100644 GIT binary patch literal 17472 zcmV)6K*+y$Pew8T0RR9107O6l5&!@I0Du?(07KdU0RR9100000000000000000000 z0000QS{sWR96SbKKT}jeR9*mF2!VVFpA-=g3W2yhfu1J|gE9aCHUcCAhFAn31%!A9 zAPj{c8yRpl;_V{=bO%nNGj)|jQ6^?}6v4&;VuUsX|NrOY#*hNrgJ!jE4|!CQ0x3)u z+oWfzrnxIi!NLseoyoK32}GKMh7Y^q9?;(tr4q}JzY1RsZP8WK3d{7v^()Lp2N~%z zR$(T#Odo6($-j2ex~MdJykzLb*~q{nrY1EOL@kGkuShIfob>-h(?zZCn6~q?V4e4F z{6-tg=oreLqLm0H_qp{|)dE9R11tJ+3DP~YAY=HV+EfDXM+fI3 zBWr^-7kXb^H`fDR_ER1{U}4}-Ls)zn$*VTrwLY{M0}f&1j7QwJQupuP=_JeWevtIXk%C2) zN;3`;I6x|@Ov+S1?ur0*X*#l%rRJ_uT*=OG7}Pj}ymw06WpZFT30OG*T#`CDhxc8L zUq8PZj;p8B>wUh=7JMN<2*E~Hbaua(*H_fnbg!tUWoA~K|DR2(v|25V+xF}{YrXf@ zyGQn-4lsxYqP+;BOCf`ocm1k{s_M2%EqTXk8D!ZD_L5|KKpJvO=JEAqL4owI95C;*&A!J!j{a2HvTCr@L0R$vYf+T(R+n+J_{};p7cx7@JvK17ZzdssSkOg+Q zWOvj;`A`Da0m2B})}oWJ7rlWZdJDHl?-G9%>d*%bB%%NcA-Ss*2n^aihbp)XR>#QY zOa*NB-t^dPd2|VjX?Z*kp|?CAGvYmDy-M*t2jq*{0Wlif?-v)PX7dE%0 zZEVj)*TU{#clL14_jaH6bN>PYiGl<{q99nxsUr*O%?4-+gRV2dLpJn&PDNJ8qh z5f6h5@?cRx9W8V*5SC%anc@;F%CmKg9&+W*b&toq