From c97b08e6c0eb121899621573c79efacf85ddada8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 20 Apr 2017 12:57:35 +0200 Subject: [PATCH] [FrameworkBundle] Restore 3.2-like behavior for FormPass, to help BC with Sonata --- .../DependencyInjection/Compiler/FormPass.php | 68 ++++++- .../FrameworkBundle/Resources/config/form.xml | 1 + .../Compiler/FormPassTest.php | 172 ++++++++---------- .../Form/DependencyInjection/FormPass.php | 3 + 4 files changed, 141 insertions(+), 103 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php index 252b00f0692c..fdbfd4297b22 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php @@ -13,16 +13,76 @@ @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\Form\DependencyInjection\FormPass instead.', FormPass::class), E_USER_DEPRECATED); -use Symfony\Component\Form\DependencyInjection\FormPass as BaseFormPass; +use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * Adds all services with the tags "form.type" and "form.type_guesser" as * arguments of the "form.extension" service. * - * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseFormPass} instead. - * * @author Bernhard Schussek + * + * @deprecated since version 3.3, to be removed in 4.0. Use FormPass in the Form component instead. */ -class FormPass extends BaseFormPass +class FormPass implements CompilerPassInterface { + use PriorityTaggedServiceTrait; + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('form.extension')) { + return; + } + + $definition = $container->getDefinition('form.extension'); + + // Builds an array with fully-qualified type class names as keys and service IDs as values + $types = array(); + + foreach ($container->findTaggedServiceIds('form.type') as $serviceId => $tag) { + $serviceDefinition = $container->getDefinition($serviceId); + if (!$serviceDefinition->isPublic()) { + $serviceDefinition->setPublic(true); + } + + // Support type access by FQCN + $types[$serviceDefinition->getClass()] = $serviceId; + } + + $definition->replaceArgument(1, $types); + + $typeExtensions = array(); + + foreach ($this->findAndSortTaggedServices('form.type_extension', $container) as $reference) { + $serviceId = (string) $reference; + $serviceDefinition = $container->getDefinition($serviceId); + if (!$serviceDefinition->isPublic()) { + $serviceDefinition->setPublic(true); + } + + $tag = $serviceDefinition->getTag('form.type_extension'); + if (isset($tag[0]['extended_type'])) { + $extendedType = $tag[0]['extended_type']; + } else { + throw new InvalidArgumentException(sprintf('Tagged form type extension must have the extended type configured using the extended_type/extended-type attribute, none was configured for the "%s" service.', $serviceId)); + } + + $typeExtensions[$extendedType][] = $serviceId; + } + + $definition->replaceArgument(2, $typeExtensions); + + // Find all services annotated with "form.type_guesser" + $guessers = array_keys($container->findTaggedServiceIds('form.type_guesser')); + foreach ($guessers as $serviceId) { + $serviceDefinition = $container->getDefinition($serviceId); + if (!$serviceDefinition->isPublic()) { + $serviceDefinition->setPublic(true); + } + } + + $definition->replaceArgument(3, $guessers); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml index 3663a991afc4..a9eb59b4782a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml @@ -36,6 +36,7 @@ + null diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php index 5ea5169a6d5a..9adbaf8da906 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php @@ -13,12 +13,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\Form\AbstractType; /** @@ -30,7 +27,8 @@ class FormPassTest extends TestCase { public function testDoNothingIfFormExtensionNotLoaded() { - $container = $this->createContainerBuilder(); + $container = new ContainerBuilder(); + $container->addCompilerPass(new FormPass()); $container->compile(); @@ -39,9 +37,18 @@ public function testDoNothingIfFormExtensionNotLoaded() public function testAddTaggedTypes() { - $container = $this->createContainerBuilder(); + $container = new ContainerBuilder(); + $container->addCompilerPass(new FormPass()); - $container->setDefinition('form.extension', $this->createExtensionDefinition()); + $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension'); + $extDefinition->setArguments(array( + new Reference('service_container'), + array(), + array(), + array(), + )); + + $container->setDefinition('form.extension', $extDefinition); $container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type'); $container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type'); @@ -49,13 +56,10 @@ public function testAddTaggedTypes() $extDefinition = $container->getDefinition('form.extension'); - $this->assertEquals( - (new Definition(ServiceLocator::class, array(array( - __CLASS__.'_Type1' => new ServiceClosureArgument(new Reference('my.type1')), - __CLASS__.'_Type2' => new ServiceClosureArgument(new Reference('my.type2')), - ))))->addTag('container.service_locator')->setPublic(false), - $extDefinition->getArgument(0) - ); + $this->assertEquals(array( + __CLASS__.'_Type1' => 'my.type1', + __CLASS__.'_Type2' => 'my.type2', + ), $extDefinition->getArgument(1)); } /** @@ -63,9 +67,17 @@ public function testAddTaggedTypes() */ public function testAddTaggedTypeExtensions(array $extensions, array $expectedRegisteredExtensions) { - $container = $this->createContainerBuilder(); + $container = new ContainerBuilder(); + $container->addCompilerPass(new FormPass()); - $container->setDefinition('form.extension', $this->createExtensionDefinition()); + $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension', array( + new Reference('service_container'), + array(), + array(), + array(), + )); + + $container->setDefinition('form.extension', $extDefinition); foreach ($extensions as $serviceId => $tag) { $container->register($serviceId, 'stdClass')->addTag('form.type_extension', $tag); @@ -74,7 +86,7 @@ public function testAddTaggedTypeExtensions(array $extensions, array $expectedRe $container->compile(); $extDefinition = $container->getDefinition('form.extension'); - $this->assertEquals($expectedRegisteredExtensions, $extDefinition->getArgument(1)); + $this->assertSame($expectedRegisteredExtensions, $extDefinition->getArgument(2)); } /** @@ -90,11 +102,8 @@ public function addTaggedTypeExtensionsDataProvider() 'my.type_extension3' => array('extended_type' => 'type2'), ), array( - 'type1' => new IteratorArgument(array( - new Reference('my.type_extension1'), - new Reference('my.type_extension2'), - )), - 'type2' => new IteratorArgument(array(new Reference('my.type_extension3'))), + 'type1' => array('my.type_extension1', 'my.type_extension2'), + 'type2' => array('my.type_extension3'), ), ), array( @@ -107,16 +116,8 @@ public function addTaggedTypeExtensionsDataProvider() 'my.type_extension6' => array('extended_type' => 'type2', 'priority' => 1), ), array( - 'type1' => new IteratorArgument(array( - new Reference('my.type_extension2'), - new Reference('my.type_extension1'), - new Reference('my.type_extension3'), - )), - 'type2' => new IteratorArgument(array( - new Reference('my.type_extension4'), - new Reference('my.type_extension5'), - new Reference('my.type_extension6'), - )), + 'type1' => array('my.type_extension2', 'my.type_extension1', 'my.type_extension3'), + 'type2' => array('my.type_extension4', 'my.type_extension5', 'my.type_extension6'), ), ), ); @@ -128,9 +129,17 @@ public function addTaggedTypeExtensionsDataProvider() */ public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute() { - $container = $this->createContainerBuilder(); + $container = new ContainerBuilder(); + $container->addCompilerPass(new FormPass()); + + $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension', array( + new Reference('service_container'), + array(), + array(), + array(), + )); - $container->setDefinition('form.extension', $this->createExtensionDefinition()); + $container->setDefinition('form.extension', $extDefinition); $container->register('my.type_extension', 'stdClass') ->addTag('form.type_extension'); @@ -139,14 +148,23 @@ public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute() public function testAddTaggedGuessers() { - $container = $this->createContainerBuilder(); + $container = new ContainerBuilder(); + $container->addCompilerPass(new FormPass()); + + $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension'); + $extDefinition->setArguments(array( + new Reference('service_container'), + array(), + array(), + array(), + )); $definition1 = new Definition('stdClass'); $definition1->addTag('form.type_guesser'); $definition2 = new Definition('stdClass'); $definition2->addTag('form.type_guesser'); - $container->setDefinition('form.extension', $this->createExtensionDefinition()); + $container->setDefinition('form.extension', $extDefinition); $container->setDefinition('my.guesser1', $definition1); $container->setDefinition('my.guesser2', $definition2); @@ -154,87 +172,43 @@ public function testAddTaggedGuessers() $extDefinition = $container->getDefinition('form.extension'); - $this->assertEquals( - new IteratorArgument(array( - new Reference('my.guesser1'), - new Reference('my.guesser2'), - )), - $extDefinition->getArgument(2) - ); + $this->assertSame(array( + 'my.guesser1', + 'my.guesser2', + ), $extDefinition->getArgument(3)); } /** * @dataProvider privateTaggedServicesProvider */ - public function testPrivateTaggedServices($id, $tagName, callable $assertion, array $tagAttributes = array()) + public function testPrivateTaggedServices($id, $tagName) { - $formPass = new FormPass(); $container = new ContainerBuilder(); + $container->addCompilerPass(new FormPass()); - $container->setDefinition('form.extension', $this->createExtensionDefinition()); - $container->register($id, 'stdClass')->setPublic(false)->addTag($tagName, $tagAttributes); + $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension'); + $extDefinition->setArguments(array( + new Reference('service_container'), + array(), + array(), + array(), + )); - $formPass->process($container); + $container->setDefinition('form.extension', $extDefinition); + $container->register($id, 'stdClass')->setPublic(false)->addTag($tagName, array('extended_type' => 'Foo')); - $assertion($container); + $container->compile(); + $this->assertTrue($container->getDefinition($id)->isPublic()); } public function privateTaggedServicesProvider() { return array( - array( - 'my.type', - 'form.type', - function (ContainerBuilder $container) { - $formTypes = $container->getDefinition('form.extension')->getArgument(0); - - $this->assertInstanceOf(Reference::class, $formTypes); - - $locator = $container->getDefinition((string) $formTypes); - $expectedLocatorMap = array( - 'stdClass' => new ServiceClosureArgument(new Reference('my.type')), - ); - - $this->assertInstanceOf(Definition::class, $locator); - $this->assertEquals($expectedLocatorMap, $locator->getArgument(0)); - }, - ), - array( - 'my.type_extension', - 'form.type_extension', - function (ContainerBuilder $container) { - $this->assertEquals( - array('Symfony\Component\Form\Extension\Core\Type\FormType' => new IteratorArgument(array(new Reference('my.type_extension')))), - $container->getDefinition('form.extension')->getArgument(1) - ); - }, - array('extended_type' => 'Symfony\Component\Form\Extension\Core\Type\FormType'), - ), - array('my.guesser', 'form.type_guesser', function (ContainerBuilder $container) { - $this->assertEquals(new IteratorArgument(array(new Reference('my.guesser'))), $container->getDefinition('form.extension')->getArgument(2)); - }), + array('my.type', 'form.type'), + array('my.type_extension', 'form.type_extension'), + array('my.guesser', 'form.type_guesser'), ); } - - private function createContainerBuilder() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new FormPass()); - - return $container; - } - - private function createExtensionDefinition() - { - $definition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension'); - $definition->setArguments(array( - array(), - array(), - new IteratorArgument(array()), - )); - - return $definition; - } } class FormPassTest_Type1 extends AbstractType diff --git a/src/Symfony/Component/Form/DependencyInjection/FormPass.php b/src/Symfony/Component/Form/DependencyInjection/FormPass.php index 464035607c20..55e4cc1239b2 100644 --- a/src/Symfony/Component/Form/DependencyInjection/FormPass.php +++ b/src/Symfony/Component/Form/DependencyInjection/FormPass.php @@ -50,6 +50,9 @@ public function process(ContainerBuilder $container) } $definition = $container->getDefinition($this->formExtensionService); + if (new IteratorArgument(array()) != $definition->getArgument(2)) { + return; + } $definition->replaceArgument(0, $this->processFormTypes($container, $definition)); $definition->replaceArgument(1, $this->processFormTypeExtensions($container)); $definition->replaceArgument(2, $this->processFormTypeGuessers($container));