diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 9ca5dc07ee5bb..bbe164bacf575 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 4.4.0 ----- + * added support for dumping the container in one file instead of many files * deprecated support for short factories and short configurators in Yaml * deprecated `tagged` in favor of `tagged_iterator` * deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition` diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 2228bdc00f598..71069466e786e 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -72,6 +72,7 @@ class PhpDumper extends Dumper private $namespace; private $asFiles; private $hotPathTag; + private $inlineFactories; private $inlineRequires; private $inlinedRequires = []; private $circularReferences = []; @@ -134,6 +135,7 @@ public function dump(array $options = []) 'as_files' => false, 'debug' => true, 'hot_path_tag' => 'container.hot_path', + 'inline_factories_parameter' => 'container.dumper.inline_factories', 'inline_class_loader_parameter' => 'container.dumper.inline_class_loader', 'service_locator_tag' => 'container.service_locator', 'build_time' => time(), @@ -143,6 +145,7 @@ public function dump(array $options = []) $this->namespace = $options['namespace']; $this->asFiles = $options['as_files']; $this->hotPathTag = $options['hot_path_tag']; + $this->inlineFactories = $this->asFiles && $options['inline_factories_parameter'] && $this->container->hasParameter($options['inline_factories_parameter']) && $this->container->getParameter($options['inline_factories_parameter']); $this->inlineRequires = $options['inline_class_loader_parameter'] && $this->container->hasParameter($options['inline_class_loader_parameter']) && $this->container->getParameter($options['inline_class_loader_parameter']); $this->serviceLocatorTag = $options['service_locator_tag']; @@ -215,6 +218,8 @@ public function dump(array $options = []) } } + $proxyClasses = $this->inlineFactories ? $this->generateProxyClasses() : null; + $code = $this->startClass($options['class'], $baseClass, $baseClassWithNamespace). $this->addServices($services). @@ -222,6 +227,8 @@ public function dump(array $options = []) $this->addDefaultParametersMethod() ; + $proxyClasses = $proxyClasses ?? $this->generateProxyClasses(); + if ($this->addGetService) { $code = preg_replace( "/(\r?\n\r?\n public function __construct.+?\\{\r?\n)/s", @@ -258,13 +265,24 @@ public function dump(array $options = []) $files['removed-ids.php'] = $c .= "];\n"; } - foreach ($this->generateServiceFiles($services) as $file => $c) { - $files[$file] = $fileStart.$c; + if (!$this->inlineFactories) { + foreach ($this->generateServiceFiles($services) as $file => $c) { + $files[$file] = $fileStart.$c; + } + foreach ($proxyClasses as $file => $c) { + $files[$file] = "generateProxyClasses() as $file => $c) { - $files[$file] = "endClass(); + + if ($this->inlineFactories) { + foreach ($proxyClasses as $c) { + $code .= $c; + } } - $files[$options['class'].'.php'] = $code.$this->endClass(); + + $files[$options['class'].'.php'] = $code; $hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx')); $code = []; @@ -303,7 +321,7 @@ public function dump(array $options = []) EOF; } else { $code .= $this->endClass(); - foreach ($this->generateProxyClasses() as $c) { + foreach ($proxyClasses as $c) { $code .= $c; } } @@ -422,8 +440,9 @@ private function collectLineage($class, array &$lineage) $lineage[$class] = substr($exportedFile, 1, -1); } - private function generateProxyClasses() + private function generateProxyClasses(): array { + $proxyClasses = []; $alreadyGenerated = []; $definitions = $this->container->getDefinitions(); $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments'); @@ -442,19 +461,39 @@ private function generateProxyClasses() if ("\n" === $proxyCode = "\n".$proxyDumper->getProxyCode($definition)) { continue; } + + if ($this->inlineRequires) { + $lineage = []; + $this->collectLineage($class, $lineage); + + $code = ''; + foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) { + if ($this->inlineFactories) { + $this->inlinedRequires[$file] = true; + } + $file = preg_replace('#^\\$this->targetDirs\[(\d++)\]#', sprintf('\dirname(__DIR__, %d + $1)', $this->asFiles), $file); + $code .= sprintf("include_once %s;\n", $file); + } + + $proxyCode = $code.$proxyCode; + } + if ($strip) { $proxyCode = " $proxyCode; + + $proxyClasses[sprintf('%s.php', explode(' ', $proxyCode, 3)[1])] = $proxyCode; } + + return $proxyClasses; } private function addServiceInclude(string $cId, Definition $definition): string { $code = ''; - if ($this->inlineRequires && !$this->isHotPath($definition)) { + if ($this->inlineRequires && (!$this->isHotPath($definition) || $this->getProxyDumper()->isProxyCandidate($definition))) { $lineage = []; foreach ($this->inlinedDefinitions as $def) { if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) { @@ -685,7 +724,7 @@ private function addService(string $id, Definition $definition): array $lazyInitialization = ''; } - $asFile = $this->asFiles && !$this->isHotPath($definition); + $asFile = $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition); $methodName = $this->generateMethodName($id); if ($asFile) { $file = $methodName.'.php'; @@ -711,17 +750,16 @@ protected function {$methodName}($lazyInitialization) $this->serviceCalls = []; $this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls); - $code .= $this->addServiceInclude($id, $definition); + if ($definition->isDeprecated()) { + $code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id))); + } if ($this->getProxyDumper()->isProxyCandidate($definition)) { $factoryCode = $asFile ? ($definition->isShared() ? "\$this->load('%s.php', false)" : '$this->factories[%2$s](false)') : '$this->%s(false)'; $code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName, $this->doExport($id))); } - if ($definition->isDeprecated()) { - $code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id))); - } - + $code .= $this->addServiceInclude($id, $definition); $code .= $this->addInlineService($id, $definition); if ($asFile) { @@ -1024,7 +1062,7 @@ public function __construct() $code .= $this->addSyntheticIds(); $code .= $this->addMethodMap(); - $code .= $this->asFiles ? $this->addFileMap() : ''; + $code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : ''; $code .= $this->addAliases(); $code .= $this->addInlineRequires(); $code .= <<addRemovedIds(); - if ($this->asFiles) { + if ($this->asFiles && !$this->inlineFactories) { $code .= <<isProxyCandidate($definition)) { continue; } - if ($this->asFiles) { + if ($this->asFiles && !$this->inlineFactories) { $proxyLoader = '$this->load("{$class}.php")'; - } elseif ($this->namespace) { - $proxyLoader = 'class_alias("'.$this->namespace.'\\\\{$class}", $class, false)'; + } elseif ($this->namespace || $this->inlineFactories) { + $proxyLoader = 'class_alias(__NAMESPACE__."\\\\$class", $class, false)'; } else { $proxyLoader = ''; } @@ -1140,7 +1178,7 @@ private function addMethodMap(): string $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { - if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->isHotPath($definition))) { + if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->inlineFactories || $this->isHotPath($definition))) { $code .= ' '.$this->doExport($id).' => '.$this->doExport($this->generateMethodName($id)).",\n"; } } @@ -1237,6 +1275,11 @@ private function addInlineRequires(): string foreach ($this->container->findTaggedServiceIds($this->hotPathTag) as $id => $tags) { $definition = $this->container->getDefinition($id); + + if ($this->getProxyDumper()->isProxyCandidate($definition)) { + continue; + } + $inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]); foreach ($inlinedDefinitions as $def) { @@ -1578,7 +1621,7 @@ private function dumpValue($value, bool $interpolate = true): string continue; } $definition = $this->container->findDefinition($id = (string) $v); - $load = !($definition->hasErrors() && $e = $definition->getErrors()) ? $this->asFiles && !$this->isHotPath($definition) : reset($e); + $load = !($definition->hasErrors() && $e = $definition->getErrors()) ? $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition) : reset($e); $serviceMap .= sprintf("\n %s => [%s, %s, %s, %s],", $this->export($k), $this->export($definition->isShared() ? ($definition->isPublic() ? 'services' : 'privates') : false), @@ -1716,7 +1759,7 @@ private function getServiceCall(string $id, Reference $reference = null): string $code = sprintf('$this->%s[%s] = %s', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code); } $code = "($code)"; - } elseif ($this->asFiles && !$this->isHotPath($definition)) { + } elseif ($this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition)) { $code = sprintf("\$this->load('%s.php')", $this->generateMethodName($id)); if (!$definition->isShared()) { $factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id)); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 28779181af184..71087a4b8681a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; +use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; @@ -42,6 +43,8 @@ require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php'; require_once __DIR__.'/../Fixtures/includes/classes.php'; +require_once __DIR__.'/../Fixtures/includes/foo.php'; +require_once __DIR__.'/../Fixtures/includes/foo_lazy.php'; class PhpDumperTest extends TestCase { @@ -234,6 +237,59 @@ public function testDumpAsFiles() $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_as_files.txt', $dump); } + public function testDumpAsFilesWithFactoriesInlined() + { + $container = include self::$fixturesPath.'/containers/container9.php'; + $container->setParameter('container.dumper.inline_factories', true); + $container->setParameter('container.dumper.inline_class_loader', true); + + $container->getDefinition('bar')->addTag('hot'); + $container->register('non_shared_foo', \Bar\FooClass::class) + ->setFile(realpath(self::$fixturesPath.'/includes/foo.php')) + ->setShared(false) + ->setPublic(true); + $container->register('throwing_one', \Bar\FooClass::class) + ->addArgument(new Reference('errored_one', ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE)) + ->setPublic(true); + $container->register('errored_one', 'stdClass') + ->addError('No-no-no-no'); + $container->compile(); + + $dumper = new PhpDumper($container); + $dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'build_time' => 1563381341]), true); + + if ('\\' === \DIRECTORY_SEPARATOR) { + $dump = str_replace('\\\\Fixtures\\\\includes\\\\', '/Fixtures/includes/', $dump); + } + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_inlined_factories.txt', $dump); + } + + /** + * @requires function \Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper::getProxyCode + */ + public function testDumpAsFilesWithLazyFactoriesInlined() + { + $container = new ContainerBuilder(); + $container->setParameter('container.dumper.inline_factories', true); + $container->setParameter('container.dumper.inline_class_loader', true); + + $container->register('lazy_foo', \Bar\FooClass::class) + ->addArgument(new Definition(\Bar\FooLazyClass::class)) + ->setPublic(true) + ->setLazy(true); + + $container->compile(); + + $dumper = new PhpDumper($container); + $dumper->setProxyDumper(new ProxyDumper()); + $dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'build_time' => 1563381341]), true); + + if ('\\' === \DIRECTORY_SEPARATOR) { + $dump = str_replace('\\\\Fixtures\\\\includes\\\\', '/Fixtures/includes/', $dump); + } + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_lazy_inlined_factories.txt', $dump); + } + public function testNonSharedLazyDumpAsFiles() { $container = include self::$fixturesPath.'/containers/container_non_shared_lazy.php'; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_inlined_factories.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_inlined_factories.txt new file mode 100644 index 0000000000000..2a9df5a967e8a --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_inlined_factories.txt @@ -0,0 +1,572 @@ +Array +( + [Container%s/removed-ids.php] => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'configurator_service' => true, + 'configurator_service_simple' => true, + 'decorated.pif-pouf' => true, + 'decorator_service.inner' => true, + 'errored_definition' => true, + 'errored_one' => true, + 'factory_simple' => true, + 'inlined' => true, + 'new_factory' => true, + 'tagged_iterator_foo' => true, +]; + + [Container%s/ProjectServiceContainer.php] => targetDirs[0] = \dirname($containerDir); + for ($i = 1; $i <= 5; ++$i) { + $this->targetDirs[$i] = $dir = \dirname($dir); + } + $this->buildParameters = $buildParameters; + $this->containerDir = $containerDir; + $this->parameters = $this->getDefaultParameters(); + + $this->services = $this->privates = []; + $this->syntheticIds = [ + 'request' => true, + ]; + $this->methodMap = [ + 'BAR' => 'getBARService', + 'BAR2' => 'getBAR2Service', + 'bar' => 'getBar3Service', + 'bar2' => 'getBar22Service', + 'baz' => 'getBazService', + 'configured_service' => 'getConfiguredServiceService', + 'configured_service_simple' => 'getConfiguredServiceSimpleService', + 'decorator_service' => 'getDecoratorServiceService', + 'decorator_service_with_name' => 'getDecoratorServiceWithNameService', + 'deprecated_service' => 'getDeprecatedServiceService', + 'factory_service' => 'getFactoryServiceService', + 'factory_service_simple' => 'getFactoryServiceSimpleService', + 'foo' => 'getFooService', + 'foo.baz' => 'getFoo_BazService', + 'foo_bar' => 'getFooBarService', + 'foo_with_inline' => 'getFooWithInlineService', + 'lazy_context' => 'getLazyContextService', + 'lazy_context_ignore_invalid_ref' => 'getLazyContextIgnoreInvalidRefService', + 'method_call1' => 'getMethodCall1Service', + 'new_factory_service' => 'getNewFactoryServiceService', + 'non_shared_foo' => 'getNonSharedFooService', + 'runtime_error' => 'getRuntimeErrorService', + 'service_from_static_method' => 'getServiceFromStaticMethodService', + 'tagged_iterator' => 'getTaggedIteratorService', + 'throwing_one' => 'getThrowingOneService', + ]; + $this->aliases = [ + 'alias_for_alias' => 'foo', + 'alias_for_foo' => 'foo', + 'decorated' => 'decorator_service_with_name', + ]; + + $this->privates['service_container'] = function () { + include_once $this->targetDirs[0].'/Fixtures/includes/foo.php'; + }; + } + + 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 require $this->containerDir.\DIRECTORY_SEPARATOR.'removed-ids.php'; + } + + /** + * Gets the public 'BAR' shared service. + * + * @return \stdClass + */ + protected function getBARService() + { + $this->services['BAR'] = $instance = new \stdClass(); + + $instance->bar = ($this->services['bar'] ?? $this->getBar3Service()); + + return $instance; + } + + /** + * Gets the public 'BAR2' shared service. + * + * @return \stdClass + */ + protected function getBAR2Service() + { + return $this->services['BAR2'] = new \stdClass(); + } + + /** + * Gets the public 'bar' shared service. + * + * @return \Bar\FooClass + */ + protected function getBar3Service() + { + $a = ($this->services['foo.baz'] ?? $this->getFoo_BazService()); + + $this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar')); + + $a->configure($instance); + + return $instance; + } + + /** + * Gets the public 'bar2' shared service. + * + * @return \stdClass + */ + protected function getBar22Service() + { + return $this->services['bar2'] = new \stdClass(); + } + + /** + * Gets the public 'baz' shared service. + * + * @return \Baz + */ + protected function getBazService() + { + $this->services['baz'] = $instance = new \Baz(); + + $instance->setFoo(($this->services['foo_with_inline'] ?? $this->getFooWithInlineService())); + + return $instance; + } + + /** + * Gets the public 'configured_service' shared service. + * + * @return \stdClass + */ + protected function getConfiguredServiceService() + { + $this->services['configured_service'] = $instance = new \stdClass(); + + $a = new \ConfClass(); + $a->setFoo(($this->services['baz'] ?? $this->getBazService())); + + $a->configureStdClass($instance); + + return $instance; + } + + /** + * Gets the public 'configured_service_simple' shared service. + * + * @return \stdClass + */ + protected function getConfiguredServiceSimpleService() + { + $this->services['configured_service_simple'] = $instance = new \stdClass(); + + (new \ConfClass('bar'))->configureStdClass($instance); + + return $instance; + } + + /** + * Gets the public 'decorator_service' shared service. + * + * @return \stdClass + */ + protected function getDecoratorServiceService() + { + return $this->services['decorator_service'] = new \stdClass(); + } + + /** + * Gets the public 'decorator_service_with_name' shared service. + * + * @return \stdClass + */ + protected function getDecoratorServiceWithNameService() + { + return $this->services['decorator_service_with_name'] = new \stdClass(); + } + + /** + * Gets the public 'deprecated_service' shared service. + * + * @return \stdClass + * + * @deprecated The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future. + */ + protected function getDeprecatedServiceService() + { + @trigger_error('The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.', E_USER_DEPRECATED); + + return $this->services['deprecated_service'] = new \stdClass(); + } + + /** + * Gets the public 'factory_service' shared service. + * + * @return \Bar + */ + protected function getFactoryServiceService() + { + return $this->services['factory_service'] = ($this->services['foo.baz'] ?? $this->getFoo_BazService())->getInstance(); + } + + /** + * Gets the public 'factory_service_simple' shared service. + * + * @return \Bar + */ + protected function getFactoryServiceSimpleService() + { + return $this->services['factory_service_simple'] = $this->getFactorySimpleService()->getInstance(); + } + + /** + * Gets the public 'foo' shared service. + * + * @return \Bar\FooClass + */ + protected function getFooService() + { + $a = ($this->services['foo.baz'] ?? $this->getFoo_BazService()); + + $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, ['bar' => 'foo is bar', 'foobar' => 'bar'], true, $this); + + $instance->foo = 'bar'; + $instance->moo = $a; + $instance->qux = ['bar' => 'foo is bar', 'foobar' => 'bar']; + $instance->setBar(($this->services['bar'] ?? $this->getBar3Service())); + $instance->initialize(); + sc_configure($instance); + + return $instance; + } + + /** + * Gets the public 'foo.baz' shared service. + * + * @return \BazClass + */ + protected function getFoo_BazService() + { + include_once $this->targetDirs[0].'/Fixtures/includes/classes.php'; + + $this->services['foo.baz'] = $instance = \BazClass::getInstance(); + + \BazClass::configureStatic1($instance); + + return $instance; + } + + /** + * Gets the public 'foo_bar' service. + * + * @return \Bar\FooClass + */ + protected function getFooBarService() + { + return new \Bar\FooClass(($this->services['deprecated_service'] ?? $this->getDeprecatedServiceService())); + } + + /** + * Gets the public 'foo_with_inline' shared service. + * + * @return \Foo + */ + protected function getFooWithInlineService() + { + $this->services['foo_with_inline'] = $instance = new \Foo(); + + $a = new \Bar(); + $a->pub = 'pub'; + $a->setBaz(($this->services['baz'] ?? $this->getBazService())); + + $instance->setBar($a); + + return $instance; + } + + /** + * Gets the public 'lazy_context' shared service. + * + * @return \LazyContext + */ + protected function getLazyContextService() + { + include_once $this->targetDirs[0].'/Fixtures/includes/classes.php'; + + return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () { + yield 'k1' => ($this->services['foo.baz'] ?? $this->getFoo_BazService()); + yield 'k2' => $this; + }, 2), new RewindableGenerator(function () { + return new \EmptyIterator(); + }, 0)); + } + + /** + * Gets the public 'lazy_context_ignore_invalid_ref' shared service. + * + * @return \LazyContext + */ + protected function getLazyContextIgnoreInvalidRefService() + { + include_once $this->targetDirs[0].'/Fixtures/includes/classes.php'; + + return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { + yield 0 => ($this->services['foo.baz'] ?? $this->getFoo_BazService()); + }, 1), new RewindableGenerator(function () { + return new \EmptyIterator(); + }, 0)); + } + + /** + * Gets the public 'method_call1' shared service. + * + * @return \Bar\FooClass + */ + protected function getMethodCall1Service() + { + include_once ($this->targetDirs[0].'/Fixtures/includes/foo.php'); + + $this->services['method_call1'] = $instance = new \Bar\FooClass(); + + $instance->setBar(($this->services['foo'] ?? $this->getFooService())); + $instance->setBar(NULL); + $instance->setBar((($this->services['foo'] ?? $this->getFooService())->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); + + return $instance; + } + + /** + * Gets the public 'new_factory_service' shared service. + * + * @return \FooBarBaz + */ + protected function getNewFactoryServiceService() + { + $a = new \FactoryClass(); + $a->foo = 'bar'; + + $this->services['new_factory_service'] = $instance = $a->getInstance(); + + $instance->foo = 'bar'; + + return $instance; + } + + /** + * Gets the public 'non_shared_foo' service. + * + * @return \Bar\FooClass + */ + protected function getNonSharedFooService() + { + include_once ($this->targetDirs[0].'/Fixtures/includes/foo.php'); + + return new \Bar\FooClass(); + } + + /** + * Gets the public 'runtime_error' shared service. + * + * @return \stdClass + */ + protected function getRuntimeErrorService() + { + return $this->services['runtime_error'] = new \stdClass($this->throw('Service "errored_definition" is broken.')); + } + + /** + * Gets the public 'service_from_static_method' shared service. + * + * @return \Bar\FooClass + */ + protected function getServiceFromStaticMethodService() + { + return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance(); + } + + /** + * Gets the public 'tagged_iterator' shared service. + * + * @return \Bar + */ + protected function getTaggedIteratorService() + { + return $this->services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () { + yield 0 => ($this->services['foo'] ?? $this->getFooService()); + yield 1 => ($this->privates['tagged_iterator_foo'] ?? ($this->privates['tagged_iterator_foo'] = new \Bar())); + }, 2)); + } + + /** + * Gets the public 'throwing_one' shared service. + * + * @return \Bar\FooClass + */ + protected function getThrowingOneService() + { + return $this->services['throwing_one'] = new \Bar\FooClass($this->throw('No-no-no-no')); + } + + /** + * Gets the private 'factory_simple' shared service. + * + * @return \SimpleFactoryClass + * + * @deprecated The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future. + */ + protected function getFactorySimpleService() + { + @trigger_error('The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.', E_USER_DEPRECATED); + + return new \SimpleFactoryClass('foo'); + } + + public function getParameter($name) + { + $name = (string) $name; + if (isset($this->buildParameters[$name])) { + return $this->buildParameters[$name]; + } + + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } + if (isset($this->loadedDynamicParameters[$name])) { + return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + + return $this->parameters[$name]; + } + + public function hasParameter($name) + { + $name = (string) $name; + if (isset($this->buildParameters[$name])) { + return true; + } + + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); + } + + public function setParameter($name, $value) + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + public function getParameterBag() + { + if (null === $this->parameterBag) { + $parameters = $this->parameters; + foreach ($this->loadedDynamicParameters as $name => $loaded) { + $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + foreach ($this->buildParameters as $name => $value) { + $parameters[$name] = $value; + } + $this->parameterBag = new FrozenParameterBag($parameters); + } + + return $this->parameterBag; + } + + private $loadedDynamicParameters = []; + private $dynamicParameters = []; + + /** + * Computes a dynamic parameter. + * + * @param string $name The name of the dynamic parameter to load + * + * @return mixed The value of the dynamic parameter + * + * @throws InvalidArgumentException When the dynamic parameter does not exist + */ + private function getDynamicParameter($name) + { + throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); + } + + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return [ + 'baz_class' => 'BazClass', + 'foo_class' => 'Bar\\FooClass', + 'foo' => 'bar', + 'container.dumper.inline_factories' => true, + 'container.dumper.inline_class_loader' => true, + ]; + } + + protected function throw($message) + { + throw new RuntimeException($message); + } +} + + [ProjectServiceContainer.php] => '%s', + 'container.build_id' => '%s', + 'container.build_time' => 1563381341, +], __DIR__.\DIRECTORY_SEPARATOR.'Container%s'); + +) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_lazy_inlined_factories.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_lazy_inlined_factories.txt new file mode 100644 index 0000000000000..7be60f712932b --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_lazy_inlined_factories.txt @@ -0,0 +1,206 @@ +Array +( + [Container%s/removed-ids.php] => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, +]; + + [Container%s/ProjectServiceContainer.php] => targetDirs[0] = \dirname($containerDir); + for ($i = 1; $i <= 5; ++$i) { + $this->targetDirs[$i] = $dir = \dirname($dir); + } + $this->buildParameters = $buildParameters; + $this->containerDir = $containerDir; + $this->parameters = $this->getDefaultParameters(); + + $this->services = $this->privates = []; + $this->methodMap = [ + 'lazy_foo' => 'getLazyFooService', + ]; + + $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 require $this->containerDir.\DIRECTORY_SEPARATOR.'removed-ids.php'; + } + + protected function createProxy($class, \Closure $factory) + { + class_exists($class, false) || class_alias(__NAMESPACE__."\\$class", $class, false); + + return $factory(); + } + + /** + * Gets the public 'lazy_foo' shared service. + * + * @return \Bar\FooClass + */ + protected function getLazyFooService($lazyLoad = true) + { + if ($lazyLoad) { + return $this->services['lazy_foo'] = $this->createProxy('FooClass_%s', function () { + return \FooClass_%s::staticProxyConstructor(function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) { + $wrappedInstance = $this->getLazyFooService(false); + + $proxy->setProxyInitializer(null); + + return true; + }); + }); + } + + include_once $this->targetDirs[0].'/Fixtures/includes/foo_lazy.php'; + + return new \Bar\FooClass(new \Bar\FooLazyClass()); + } + + public function getParameter($name) + { + $name = (string) $name; + if (isset($this->buildParameters[$name])) { + return $this->buildParameters[$name]; + } + + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } + if (isset($this->loadedDynamicParameters[$name])) { + return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + + return $this->parameters[$name]; + } + + public function hasParameter($name) + { + $name = (string) $name; + if (isset($this->buildParameters[$name])) { + return true; + } + + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); + } + + public function setParameter($name, $value) + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + public function getParameterBag() + { + if (null === $this->parameterBag) { + $parameters = $this->parameters; + foreach ($this->loadedDynamicParameters as $name => $loaded) { + $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + foreach ($this->buildParameters as $name => $value) { + $parameters[$name] = $value; + } + $this->parameterBag = new FrozenParameterBag($parameters); + } + + return $this->parameterBag; + } + + private $loadedDynamicParameters = []; + private $dynamicParameters = []; + + /** + * Computes a dynamic parameter. + * + * @param string $name The name of the dynamic parameter to load + * + * @return mixed The value of the dynamic parameter + * + * @throws InvalidArgumentException When the dynamic parameter does not exist + */ + private function getDynamicParameter($name) + { + throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); + } + + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return [ + 'container.dumper.inline_factories' => true, + 'container.dumper.inline_class_loader' => true, + ]; + } +} +include_once \dirname(__DIR__, 1 + 0).'/Fixtures/includes/foo.php'; + +class FooClass_%s extends \Bar\FooClass implements \ProxyManager\Proxy\VirtualProxyInterface +{ +%A +} + + [ProjectServiceContainer.php] => '%s', + 'container.build_id' => '%s', + 'container.build_time' => 1563381341, +], __DIR__.\DIRECTORY_SEPARATOR.'Container%s'); + +) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy