From f455d1bd976054352136cc0f465dabdff92fff8e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 12 Feb 2019 11:56:23 +0100 Subject: [PATCH] [DI] Add support for "wither" methods - for greater immutable services --- .../Console/Descriptor/XmlDescriptor.php | 3 + .../Compiler/AnalyzeServiceReferencesPass.php | 34 +++++++++- .../Compiler/AutowireRequiredMethodsPass.php | 16 ++++- .../DependencyInjection/ContainerBuilder.php | 28 ++++++-- .../DependencyInjection/Definition.php | 11 +-- .../DependencyInjection/Dumper/PhpDumper.php | 33 +++++++-- .../DependencyInjection/Dumper/XmlDumper.php | 3 + .../Loader/XmlFileLoader.php | 2 +- .../Loader/YamlFileLoader.php | 4 +- .../schema/dic/services/services-1.0.xsd | 1 + .../AutowireRequiredMethodsPassTest.php | 22 ++++++ .../Tests/ContainerBuilderTest.php | 19 ++++++ .../Tests/DefinitionTest.php | 6 ++ .../Tests/Dumper/PhpDumperTest.php | 25 +++++++ .../Fixtures/includes/autowiring_classes.php | 33 +++++++++ .../Tests/Fixtures/php/services_wither.php | 68 +++++++++++++++++++ 16 files changed, 286 insertions(+), 22 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_wither.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php index db0f346ebd..956e0ce44a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php @@ -348,6 +348,9 @@ class XmlDescriptor extends Descriptor foreach ($calls as $callData) { $callsXML->appendChild($callXML = $dom->createElement('call')); $callXML->setAttribute('method', $callData[0]); + if ($callData[2] ?? false) { + $callXML->setAttribute('returns-clone', 'true'); + } } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php index 2dafb53789..d10ee4575b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php @@ -140,11 +140,41 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe $this->byConstructor = true; $this->processValue($value->getFactory()); $this->processValue($value->getArguments()); + + $properties = $value->getProperties(); + $setters = $value->getMethodCalls(); + + // Any references before a "wither" are part of the constructor-instantiation graph + $lastWitherIndex = null; + foreach ($setters as $k => $call) { + if ($call[2] ?? false) { + $lastWitherIndex = $k; + } + } + + if (null !== $lastWitherIndex) { + $this->processValue($properties); + $setters = $properties = []; + + foreach ($value->getMethodCalls() as $k => $call) { + if (null === $lastWitherIndex) { + $setters[] = $call; + continue; + } + + if ($lastWitherIndex === $k) { + $lastWitherIndex = null; + } + + $this->processValue($call); + } + } + $this->byConstructor = $byConstructor; if (!$this->onlyConstructorArguments) { - $this->processValue($value->getProperties()); - $this->processValue($value->getMethodCalls()); + $this->processValue($properties); + $this->processValue($setters); $this->processValue($value->getConfigurator()); } $this->lazy = $lazy; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php index efb9df7b94..20d31135a7 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php @@ -35,6 +35,7 @@ class AutowireRequiredMethodsPass extends AbstractRecursivePass } $alreadyCalledMethods = []; + $withers = []; foreach ($value->getMethodCalls() as list($method)) { $alreadyCalledMethods[strtolower($method)] = true; @@ -50,7 +51,11 @@ class AutowireRequiredMethodsPass extends AbstractRecursivePass while (true) { if (false !== $doc = $r->getDocComment()) { if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) { - $value->addMethodCall($reflectionMethod->name); + if (preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@return\s++static[\s\*]#i', $doc)) { + $withers[] = [$reflectionMethod->name, [], true]; + } else { + $value->addMethodCall($reflectionMethod->name, []); + } break; } if (false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) { @@ -65,6 +70,15 @@ class AutowireRequiredMethodsPass extends AbstractRecursivePass } } + if ($withers) { + // Prepend withers to prevent creating circular loops + $setters = $value->getMethodCalls(); + $value->setMethodCalls($withers); + foreach ($setters as $call) { + $value->addMethodCall($call[0], $call[1], $call[2] ?? false); + } + } + return $value; } } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 943df8d314..6da41d35af 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1139,8 +1139,15 @@ class ContainerBuilder extends Container implements TaggedContainerInterface } } - if ($tryProxy || !$definition->isLazy()) { - // share only if proxying failed, or if not a proxy + $lastWitherIndex = null; + foreach ($definition->getMethodCalls() as $k => $call) { + if ($call[2] ?? false) { + $lastWitherIndex = $k; + } + } + + if (null === $lastWitherIndex && ($tryProxy || !$definition->isLazy())) { + // share only if proxying failed, or if not a proxy, and if no withers are found $this->shareService($definition, $service, $id, $inlineServices); } @@ -1149,8 +1156,13 @@ class ContainerBuilder extends Container implements TaggedContainerInterface $service->$name = $value; } - foreach ($definition->getMethodCalls() as $call) { - $this->callMethod($service, $call, $inlineServices); + foreach ($definition->getMethodCalls() as $k => $call) { + $service = $this->callMethod($service, $call, $inlineServices); + + if ($lastWitherIndex === $k && ($tryProxy || !$definition->isLazy())) { + // share only if proxying failed, or if not a proxy, and this is the last wither + $this->shareService($definition, $service, $id, $inlineServices); + } } if ($callable = $definition->getConfigurator()) { @@ -1568,16 +1580,18 @@ class ContainerBuilder extends Container implements TaggedContainerInterface { foreach (self::getServiceConditionals($call[1]) as $s) { if (!$this->has($s)) { - return; + return $service; } } foreach (self::getInitializedConditionals($call[1]) as $s) { if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) { - return; + return $service; } } - $service->{$call[0]}(...$this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices)); + $result = $service->{$call[0]}(...$this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices)); + + return empty($call[2]) ? $service : $result; } /** diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index b79a8c9a82..857176c44f 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -330,7 +330,7 @@ class Definition { $this->calls = []; foreach ($calls as $call) { - $this->addMethodCall($call[0], $call[1]); + $this->addMethodCall($call[0], $call[1], $call[2] ?? false); } return $this; @@ -339,19 +339,20 @@ class Definition /** * Adds a method to call after service initialization. * - * @param string $method The method name to call - * @param array $arguments An array of arguments to pass to the method call + * @param string $method The method name to call + * @param array $arguments An array of arguments to pass to the method call + * @param bool $returnsClone Whether the call returns the service instance or not * * @return $this * * @throws InvalidArgumentException on empty $method param */ - public function addMethodCall($method, array $arguments = []) + public function addMethodCall($method, array $arguments = []/*, bool $returnsClone = false*/) { if (empty($method)) { throw new InvalidArgumentException('Method name cannot be empty.'); } - $this->calls[] = [$method, $arguments]; + $this->calls[] = 2 < \func_num_args() && \func_get_arg(2) ? [$method, $arguments, true] : [$method, $arguments]; return $this; } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 4cf663b3dd..1c4bcf23c0 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -506,7 +506,14 @@ EOF; $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); $instantiation = ''; - if (!$isProxyCandidate && $definition->isShared() && !isset($this->singleUsePrivateIds[$id])) { + $lastWitherIndex = null; + foreach ($definition->getMethodCalls() as $k => $call) { + if ($call[2] ?? false) { + $lastWitherIndex = $k; + } + } + + if (!$isProxyCandidate && $definition->isShared() && !isset($this->singleUsePrivateIds[$id]) && null === $lastWitherIndex) { $instantiation = sprintf('$this->%s[\'%s\'] = %s', $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $id, $isSimpleInstance ? '' : '$instance'); } elseif (!$isSimpleInstance) { $instantiation = '$instance'; @@ -563,16 +570,32 @@ EOF; return true; } - private function addServiceMethodCalls(Definition $definition, string $variableName = 'instance'): string + private function addServiceMethodCalls(Definition $definition, string $variableName, ?string $sharedNonLazyId): string { + $lastWitherIndex = null; + foreach ($definition->getMethodCalls() as $k => $call) { + if ($call[2] ?? false) { + $lastWitherIndex = $k; + } + } + $calls = ''; - foreach ($definition->getMethodCalls() as $call) { + foreach ($definition->getMethodCalls() as $k => $call) { $arguments = []; foreach ($call[1] as $value) { $arguments[] = $this->dumpValue($value); } - $calls .= $this->wrapServiceConditionals($call[1], sprintf(" \$%s->%s(%s);\n", $variableName, $call[0], implode(', ', $arguments))); + $witherAssignation = ''; + + if ($call[2] ?? false) { + if (null !== $sharedNonLazyId && $lastWitherIndex === $k) { + $witherAssignation = sprintf('$this->%s[\'%s\'] = ', $definition->isPublic() ? 'services' : 'privates', $sharedNonLazyId); + } + $witherAssignation .= sprintf('$%s = ', $variableName); + } + + $calls .= $this->wrapServiceConditionals($call[1], sprintf(" %s\$%s->%s(%s);\n", $witherAssignation, $variableName, $call[0], implode(', ', $arguments))); } return $calls; @@ -814,7 +837,7 @@ EOTXT } $code .= $this->addServiceProperties($inlineDef, $name); - $code .= $this->addServiceMethodCalls($inlineDef, $name); + $code .= $this->addServiceMethodCalls($inlineDef, $name, !$this->getProxyDumper()->isProxyCandidate($inlineDef) && $inlineDef->isShared() && !isset($this->singleUsePrivateIds[$id]) ? $id : null); $code .= $this->addServiceConfigurator($inlineDef, $name); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index eb56becd8d..79b316336d 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -84,6 +84,9 @@ class XmlDumper extends Dumper if (\count($methodcall[1])) { $this->convertParameters($methodcall[1], 'argument', $call); } + if ($methodcall[2] ?? false) { + $call->setAttribute('returns-clone', 'true'); + } $parent->appendChild($call); } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index b5e076888f..c29bf1dd1d 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -337,7 +337,7 @@ class XmlFileLoader extends FileLoader } foreach ($this->getChildren($service, 'call') as $call) { - $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file)); + $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file), XmlUtils::phpize($call->getAttribute('returns-clone'))); } $tags = $this->getChildren($service, 'tag'); diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 06fcbb4a91..a03cb6118b 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -463,15 +463,17 @@ class YamlFileLoader extends FileLoader if (isset($call['method'])) { $method = $call['method']; $args = isset($call['arguments']) ? $this->resolveServices($call['arguments'], $file) : []; + $returnsClone = $call['returns_clone'] ?? false; } else { $method = $call[0]; $args = isset($call[1]) ? $this->resolveServices($call[1], $file) : []; + $returnsClone = $call[2] ?? false; } if (!\is_array($args)) { throw new InvalidArgumentException(sprintf('The second parameter for function call "%s" must be an array of its arguments for service "%s" in %s. Check your YAML syntax.', $method, $id, $file)); } - $definition->addMethodCall($method, $args); + $definition->addMethodCall($method, $args, $returnsClone); } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd index b14ffc8dcd..6db5d0b7a4 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd +++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd @@ -243,6 +243,7 @@ + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireRequiredMethodsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireRequiredMethodsPassTest.php index 644b32d204..653e27ea53 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireRequiredMethodsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireRequiredMethodsPassTest.php @@ -77,4 +77,26 @@ class AutowireRequiredMethodsPassTest extends TestCase ); $this->assertEquals([], $methodCalls[0][1]); } + + public function testWitherInjection() + { + $container = new ContainerBuilder(); + $container->register(Foo::class); + + $container + ->register('wither', Wither::class) + ->setAutowired(true); + + (new ResolveClassPass())->process($container); + (new AutowireRequiredMethodsPass())->process($container); + + $methodCalls = $container->getDefinition('wither')->getMethodCalls(); + + $expected = [ + ['withFoo1', [], true], + ['withFoo2', [], true], + ['setFoo', []], + ]; + $this->assertSame($expected, $methodCalls); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index e6c0b26455..42aa565bc8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\DependencyInjection\Tests; +require_once __DIR__.'/Fixtures/includes/autowiring_classes.php'; require_once __DIR__.'/Fixtures/includes/classes.php'; require_once __DIR__.'/Fixtures/includes/ProjectExtension.php'; @@ -36,6 +37,8 @@ use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBa use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\DependencyInjection\Tests\Compiler\Foo; +use Symfony\Component\DependencyInjection\Tests\Compiler\Wither; use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass; use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition; use Symfony\Component\DependencyInjection\Tests\Fixtures\SimilarArgumentsDummy; @@ -1565,6 +1568,22 @@ class ContainerBuilderTest extends TestCase $this->assertSame(['service_container'], array_keys($container->getDefinitions())); } + + public function testWither() + { + $container = new ContainerBuilder(); + $container->register(Foo::class); + + $container + ->register('wither', Wither::class) + ->setPublic(true) + ->setAutowired(true); + + $container->compile(); + + $wither = $container->get('wither'); + $this->assertInstanceOf(Foo::class, $wither->foo); + } } class FooClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php index 3462726943..c464798964 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php @@ -95,10 +95,16 @@ class DefinitionTest extends TestCase $this->assertEquals([['foo', ['foo']]], $def->getMethodCalls(), '->getMethodCalls() returns the methods to call'); $this->assertSame($def, $def->addMethodCall('bar', ['bar']), '->addMethodCall() implements a fluent interface'); $this->assertEquals([['foo', ['foo']], ['bar', ['bar']]], $def->getMethodCalls(), '->addMethodCall() adds a method to call'); + $this->assertSame($def, $def->addMethodCall('foobar', ['foobar'], true), '->addMethodCall() implements a fluent interface with third parameter'); + $this->assertEquals([['foo', ['foo']], ['bar', ['bar']], ['foobar', ['foobar'], true]], $def->getMethodCalls(), '->addMethodCall() adds a method to call'); $this->assertTrue($def->hasMethodCall('bar'), '->hasMethodCall() returns true if first argument is a method to call registered'); $this->assertFalse($def->hasMethodCall('no_registered'), '->hasMethodCall() returns false if first argument is not a method to call registered'); $this->assertSame($def, $def->removeMethodCall('bar'), '->removeMethodCall() implements a fluent interface'); + $this->assertTrue($def->hasMethodCall('foobar'), '->hasMethodCall() returns true if first argument is a method to call registered'); + $this->assertSame($def, $def->removeMethodCall('foobar'), '->removeMethodCall() implements a fluent interface'); $this->assertEquals([['foo', ['foo']]], $def->getMethodCalls(), '->removeMethodCall() removes a method to call'); + $this->assertSame($def, $def->setMethodCalls([['foobar', ['foobar'], true]]), '->setMethodCalls() implements a fluent interface with third parameter'); + $this->assertEquals([['foobar', ['foobar'], true]], $def->getMethodCalls(), '->addMethodCall() adds a method to call'); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 828439969e..481947de57 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -30,6 +30,8 @@ use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\DependencyInjection\Tests\Compiler\Foo; +use Symfony\Component\DependencyInjection\Tests\Compiler\Wither; use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition; use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator; use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber; @@ -37,6 +39,7 @@ use Symfony\Component\DependencyInjection\TypedReference; use Symfony\Component\DependencyInjection\Variable; use Symfony\Component\ExpressionLanguage\Expression; +require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php'; require_once __DIR__.'/../Fixtures/includes/classes.php'; class PhpDumperTest extends TestCase @@ -1170,6 +1173,28 @@ class PhpDumperTest extends TestCase $container->set('foo5', $foo5 = new \stdClass()); $this->assertSame($foo5, $locator->get('foo5')); } + + public function testWither() + { + $container = new ContainerBuilder(); + $container->register(Foo::class); + + $container + ->register('wither', Wither::class) + ->setPublic(true) + ->setAutowired(true); + + $container->compile(); + $dumper = new PhpDumper($container); + $dump = $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Service_Wither']); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_wither.php', $dump); + eval('?>'.$dump); + + $container = new \Symfony_DI_PhpDumper_Service_Wither(); + + $wither = $container->get('wither'); + $this->assertInstanceOf(Foo::class, $wither->foo); + } } class Rot13EnvVarProcessor implements EnvVarProcessorInterface diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php index a2f8721683..504ed26da3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php @@ -278,6 +278,39 @@ class SetterInjection extends SetterInjectionParent } } +class Wither +{ + public $foo; + + /** + * @required + */ + public function setFoo(Foo $foo) + { + } + + /** + * @required + * @return static + */ + public function withFoo1(Foo $foo) + { + return $this->withFoo2($foo); + } + + /** + * @required + * @return static + */ + public function withFoo2(Foo $foo) + { + $new = clone $this; + $new->foo = $foo; + + return $new; + } +} + class SetterInjectionParent { /** @required*/ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_wither.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_wither.php new file mode 100644 index 0000000000..c8a0d03588 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_wither.php @@ -0,0 +1,68 @@ +services = $this->privates = []; + $this->methodMap = [ + 'wither' => 'getWitherService', + ]; + + $this->aliases = []; + } + + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + public function isCompiled() + { + return true; + } + + public function getRemovedIds() + { + return [ + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\Foo' => true, + ]; + } + + /** + * Gets the public 'wither' shared autowired service. + * + * @return \Symfony\Component\DependencyInjection\Tests\Compiler\Wither + */ + protected function getWitherService() + { + $instance = new \Symfony\Component\DependencyInjection\Tests\Compiler\Wither(); + + $a = new \Symfony\Component\DependencyInjection\Tests\Compiler\Foo(); + + $instance = $instance->withFoo1($a); + $this->services['wither'] = $instance = $instance->withFoo2($a); + $instance->setFoo($a); + + return $instance; + } +}