diff --git a/CHANGELOG.md b/CHANGELOG.md index f3aac4b4a9e..b6f0d5386fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,12 +50,13 @@ * Symfony: Allow using `ItemNormalizer` without Symfony SecurityBundle (#3801) * Symfony: Lazy load all commands (#3798) * Tests: adds a method to retrieve the CookieJar in the test Client `getCookieJar` +* Tests: Fix the registration of the `test.api_platform.client` service when the `FrameworkBundle` bundle is registered after the `ApiPlatformBundle` bundle (#3928) * Validator: Add the violation code to the violation properties (#3857) * Validator: Allow customizing the validation error status code (#3808) * Validator: Autoconfiguration of validation groups generator via `ApiPlatform\Core\Validator\ValidationGroupsGeneratorInterface` * Validator: Deprecate using a validation groups generator service not implementing `ApiPlatform\Core\Bridge\Symfony\Validator\ValidationGroupsGeneratorInterface` (#3346) * Validator: Property validation through OpenAPI (#33329) -* Validator:Query filters and parameters are validated (#1723) +* Validator: Query filters and parameters are validated (#1723) * `ExceptionInterface` now extends `\Throwable` (#3217) ## 2.5.9 diff --git a/src/Bridge/Symfony/Bundle/ApiPlatformBundle.php b/src/Bridge/Symfony/Bundle/ApiPlatformBundle.php index 3411ee33937..560b61d80c8 100644 --- a/src/Bridge/Symfony/Bundle/ApiPlatformBundle.php +++ b/src/Bridge/Symfony/Bundle/ApiPlatformBundle.php @@ -22,6 +22,7 @@ use ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass; use ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; use ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; +use ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\Compiler\ResolveInstanceofConditionalsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -51,5 +52,6 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new GraphQlMutationResolverPass()); $container->addCompilerPass(new DeprecateMercurePublisherPass()); $container->addCompilerPass(new MetadataAwareNameConverterPass()); + $container->addCompilerPass(new TestClientPass()); } } diff --git a/src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 468a7f35866..cd7a5215d6e 100644 --- a/src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -41,7 +41,6 @@ use Doctrine\Common\Annotations\Annotation; use phpDocumentor\Reflection\DocBlockFactoryInterface; use Ramsey\Uuid\Uuid; -use Symfony\Component\BrowserKit\AbstractBrowser; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Resource\DirectoryResource; @@ -53,7 +52,6 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Finder\Finder; -use Symfony\Component\HttpClient\HttpClientTrait; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Uid\AbstractUid; @@ -138,14 +136,6 @@ public function load(array $configs, ContainerBuilder $container): void ->addTag('api_platform.subresource_data_provider'); $container->registerForAutoconfiguration(FilterInterface::class) ->addTag('api_platform.filter'); - - if ($container->hasParameter('test.client.parameters')) { - $loader->load('test.xml'); - - if (!class_exists(AbstractBrowser::class) || !trait_exists(HttpClientTrait::class)) { - $container->removeDefinition('test.api_platform.client'); - } - } } private function registerCommonConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader, array $formats, array $patchFormats, array $errorFormats): void diff --git a/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php b/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php new file mode 100644 index 00000000000..1d1ec96c61b --- /dev/null +++ b/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php @@ -0,0 +1,43 @@ + + * + * 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\Bridge\Symfony\Bundle\DependencyInjection\Compiler; + +use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client; +use Symfony\Component\BrowserKit\AbstractBrowser; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpClient\HttpClientTrait; + +final class TestClientPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if ( + !class_exists(AbstractBrowser::class) || + !trait_exists(HttpClientTrait::class) || + !$container->hasParameter('test.client.parameters') + ) { + return; + } + + $container->setDefinition( + 'test.api_platform.client', + (new Definition(Client::class, [new Reference('test.client')])) + ->setShared(false) + ->setPublic(true) + ); + } +} diff --git a/src/Bridge/Symfony/Bundle/Resources/config/test.xml b/src/Bridge/Symfony/Bundle/Resources/config/test.xml deleted file mode 100644 index 001e68219ba..00000000000 --- a/src/Bridge/Symfony/Bundle/Resources/config/test.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/tests/Bridge/Symfony/Bundle/ApiPlatformBundleTest.php b/tests/Bridge/Symfony/Bundle/ApiPlatformBundleTest.php index ce92910072d..5ea6458148c 100644 --- a/tests/Bridge/Symfony/Bundle/ApiPlatformBundleTest.php +++ b/tests/Bridge/Symfony/Bundle/ApiPlatformBundleTest.php @@ -23,6 +23,7 @@ use ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass; use ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; use ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; +use ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; @@ -48,6 +49,7 @@ public function testBuild() $containerProphecy->addCompilerPass(Argument::type(GraphQlMutationResolverPass::class))->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(DeprecateMercurePublisherPass::class))->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(MetadataAwareNameConverterPass::class))->shouldBeCalled(); + $containerProphecy->addCompilerPass(Argument::type(TestClientPass::class))->shouldBeCalled(); $bundle = new ApiPlatformBundle(); $bundle->build($containerProphecy->reveal()); diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index e2c3f794647..a9b1ae66bc5 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -1159,7 +1159,6 @@ private function getBaseContainerBuilderProphecy(array $doctrineIntegrationsToLo foreach ($parameters as $key => $value) { $containerBuilderProphecy->setParameter($key, $value)->shouldBeCalled(); } - $containerBuilderProphecy->hasParameter('test.client.parameters')->wilLReturn(true); foreach (['yaml', 'xml'] as $format) { $definitionProphecy = $this->prophesize(Definition::class); @@ -1270,7 +1269,6 @@ private function getBaseContainerBuilderProphecy(array $doctrineIntegrationsToLo 'api_platform.swagger.listener.ui', 'api_platform.validator', 'api_platform.validator.query_parameter_validator', - 'test.api_platform.client', ]; if (\in_array('odm', $doctrineIntegrationsToLoad, true)) { diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php new file mode 100644 index 00000000000..02d4d7147f4 --- /dev/null +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php @@ -0,0 +1,68 @@ + + * + * 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\Tests\Bridge\Symfony\Bundle\DependencyInjection\Compiler; + +use ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; +use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client; +use PHPUnit\Framework\TestCase; +use Prophecy\Argument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; + +final class TestClientPassTest extends TestCase +{ + private $containerBuilderProphecy; + private $testClientPass; + + protected function setUp(): void + { + $this->containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); + $this->testClientPass = new TestClientPass(); + } + + public function testConstruct(): void + { + self::assertInstanceOf(CompilerPassInterface::class, $this->testClientPass); + } + + public function testProcessWithoutTestClientParameters(): void + { + $this->containerBuilderProphecy->hasParameter('test.client.parameters')->willReturn(false)->shouldBeCalledOnce(); + $this->containerBuilderProphecy->setDefinition('test.api_platform.client', Argument::type(Definition::class))->shouldNotBeCalled(); + + $this->testClientPass->process($this->containerBuilderProphecy->reveal()); + } + + public function testProcess(): void + { + $this->containerBuilderProphecy->hasParameter('test.client.parameters')->willReturn(true)->shouldBeCalledOnce(); + $this->containerBuilderProphecy + ->setDefinition( + 'test.api_platform.client', + Argument::allOf( + Argument::type(Definition::class), + Argument::that(function (Definition $testClientDefinition) { + return + Client::class === $testClientDefinition->getClass() && + !$testClientDefinition->isShared() && + $testClientDefinition->isPublic(); + }) + ) + ) + ->shouldBeCalledOnce(); + + $this->testClientPass->process($this->containerBuilderProphecy->reveal()); + } +} diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index 3d7d1f01afe..af4e67daf87 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -61,14 +61,14 @@ public function __construct(string $environment, bool $debug) public function registerBundles(): array { $bundles = [ - new FrameworkBundle(), + new ApiPlatformBundle(), new TwigBundle(), new DoctrineBundle(), new MercureBundle(), - new ApiPlatformBundle(), new SecurityBundle(), new WebProfilerBundle(), new FriendsOfBehatSymfonyExtensionBundle(), + new FrameworkBundle(), ]; if (class_exists(DoctrineMongoDBBundle::class)) {