diff --git a/src/Symfony/Component/DependencyInjection/ChildDefinition.php b/src/Symfony/Component/DependencyInjection/ChildDefinition.php index b75124f61977f..d202170e373b2 100644 --- a/src/Symfony/Component/DependencyInjection/ChildDefinition.php +++ b/src/Symfony/Component/DependencyInjection/ChildDefinition.php @@ -11,6 +11,7 @@ namespace Symfony\Component\DependencyInjection; +use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; @@ -134,6 +135,22 @@ public function replaceArgument($index, $value) return $this; } + + /** + * @internal + */ + public function setAutoconfigured($autoconfigured) + { + throw new BadMethodCallException('A ChildDefinition cannot be autoconfigured.'); + } + + /** + * @internal + */ + public function setInstanceofConditionals(array $instanceof) + { + throw new BadMethodCallException('A ChildDefinition cannot have instanceof conditionals set on it.'); + } } class_alias(ChildDefinition::class, DefinitionDecorator::class); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php index 0be05dea23bcb..f4f8cd5c151c7 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php @@ -101,7 +101,6 @@ private function doResolveDefinition(ChildDefinition $definition) $def->setPublic($parentDef->isPublic()); $def->setLazy($parentDef->isLazy()); $def->setAutowired($parentDef->isAutowired()); - $def->setAutoconfigured($parentDef->isAutoconfigured()); $def->setChanges($parentDef->getChanges()); // overwrite with values specified in the decorator @@ -130,9 +129,6 @@ private function doResolveDefinition(ChildDefinition $definition) if (isset($changes['autowired'])) { $def->setAutowired($definition->isAutowired()); } - if (isset($changes['autoconfigured'])) { - $def->setAutoconfigured($definition->isAutoconfigured()); - } if (isset($changes['shared'])) { $def->setShared($definition->isShared()); } @@ -174,6 +170,9 @@ private function doResolveDefinition(ChildDefinition $definition) // these attributes are always taken from the child $def->setAbstract($definition->isAbstract()); $def->setTags($definition->getTags()); + // autoconfigure is never taken from parent (on purpose) + // and it's not legal on an instanceof + $def->setAutoconfigured($definition->isAutoconfigured()); return $def; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php index 555e8eb36fe3e..6ec07672567d6 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * Applies instanceof conditionals to definitions. @@ -28,6 +29,15 @@ class ResolveInstanceofConditionalsPass implements CompilerPassInterface */ public function process(ContainerBuilder $container) { + foreach ($container->getAutoconfiguredInstanceof() as $interface => $definition) { + if ($definition->getArguments()) { + throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines arguments but these are not supported and should be removed.', $interface)); + } + if ($definition->getMethodCalls()) { + throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines method calls but these are not supported and should be removed.', $interface)); + } + } + foreach ($container->getDefinitions() as $id => $definition) { if ($definition instanceof ChildDefinition) { // don't apply "instanceof" to children: it will be applied to their parent @@ -40,8 +50,8 @@ public function process(ContainerBuilder $container) private function processDefinition(ContainerBuilder $container, $id, Definition $definition) { $instanceofConditionals = $definition->getInstanceofConditionals(); - $automaticInstanceofConditionals = $definition->isAutoconfigured() ? $container->getAutomaticInstanceofDefinitions() : array(); - if (!$instanceofConditionals && !$automaticInstanceofConditionals) { + $autoconfiguredInstanceof = $definition->isAutoconfigured() ? $container->getAutoconfiguredInstanceof() : array(); + if (!$instanceofConditionals && !$autoconfiguredInstanceof) { return $definition; } @@ -49,7 +59,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition return $definition; } - $conditionals = $this->mergeConditionals($automaticInstanceofConditionals, $instanceofConditionals, $container); + $conditionals = $this->mergeConditionals($autoconfiguredInstanceof, $instanceofConditionals, $container); $definition->setInstanceofConditionals(array()); $parent = $shared = null; @@ -113,10 +123,10 @@ private function processDefinition(ContainerBuilder $container, $id, Definition return $definition; } - private function mergeConditionals(array $automaticInstanceofConditionals, array $instanceofConditionals, ContainerBuilder $container) + private function mergeConditionals(array $autoconfiguredInstanceof, array $instanceofConditionals, ContainerBuilder $container) { // make each value an array of ChildDefinition - $conditionals = array_map(function ($childDef) { return array($childDef); }, $automaticInstanceofConditionals); + $conditionals = array_map(function ($childDef) { return array($childDef); }, $autoconfiguredInstanceof); foreach ($instanceofConditionals as $interface => $instanceofDef) { // make sure the interface/class exists (but don't validate automaticInstanceofConditionals) @@ -124,7 +134,7 @@ private function mergeConditionals(array $automaticInstanceofConditionals, array throw new RuntimeException(sprintf('"%s" is set as an "instanceof" conditional, but it does not exist.', $interface)); } - if (!isset($automaticInstanceofConditionals[$interface])) { + if (!isset($autoconfiguredInstanceof[$interface])) { $conditionals[$interface] = array(); } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 910427b210788..929b8983cacc4 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -118,7 +118,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface */ private $vendors; - private $automaticInstanceofDefinitions = array(); + private $autoconfiguredInstanceof = array(); public function __construct(ParameterBagInterface $parameterBag = null) { @@ -641,12 +641,12 @@ public function merge(ContainerBuilder $container) } } - foreach ($container->getAutomaticInstanceofDefinitions() as $interface => $childDefinition) { - if (isset($this->automaticInstanceofDefinitions[$interface])) { + foreach ($container->getAutoconfiguredInstanceof() as $interface => $childDefinition) { + if (isset($this->autoconfiguredInstanceof[$interface])) { throw new InvalidArgumentException(sprintf('"%s" has already been autoconfigured and merge() does not support merging autoconfiguration for the same class/interface.', $interface)); } - $this->automaticInstanceofDefinitions[$interface] = $childDefinition; + $this->autoconfiguredInstanceof[$interface] = $childDefinition; } } @@ -1272,15 +1272,16 @@ public function getExpressionLanguageProviders() * Returns a ChildDefinition that will be used for autoconfiguring the interface/class. * * @param string $interface The class or interface to match + * * @return ChildDefinition */ public function registerForAutoconfiguration($interface) { - if (!isset($this->automaticInstanceofDefinitions[$interface])) { - $this->automaticInstanceofDefinitions[$interface] = new ChildDefinition(''); + if (!isset($this->autoconfiguredInstanceof[$interface])) { + $this->autoconfiguredInstanceof[$interface] = new ChildDefinition(''); } - return $this->automaticInstanceofDefinitions[$interface]; + return $this->autoconfiguredInstanceof[$interface]; } /** @@ -1288,9 +1289,9 @@ public function registerForAutoconfiguration($interface) * * @return ChildDefinition[] */ - public function getAutomaticInstanceofDefinitions() + public function getAutoconfiguredInstanceof() { - return $this->automaticInstanceofDefinitions; + return $this->autoconfiguredInstanceof; } /** diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php index e183fdad42167..4e3c37d87eb72 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php @@ -79,7 +79,7 @@ protected function setDefinition($id, Definition $definition) } $this->instanceof[$id] = $definition; } else { - $this->container->setDefinition($id, $definition->setInstanceofConditionals($this->instanceof)); + $this->container->setDefinition($id, $definition instanceof ChildDefinition ? $definition : $definition->setInstanceofConditionals($this->instanceof)); } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 9f730472d72e1..b9a0f004e73e1 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -215,6 +215,14 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults = if ($this->isLoadingInstanceof) { $definition = new ChildDefinition(''); } elseif ($parent = $service->getAttribute('parent')) { + if (!empty($this->instanceof)) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "instanceof" configuration is defined as using both is not supported. Try moving your child definitions to a different file.', $service->getAttribute('id'))); + } + + if (!empty($defaults)) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "defaults" configuration is defined as using both is not supported. Try moving your child definitions to a different file.', $service->getAttribute('id'))); + } + $definition = new ChildDefinition($parent); if ($value = $service->getAttribute('inherit-tags')) { @@ -255,7 +263,11 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults = } if ($value = $service->getAttribute('autoconfigure')) { - $definition->setAutoconfigured(XmlUtils::phpize($value)); + if (!$definition instanceof ChildDefinition) { + $definition->setAutoconfigured(XmlUtils::phpize($value)); + } elseif ($value = XmlUtils::phpize($value)) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try setting autoconfigure="false" for the service.', $service->getAttribute('id'))); + } } if ($files = $this->getChildren($service, 'file')) { diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index e7703aabf89a9..7ee19e7f6c50c 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -88,7 +88,6 @@ class YamlFileLoader extends FileLoader 'calls' => 'calls', 'tags' => 'tags', 'autowire' => 'autowire', - 'autoconfigure' => 'autoconfigure', ); private static $defaultsKeywords = array( @@ -357,6 +356,14 @@ private function parseDefinition($id, $service, $file, array $defaults) if ($this->isLoadingInstanceof) { $definition = new ChildDefinition(''); } elseif (isset($service['parent'])) { + if (!empty($this->instanceof)) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "_instanceof" configuration is defined as using both is not supported. Try moving your child definitions to a different file.', $id)); + } + + if (!empty($defaults)) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "_defaults" configuration is defined as using both is not supported. Try moving your child definitions to a different file.', $id)); + } + $definition = new ChildDefinition($service['parent']); $inheritTag = isset($service['inherit_tags']) ? $service['inherit_tags'] : (isset($defaults['inherit_tags']) ? $defaults['inherit_tags'] : null); @@ -518,7 +525,11 @@ private function parseDefinition($id, $service, $file, array $defaults) } if (isset($service['autoconfigure'])) { - $definition->setAutoconfigured($service['autoconfigure']); + if (!$definition instanceof ChildDefinition) { + $definition->setAutoconfigured($service['autoconfigure']); + } elseif ($service['autoconfigure']) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try setting "autoconfigure: false" for the service.', $id)); + } } if (array_key_exists('resource', $service)) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php index 0890f53cdbbbe..a367a8b2c4d03 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php @@ -132,4 +132,22 @@ public function testDefinitionDecoratorAliasExistsForBackwardsCompatibility() { $this->assertInstanceOf(ChildDefinition::class, new DefinitionDecorator('foo')); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\BadMethodCallException + */ + public function testCannotCallSetAutoconfigured() + { + $def = new ChildDefinition('foo'); + $def->setAutoconfigured(true); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\BadMethodCallException + */ + public function testCannotCallSetInstanceofConditionals() + { + $def = new ChildDefinition('foo'); + $def->setInstanceofConditionals(array('Foo' => new ChildDefinition(''))); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php index 9d75c0b962186..a1856dfe84828 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php @@ -117,64 +117,86 @@ public function testProcessInlinesWhenThereAreMultipleReferencesButFromTheSameDe $this->assertFalse($container->hasDefinition('c'), 'Service C was not inlined.'); } - public function testInstanceofDefaultsAndParentDefinitionResolution() + /** + * @dataProvider getYamlCompileTests + */ + public function testYamlContainerCompiles($directory, $actualServiceId, $expectedServiceId, ContainerBuilder $mainContainer = null) { - $container = new ContainerBuilder(); + // allow a container to be passed in, which might have autoconfigure settings + $container = $mainContainer ? $mainContainer : new ContainerBuilder(); $container->setResourceTracking(false); + $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Fixtures/yaml/integration/'.$directory)); + $loader->load('main.yml'); + $container->compile(); + $actualService = $container->getDefinition($actualServiceId); - // loading YAML with an expressive test-case in that file - $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Fixtures/yaml')); - $loader->load('services_defaults_instanceof_parent.yml'); + // create a fresh ContainerBuilder, to avoid autoconfigure stuff + $container = new ContainerBuilder(); + $container->setResourceTracking(false); + $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Fixtures/yaml/integration/'.$directory)); + $loader->load('expected.yml'); $container->compile(); + $expectedService = $container->getDefinition($expectedServiceId); + + // reset changes, we don't care if these differ + $actualService->setChanges(array()); + $expectedService->setChanges(array()); + + $this->assertEquals($expectedService, $actualService); + } + + public function getYamlCompileTests() + { + $container = new ContainerBuilder(); + $container->registerForAutoconfiguration(IntegrationTestStub::class); + yield array( + 'autoconfigure_child_not_applied', + 'child_service', + 'child_service_expected', + $container, + ); + + $container = new ContainerBuilder(); + $container->registerForAutoconfiguration(IntegrationTestStub::class); + yield array( + 'autoconfigure_parent_child', + 'child_service', + 'child_service_expected', + $container, + ); + + $container = new ContainerBuilder(); + $container->registerForAutoconfiguration(IntegrationTestStub::class) + ->addTag('from_autoconfigure'); + yield array( + 'autoconfigure_parent_child_tags', + 'child_service', + 'child_service_expected', + $container, + ); + + yield array( + 'child_parent', + 'child_service', + 'child_service_expected', + ); - // instanceof overrides defaults - $simpleService = $container->getDefinition('service_simple'); - $this->assertFalse($simpleService->isAutowired()); - $this->assertFalse($simpleService->isAutoconfigured()); - $this->assertFalse($simpleService->isShared()); - - // all tags are kept - $this->assertEquals( - array( - 'foo_tag' => array(array('tag_option' => 'from_service'), array('tag_option' => 'from_instanceof')), - 'bar_tag' => array(array()), - ), - $simpleService->getTags() + yield array( + 'defaults_instanceof_importance', + 'main_service', + 'main_service_expected', ); - // calls are all kept, but service-level calls are last - $this->assertEquals( - array( - // from instanceof - array('setSunshine', array('bright')), - // from service - array('enableSummer', array(true)), - array('setSunshine', array('warm')), - ), - $simpleService->getMethodCalls() + yield array( + 'defaults_parent_child', + 'child_service', + 'child_service_expected', ); - // service override instanceof - $overrideService = $container->getDefinition('service_override_instanceof'); - $this->assertTrue($overrideService->isAutowired()); - $this->assertTrue($overrideService->isAutoconfigured()); - - // children definitions get no instanceof - $childDef = $container->getDefinition('child_service'); - $this->assertEmpty($childDef->getTags()); - - $childDef2 = $container->getDefinition('child_service_with_parent_instanceof'); - // taken from instanceof applied to parent - $this->assertFalse($childDef2->isAutowired()); - // override the instanceof - $this->assertTrue($childDef2->isShared()); - // tags inherit like normal - $this->assertEquals( - array( - 'foo_tag' => array(array('tag_option' => 'from_child_def'), array('tag_option' => 'from_parent_def'), array('tag_option' => 'from_instanceof')), - 'bar_tag' => array(array()), - ), - $childDef2->getTags() + yield array( + 'instanceof_parent_child', + 'child_service', + 'child_service_expected', ); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php index a2dd9b130d536..9c64c502f659a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php @@ -381,23 +381,6 @@ public function testProcessSetsArguments() $this->assertSame(array(2, 1, 'foo' => 3), $def->getArguments()); } - public function testSetAutoconfiguredOnServiceHasParent() - { - $container = new ContainerBuilder(); - - $container->register('parent', 'stdClass') - ->setAutoconfigured(true) - ; - - $container->setDefinition('child1', new ChildDefinition('parent')) - ->setAutoconfigured(false) - ; - - $this->process($container); - - $this->assertFalse($container->getDefinition('child1')->isAutoconfigured()); - } - public function testSetAutoconfiguredOnServiceIsParent() { $container = new ContainerBuilder(); @@ -410,7 +393,7 @@ public function testSetAutoconfiguredOnServiceIsParent() $this->process($container); - $this->assertTrue($container->getDefinition('child1')->isAutoconfigured()); + $this->assertFalse($container->getDefinition('child1')->isAutoconfigured()); } protected function process(ContainerBuilder $container) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php index 03ef2d40b8250..6467ac7ed4d71 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php @@ -56,9 +56,6 @@ public function testProcessInheritance() )); $def = (new ChildDefinition('parent'))->setClass(self::class); - $def->setInstanceofConditionals(array( - parent::class => (new ChildDefinition(''))->addMethodCall('foo', array('baz')), - )); $container->setDefinition('child', $def); (new ResolveInstanceofConditionalsPass())->process($container); @@ -108,7 +105,7 @@ public function testProcessHandlesMultipleInheritance() $this->assertTrue($def->isShared()); } - public function testProcessUsesAutomaticInstanceofDefinitions() + public function testProcessUsesAutoconfiguredInstanceof() { $container = new ContainerBuilder(); $def = $container->register('normal_service', self::class); @@ -119,24 +116,24 @@ public function testProcessUsesAutomaticInstanceofDefinitions() )); $def->setAutoconfigured(true); $container->registerForAutoconfiguration(parent::class) - ->addTag('automatic_instanceof_tag') + ->addTag('autoconfigured_tag') ->setAutowired(true) - ->setFactory('automatically_set_factory'); + ->setFactory('autoconfigured_factory'); (new ResolveInstanceofConditionalsPass())->process($container); (new ResolveTagsInheritancePass())->process($container); (new ResolveDefinitionTemplatesPass())->process($container); $def = $container->getDefinition('normal_service'); - // autowired thanks to the automatic instanceof + // autowired thanks to the autoconfigured instanceof $this->assertTrue($def->isAutowired()); // factory from the specific instanceof overrides global one $this->assertEquals('locally_set_factory', $def->getFactory()); // tags are merged, the locally set one is first - $this->assertSame(array('local_instanceof_tag' => array(array()), 'automatic_instanceof_tag' => array(array())), $def->getTags()); + $this->assertSame(array('local_instanceof_tag' => array(array()), 'autoconfigured_tag' => array(array())), $def->getTags()); } - public function testProcessDoesNotUseAutomaticInstanceofDefinitionsIfNotEnabled() + public function testProcessDoesNotUseAutoconfiguredInstanceofIfNotEnabled() { $container = new ContainerBuilder(); $def = $container->register('normal_service', self::class); @@ -151,7 +148,6 @@ public function testProcessDoesNotUseAutomaticInstanceofDefinitionsIfNotEnabled( (new ResolveDefinitionTemplatesPass())->process($container); $def = $container->getDefinition('normal_service'); - // no automatic_tag, it was not enabled on the Definition $this->assertFalse($def->isAutowired()); } @@ -171,7 +167,7 @@ public function testBadInterfaceThrowsException() (new ResolveInstanceofConditionalsPass())->process($container); } - public function testBadInterfaceForAutomaticInstanceofIsOkException() + public function testBadInterfaceForAutomaticInstanceofIsOk() { $container = new ContainerBuilder(); $container->register('normal_service', self::class) @@ -182,4 +178,30 @@ public function testBadInterfaceForAutomaticInstanceofIsOkException() (new ResolveInstanceofConditionalsPass())->process($container); $this->assertTrue($container->hasDefinition('normal_service')); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Autoconfigured instanceof for type "PHPUnit\Framework\TestCase" defines method calls but these are not supported and should be removed. + */ + public function testProcessThrowsExceptionForAutoconfiguredCalls() + { + $container = new ContainerBuilder(); + $container->registerForAutoconfiguration(parent::class) + ->addMethodCall('setFoo'); + + (new ResolveInstanceofConditionalsPass())->process($container); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Autoconfigured instanceof for type "PHPUnit\Framework\TestCase" defines arguments but these are not supported and should be removed. + */ + public function testProcessThrowsExceptionForArguments() + { + $container = new ContainerBuilder(); + $container->registerForAutoconfiguration(parent::class) + ->addArgument('bar'); + + (new ResolveInstanceofConditionalsPass())->process($container); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 552898f73d555..05c549bcce2fe 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -573,7 +573,7 @@ public function testMerge() $childDefA = $container->registerForAutoconfiguration('AInterface'); $childDefB = $config->registerForAutoconfiguration('BInterface'); $container->merge($config); - $this->assertSame(array('AInterface' => $childDefA, 'BInterface' => $childDefB), $container->getAutomaticInstanceofDefinitions()); + $this->assertSame(array('AInterface' => $childDefA, 'BInterface' => $childDefB), $container->getAutoconfiguredInstanceof()); } /** @@ -1123,7 +1123,7 @@ public function testRegisterForAutoconfiguration() $container = new ContainerBuilder(); $childDefA = $container->registerForAutoconfiguration('AInterface'); $childDefB = $container->registerForAutoconfiguration('BInterface'); - $this->assertSame(array('AInterface' => $childDefA, 'BInterface' => $childDefB), $container->getAutomaticInstanceofDefinitions()); + $this->assertSame(array('AInterface' => $childDefA, 'BInterface' => $childDefB), $container->getAutoconfiguredInstanceof()); // when called multiple times, the same instance is returned $this->assertSame($childDefA, $container->registerForAutoconfiguration('AInterface')); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services29.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services29.xml index 4ab511ed92dbf..81f1c1a4409a1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services29.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services29.xml @@ -8,11 +8,5 @@ - - - - - - diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_autoconfigure_with_parent.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_autoconfigure_with_parent.xml new file mode 100644 index 0000000000000..103045d38fcb3 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_autoconfigure_with_parent.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_defaults_with_parent.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_defaults_with_parent.xml new file mode 100644 index 0000000000000..875ed6d51f996 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_defaults_with_parent.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_instanceof_with_parent.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_instanceof_with_parent.xml new file mode 100644 index 0000000000000..67ce6917249bd --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_instanceof_with_parent.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_child_not_applied/_child.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_child_not_applied/_child.yml new file mode 100644 index 0000000000000..89d8b914491eb --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_child_not_applied/_child.yml @@ -0,0 +1,4 @@ +services: + child_service: + class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub + parent: parent_service diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_child_not_applied/expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_child_not_applied/expected.yml new file mode 100644 index 0000000000000..ca08caad673f7 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_child_not_applied/expected.yml @@ -0,0 +1,10 @@ +services: + child_service_expected: + class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub + # the parent has autoconfigure true, but that does not cascade to the child + autoconfigure: false + # an autoconfigured "instanceof" is setup for IntegrationTestStub + # but its calls are NOT added, because the class was only + # set on the parent, not the child + #calls: + # - [enableSummer, [true]] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_child_not_applied/main.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_child_not_applied/main.yml new file mode 100644 index 0000000000000..02533bf0f5739 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_child_not_applied/main.yml @@ -0,0 +1,7 @@ +imports: + - { resource: _child.yml } + +services: + parent_service: + autoconfigure: true + abstract: true diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child/_child.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child/_child.yml new file mode 100644 index 0000000000000..5319c2045f93a --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child/_child.yml @@ -0,0 +1,3 @@ +services: + child_service: + parent: parent_service diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child/expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child/expected.yml new file mode 100644 index 0000000000000..c1dca0763cc90 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child/expected.yml @@ -0,0 +1,5 @@ +services: + child_service_expected: + class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub + # autoconfigure is set on the parent, but not on the child + autoconfigure: false diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child/main.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child/main.yml new file mode 100644 index 0000000000000..ab9877d16b9e7 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child/main.yml @@ -0,0 +1,7 @@ +imports: + - { resource: _child.yml } + +services: + parent_service: + class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub + autoconfigure: true diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child_tags/_child.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child_tags/_child.yml new file mode 100644 index 0000000000000..5319c2045f93a --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child_tags/_child.yml @@ -0,0 +1,3 @@ +services: + child_service: + parent: parent_service diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child_tags/expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child_tags/expected.yml new file mode 100644 index 0000000000000..02cf0037e215d --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child_tags/expected.yml @@ -0,0 +1,6 @@ +services: + child_service_expected: + class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub + # from an autoconfigured "instanceof" applied to parent class + # but NOT inherited down to child + # tags: [from_autoconfigure] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child_tags/main.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child_tags/main.yml new file mode 100644 index 0000000000000..ab9877d16b9e7 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/autoconfigure_parent_child_tags/main.yml @@ -0,0 +1,7 @@ +imports: + - { resource: _child.yml } + +services: + parent_service: + class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub + autoconfigure: true diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/child_parent/expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/child_parent/expected.yml new file mode 100644 index 0000000000000..54cd91c2022a8 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/child_parent/expected.yml @@ -0,0 +1,9 @@ +services: + # child_service in the end should be identical to this + child_service_expected: + class: stdClass + autowire: false + public: true + lazy: true + # ONLY the child tag, the parent tag does not inherit + tags: [from_child] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/child_parent/main.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/child_parent/main.yml new file mode 100644 index 0000000000000..edaa3a3b43993 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/child_parent/main.yml @@ -0,0 +1,13 @@ +services: + parent_service: + abstract: true + lazy: true + autowire: false + public: false + tags: [from_parent] + + child_service: + class: stdClass + parent: parent_service + public: true + tags: [from_child] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_instanceof_importance/expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_instanceof_importance/expected.yml new file mode 100644 index 0000000000000..4edeffa7c3053 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_instanceof_importance/expected.yml @@ -0,0 +1,27 @@ +services: + # main_service should look like this in the end + main_service_expected: + class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub + # _instanceof overrides _defaults + autowire: false + # inherited from _defaults + autoconfigure: true + # from _instanceof + shared: false + # service definition overrides _instanceof + public: true + + tags: + - { name: foo_tag, tag_option: from_service } + # these 2 are from instanceof + - { name: foo_tag, tag_option: from_instanceof } + - { name: bar_tag } + # the tag from defaults do NOT cascade (but see #22530) + # - { name: from_defaults } + # calls from instanceof are kept, but this comes later + calls: + # first call is from instanceof + - [setSunshine, [bright]] + # + - [enableSummer, [true]] + - [setSunshine, [warm]] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_instanceof_importance/main.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_instanceof_importance/main.yml new file mode 100644 index 0000000000000..406a351d1d3ef --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_instanceof_importance/main.yml @@ -0,0 +1,30 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: true + tags: [from_defaults] + + _instanceof: + Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStubParent: + autowire: false + shared: false + public: false + tags: + - { name: foo_tag, tag_option: from_instanceof } + calls: + - [setSunshine, [bright]] + + Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub: + tags: + - { name: bar_tag } + + main_service: + class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub + public: true + tags: + - { name: foo_tag, tag_option: from_service } + # calls from instanceof are kept, but this comes later + calls: + - [enableSummer, [true]] + - [setSunshine, [warm]] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_parent_child/_child.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_parent_child/_child.yml new file mode 100644 index 0000000000000..86ef83c26dfca --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_parent_child/_child.yml @@ -0,0 +1,4 @@ +services: + # loaded here to avoid defaults in other file + child_service: + parent: parent_service diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_parent_child/expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_parent_child/expected.yml new file mode 100644 index 0000000000000..012672ff8b8fb --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_parent_child/expected.yml @@ -0,0 +1,6 @@ +services: + child_service_expected: + class: stdClass + # _defaults is applied to the parent, but autoconfigure: true + # does not cascade to the child + autoconfigure: false diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_parent_child/main.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_parent_child/main.yml new file mode 100644 index 0000000000000..8b90b4e985892 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/defaults_parent_child/main.yml @@ -0,0 +1,9 @@ +imports: + - { resource: _child.yml } + +services: + _defaults: + autoconfigure: true + + parent_service: + class: stdClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/instanceof_parent_child/_child.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/instanceof_parent_child/_child.yml new file mode 100644 index 0000000000000..86ef83c26dfca --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/instanceof_parent_child/_child.yml @@ -0,0 +1,4 @@ +services: + # loaded here to avoid defaults in other file + child_service: + parent: parent_service diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/instanceof_parent_child/expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/instanceof_parent_child/expected.yml new file mode 100644 index 0000000000000..074ed01d03c4c --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/instanceof_parent_child/expected.yml @@ -0,0 +1,7 @@ +services: + child_service_expected: + class: stdClass + # applied to _instanceof of parent + autowire: true + # from _instanceof, applies to parent, but does NOT inherit to here + # tags: [from_instanceof] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/instanceof_parent_child/main.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/instanceof_parent_child/main.yml new file mode 100644 index 0000000000000..44cf9b0045d40 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/integration/instanceof_parent_child/main.yml @@ -0,0 +1,11 @@ +imports: + - { resource: _child.yml } + +services: + _instanceof: + stdClass: + autowire: true + tags: [from_instanceof] + + parent_service: + class: stdClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services28.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services28.yml index 99f72f1f94ac4..cacebf469cf2e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services28.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services28.yml @@ -22,19 +22,6 @@ services: autowire: false tags: [] - no_defaults_child: - parent: no_defaults - autowire: ~ - tags: - - name: bar - - with_defaults_child: - parent: with_defaults - public: true - inherit_tags: true - tags: - - name: baz - with_defaults_aliased: alias: with_defaults diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_autoconfigure_with_parent.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_autoconfigure_with_parent.yml new file mode 100644 index 0000000000000..c6e3080192a7e --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_autoconfigure_with_parent.yml @@ -0,0 +1,8 @@ +services: + parent_service: + class: stdClass + + child_service: + class: stdClass + autoconfigure: true + parent: parent_service diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_defaults_instanceof_parent.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_defaults_instanceof_parent.yml deleted file mode 100644 index 9e332a8405b0b..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_defaults_instanceof_parent.yml +++ /dev/null @@ -1,57 +0,0 @@ -services: - _defaults: - autowire: true - autoconfigure: true - - _instanceof: - Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStubParent: - # should override _defaults - autowire: false - autoconfigure: false - shared: false - tags: - - { name: foo_tag, tag_option: from_instanceof } - calls: - - [setSunshine, [bright]] - - # a second instanceof that will be applied - Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub: - tags: - - { name: bar_tag } - - service_simple: - class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub - tags: - - { name: foo_tag, tag_option: from_service } - # calls from instanceof are kept, but this comes later - calls: - - [enableSummer, [true]] - - [setSunshine, [warm]] - - service_override_instanceof: - class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub - # override instanceof - autowire: true - autoconfigure: true - - parent_service: - abstract: true - lazy: true - - # instanceof will not be applied to this - child_service: - class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub - parent: parent_service - - parent_service_with_class: - abstract: true - class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub - tags: - - { name: foo_tag, tag_option: from_parent_def } - - child_service_with_parent_instanceof: - parent: parent_service_with_class - shared: true - inherit_tags: true - tags: - - { name: foo_tag, tag_option: from_child_def } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_defaults_with_parent.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_defaults_with_parent.yml new file mode 100644 index 0000000000000..28dec4ce91791 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_defaults_with_parent.yml @@ -0,0 +1,10 @@ +services: + _defaults: + autowire: true + + parent_service: + class: stdClass + + child_service: + class: stdClass + parent: parent_service diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_instanceof_with_parent.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_instanceof_with_parent.yml new file mode 100644 index 0000000000000..fb21cdf2fb674 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_instanceof_with_parent.yml @@ -0,0 +1,11 @@ +services: + _instanceof: + FooInterface: + autowire: true + + parent_service: + class: stdClass + + child_service: + class: stdClass + parent: parent_service diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 3b6ddd7fcb862..6f85d2ee16be4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -651,20 +651,13 @@ public function testDefaults() $this->assertArrayNotHasKey('public', $container->getDefinition('with_defaults')->getChanges()); $this->assertArrayNotHasKey('autowire', $container->getDefinition('with_defaults')->getChanges()); - $this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges()); - $this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges()); - $container->compile(); $this->assertTrue($container->getDefinition('no_defaults')->isPublic()); - $this->assertTrue($container->getDefinition('no_defaults_child')->isPublic()); $this->assertSame(array(), $container->getDefinition('no_defaults')->getTags()); - $this->assertSame(array('bar' => array(array())), $container->getDefinition('no_defaults_child')->getTags()); - $this->assertSame(array('baz' => array(array()), 'foo' => array(array())), $container->getDefinition('with_defaults_child')->getTags()); $this->assertFalse($container->getDefinition('no_defaults')->isAutowired()); - $this->assertFalse($container->getDefinition('no_defaults_child')->isAutowired()); } public function testNamedArguments() @@ -694,6 +687,42 @@ public function testInstanceof() $this->assertSame(array('foo' => array(array()), 'bar' => array(array())), $definition->getTags()); } + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage The service "child_service" cannot use the "parent" option in the same file where "instanceof" configuration is defined as using both is not supported. Try moving your child definitions to a different file. + */ + public function testInstanceOfAndChildDefinitionNotAllowed() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services_instanceof_with_parent.xml'); + $container->compile(); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage The service "child_service" cannot have a "parent" and also have "autoconfigure". Try setting autoconfigure="false" for the service. + */ + public function testAutoConfigureAndChildDefinitionNotAllowed() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services_autoconfigure_with_parent.xml'); + $container->compile(); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage The service "child_service" cannot use the "parent" option in the same file where "defaults" configuration is defined as using both is not supported. Try moving your child definitions to a different file. + */ + public function testDefaultsAndChildDefinitionNotAllowed() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services_defaults_with_parent.xml'); + $container->compile(); + } + public function testAutoConfigureInstanceof() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 87a05eb2abd1f..e20575d2aa8f7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -403,9 +403,6 @@ public function testDefaults() $this->assertFalse($container->getAlias('with_defaults_aliased')->isPublic()); $this->assertFalse($container->getAlias('with_defaults_aliased_short')->isPublic()); - $this->assertArrayNotHasKey('public', $container->getDefinition('no_defaults_child')->getChanges()); - $this->assertArrayNotHasKey('autowire', $container->getDefinition('no_defaults_child')->getChanges()); - $this->assertFalse($container->getDefinition('Acme\WithShortCutArgs')->isPublic()); $this->assertSame(array('foo' => array(array())), $container->getDefinition('Acme\WithShortCutArgs')->getTags()); $this->assertTrue($container->getDefinition('Acme\WithShortCutArgs')->isAutowired()); @@ -414,16 +411,12 @@ public function testDefaults() $this->assertTrue($container->getDefinition('with_null')->isPublic()); $this->assertTrue($container->getDefinition('no_defaults')->isPublic()); - $this->assertTrue($container->getDefinition('no_defaults_child')->isPublic()); $this->assertSame(array(), $container->getDefinition('with_null')->getTags()); $this->assertSame(array(), $container->getDefinition('no_defaults')->getTags()); - $this->assertSame(array('bar' => array(array())), $container->getDefinition('no_defaults_child')->getTags()); - $this->assertSame(array('baz' => array(array()), 'foo' => array(array())), $container->getDefinition('with_defaults_child')->getTags()); $this->assertTrue($container->getDefinition('with_null')->isAutowired()); $this->assertFalse($container->getDefinition('no_defaults')->isAutowired()); - $this->assertFalse($container->getDefinition('no_defaults_child')->isAutowired()); } public function testNamedArguments() @@ -455,6 +448,42 @@ public function testInstanceof() $this->assertSame(array('foo' => array(array()), 'bar' => array(array())), $definition->getTags()); } + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage The service "child_service" cannot use the "parent" option in the same file where "_instanceof" configuration is defined as using both is not supported. Try moving your child definitions to a different file. + */ + public function testInstanceOfAndChildDefinitionNotAllowed() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_instanceof_with_parent.yml'); + $container->compile(); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage The service "child_service" cannot have a "parent" and also have "autoconfigure". Try setting "autoconfigure: false" for the service. + */ + public function testAutoConfigureAndChildDefinitionNotAllowed() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_autoconfigure_with_parent.yml'); + $container->compile(); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage The service "child_service" cannot use the "parent" option in the same file where "_defaults" configuration is defined as using both is not supported. Try moving your child definitions to a different file. + */ + public function testDefaultsAndChildDefinitionNotAllowed() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_defaults_with_parent.yml'); + $container->compile(); + } + /** * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException * @expectedExceptionMessage The value of the "decorates" option for the "bar" service must be the id of the service without the "@" prefix (replace "@foo" with "foo").