From f829b7ff452c17d9bae383dafe83f05fc27ce256 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 30 Mar 2013 00:21:12 +0100 Subject: [PATCH 01/39] First implementation of lazy services via proxy manager --- composer.json | 1 + .../DependencyInjection/ContainerBuilder.php | 19 +++++++++++- .../DependencyInjection/Definition.php | 30 +++++++++++++++++++ .../DependencyInjection/Dumper/XmlDumper.php | 3 ++ .../DependencyInjection/Dumper/YamlDumper.php | 4 +++ .../Loader/XmlFileLoader.php | 2 +- .../Loader/YamlFileLoader.php | 4 +++ .../schema/dic/services/services-1.0.xsd | 1 + .../Tests/ContainerBuilderTest.php | 24 +++++++++++++++ .../Tests/DefinitionTest.php | 12 ++++++++ .../Tests/Fixtures/xml/services6.xml | 2 +- .../Tests/Fixtures/yaml/services6.yml | 1 + .../Tests/Loader/XmlFileLoaderTest.php | 1 + .../Tests/Loader/YamlFileLoaderTest.php | 1 + 14 files changed, 102 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 504b48d92c76a..a102f4705c448 100644 --- a/composer.json +++ b/composer.json @@ -61,6 +61,7 @@ "symfony/yaml": "self.version" }, "require-dev": { + "ocramius/proxy-manager": "0.2.*", "doctrine/data-fixtures": "1.0.*", "doctrine/dbal": "~2.2", "doctrine/orm": "~2.2,>=2.2.3", diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 5d8d0d1a10f15..9ce9a18595635 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -11,6 +11,9 @@ namespace Symfony\Component\DependencyInjection; +use ProxyManager\Configuration; +use ProxyManager\Factory\LazyLoadingValueHolderFactory; +use ProxyManager\Proxy\LazyLoadingInterface; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; @@ -873,8 +876,22 @@ public function findDefinition($id) * @throws RuntimeException When the service is a synthetic service * @throws InvalidArgumentException When configure callable is not callable */ - private function createService(Definition $definition, $id) + public function createService(Definition $definition, $id, $tryProxy = true) { + if ($tryProxy && ($className = $definition->getClass()) && $definition->isLazy()) { + $factory = new LazyLoadingValueHolderFactory(new Configuration()); + $container = $this; + + return $factory->createProxy( + $className, + function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $definition, $id) { + $proxy->setProxyInitializer(null); + + $wrappedInstance = $container->createService($definition, $id, false); + } + ); + } + if ($definition->isSynthetic()) { throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); } diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 9d52426121874..803dc1640d785 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -37,6 +37,7 @@ class Definition private $synthetic; private $abstract; private $synchronized; + private $lazy; protected $arguments; @@ -58,6 +59,7 @@ public function __construct($class = null, array $arguments = array()) $this->public = true; $this->synthetic = false; $this->synchronized = false; + $this->lazy = false; $this->abstract = false; $this->properties = array(); } @@ -599,6 +601,34 @@ public function isSynchronized() return $this->synchronized; } + /** + * Sets the lazy flag of this service. + * + * @param Boolean $lazy + * + * @return Definition The current instance + * + * @api + */ + public function setLazy($lazy) + { + $this->lazy = (Boolean) $lazy; + + return $this; + } + + /** + * Whether this service is lazy. + * + * @return Boolean + * + * @api + */ + public function isLazy() + { + return $this->lazy; + } + /** * Sets whether this definition is synthetic, that is not constructed by the * container, but dynamically injected. diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index da2e2c4cd80be..a5ceb2c68d3c3 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -133,6 +133,9 @@ private function addService($definition, $id, \DOMElement $parent) if ($definition->isSynchronized()) { $service->setAttribute('synchronized', 'true'); } + if ($definition->isLazy()) { + $service->setAttribute('lazy', 'true'); + } foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index bc10c4a7b4e17..0059f0d0d7388 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -106,6 +106,10 @@ private function addService($id, $definition) $code .= sprintf(" factory_class: %s\n", $definition->getFactoryClass()); } + if ($definition->isLazy()) { + $code .= sprintf(" lazy: true\n"); + } + if ($definition->getFactoryMethod()) { $code .= sprintf(" factory_method: %s\n", $definition->getFactoryMethod()); } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 85898d3d3fe86..9f25ab7683cd2 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -148,7 +148,7 @@ private function parseDefinition($id, $service, $file) $definition = new Definition(); } - foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'abstract') as $key) { + foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'lazy', 'abstract') as $key) { if (isset($service[$key])) { $method = 'set'.str_replace('-', '', $key); $definition->$method((string) $service->getAttributeAsPhp($key)); diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index b95280dfcfe5f..cf68a33756747 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -157,6 +157,10 @@ private function parseDefinition($id, $service, $file) $definition->setSynchronized($service['synchronized']); } + if (isset($service['lazy'])) { + $definition->setLazy($service['lazy']); + } + if (isset($service['public'])) { $definition->setPublic($service['public']); } 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 4d9addcd971f8..f1c2003c62258 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 @@ -87,6 +87,7 @@ + diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 7d2cb278871cc..1e22d3e778843 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -263,6 +263,30 @@ public function testCreateService() $this->assertInstanceOf('\FooClass', $builder->get('foo2'), '->createService() replaces parameters in the file provided by the service definition'); } + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService + */ + public function testCreateServiceWithDelegateFactory() + { + $builder = new ContainerBuilder(); + + $builder->register('foo1', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php'); + $builder->getDefinition('foo1')->setLazy(true); + + /* @var $foo1 \ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */ + $foo1 = $builder->get('foo1'); + + $this->assertInstanceOf('\FooClass', $foo1); + $this->assertInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1); + $this->assertFalse($foo1->isProxyInitialized()); + + $foo1->initializeProxy(); + + $this->assertTrue($foo1->isProxyInitialized()); + $this->assertInstanceOf('\FooClass', $foo1->getWrappedValueHolderValue()); + $this->assertNotInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1->getWrappedValueHolderValue()); + } + /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php index d9a4282efefbc..d41c6a8e2b2ae 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php @@ -164,6 +164,18 @@ public function testSetIsSynchronized() $this->assertTrue($def->isSynchronized(), '->isSynchronized() returns true if the service is synchronized.'); } + /** + * @covers Symfony\Component\DependencyInjection\Definition::setLazy + * @covers Symfony\Component\DependencyInjection\Definition::isLazy + */ + public function testSetIsLazy() + { + $def = new Definition('stdClass'); + $this->assertFalse($def->isLazy(), '->isLazy() returns false by default'); + $this->assertSame($def, $def->setLazy(true), '->setLazy() implements a fluent interface'); + $this->assertTrue($def->isLazy(), '->isLazy() returns true if the service is lazy.'); + } + /** * @covers Symfony\Component\DependencyInjection\Definition::setAbstract * @covers Symfony\Component\DependencyInjection\Definition::isAbstract diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml index 4d2aa3d79ae24..abd9fbc1529b1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml @@ -46,6 +46,6 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml index 820c364a06556..7ba9453bdd6dd 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml @@ -28,3 +28,4 @@ services: class: Request synthetic: true synchronized: true + lazy: true diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index b355f0ac215c3..d8138f947541a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -187,6 +187,7 @@ public function testLoadServices() $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag'); $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag'); + $this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag'); $aliases = $container->getAliases(); $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses elements'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 290d6628acf5b..e452e5d221d19 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -130,6 +130,7 @@ public function testLoadServices() $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag'); $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag'); + $this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag'); $aliases = $container->getAliases(); $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses aliases'); From 1874dbf1e57d15919bce06b6469710c602e2bdf6 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 30 Mar 2013 01:23:57 +0100 Subject: [PATCH 02/39] Adding basic logic to generate proxy instantiation into a php dumped container --- .../DependencyInjection/ContainerBuilder.php | 2 + .../DependencyInjection/Dumper/PhpDumper.php | 62 ++++++++++++++++- .../Tests/Dumper/PhpDumperTest.php | 14 ++++ .../Tests/Fixtures/php/lazy_service.php | 66 +++++++++++++++++++ 4 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 9ce9a18595635..4e3edcb352f69 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -888,6 +888,8 @@ function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $def $proxy->setProxyInitializer(null); $wrappedInstance = $container->createService($definition, $id, false); + + return true; } ); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 294de23a7773d..88a627fef4de0 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -149,6 +149,51 @@ private function addServiceLocalTempVariables($cId, $definition) return $code; } + /** + * Generates the logic required for proxy lazy loading + * + * @param string $id The service id + * @param Definition $definition + * + * @return string + */ + private function addProxyLoading($id, Definition $definition) + { + if (!($definition->isLazy() && $definition->getClass())) { + return ''; + } + + $class = $this->dumpValue($definition->getClass()); + + if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { + return ''; + } + + // @todo this should happen directly through the factory class, but we have to ensure that the proxy + // @todo class is generated during the dump process + $methodName = 'get' . Container::camelize($id) . 'Service'; + + return <<createProxy( + $class, + function (& \$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) use (\$container) { + \$proxy->setProxyInitializer(null); + + \$wrappedInstance = \$container->$methodName(false); + + return true; + } + ); + } + + +EOF; + } + /** * Generates the require_once statement for service includes. * @@ -483,18 +528,29 @@ private function addService($id, $definition) EOF; } - $code = <<isLazy()) { + $lazyInitialization = '$lazyLoad = true'; + $lazyInitializationDoc = "\n * @param boolean \$lazyLoad whether to try lazy-loading the" + . " service with a proxy\n *"; + } else { + $lazyInitialization = ''; + $lazyInitializationDoc = ''; + } + + $code = <<addProxyLoading($id, $definition); + if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) { $code .= <<scopedServices['$scope'])) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 72d587ff070fc..767635aebc03d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -52,6 +52,20 @@ public function testDumpFrozenContainerWithNoParameter() $this->assertNotRegexp("/function getDefaultParameters\(/", $dumpedString, '->dump() does not add getDefaultParameters() method definition.'); } + public function testDumpContainerWithProxyService() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass'); + $container->getDefinition('foo')->setLazy(true); + + $container->compile(); + + $dumper = new PhpDumper($container); + + $dumpedString = $dumper->dump(); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/lazy_service.php', $dumpedString, '->dump() does generate proxy lazy loading logic.'); + } + public function testDumpOptimizationString() { $definition = new Definition(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php new file mode 100644 index 0000000000000..9f4eafd0c0fa3 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php @@ -0,0 +1,66 @@ +services = + $this->scopedServices = + $this->scopeStacks = array(); + + $this->set('service_container', $this); + + $this->scopes = array(); + $this->scopeChildren = array(); + } + + /** + * Gets the 'foo' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @param boolean $lazyLoad whether to try lazy-loading the service with a proxy + * + * @return stdClass A stdClass instance. + */ + protected function getFooService($lazyLoad = true) + { + if ($lazyLoad) { + $factory = new \ProxyManager\Factory\LazyLoadingValueHolderFactory(new \ProxyManager\Configuration()); + $container = $this; + + return $factory->createProxy( + 'stdClass', + function (& $wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) { + $proxy->setProxyInitializer(null); + + $wrappedInstance = $container->getFooService(false); + + return true; + } + ); + } + + return $this->services['foo'] = new \stdClass(); + } +} From 37abd21cd7fd226f54fc4737a6605e64b15e9111 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 30 Mar 2013 02:54:45 +0100 Subject: [PATCH 03/39] Compiling proxies into the generated DIC file --- .../DependencyInjection/Dumper/PhpDumper.php | 48 ++++- .../Tests/Dumper/PhpDumperTest.php | 2 +- .../Tests/Fixtures/php/lazy_service.php | 66 ------ .../Tests/Fixtures/php/lazy_service.txt | 190 ++++++++++++++++++ 4 files changed, 235 insertions(+), 71 deletions(-) delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 88a627fef4de0..a418b0a92e5a8 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -11,6 +11,10 @@ namespace Symfony\Component\DependencyInjection\Dumper; +use CG\Core\DefaultGeneratorStrategy; +use CG\Generator\PhpClass; +use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator; +use ReflectionClass; use Symfony\Component\DependencyInjection\Variable; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -94,7 +98,8 @@ public function dump(array $options = array()) $code .= $this->addServices(). $this->addDefaultParametersMethod(). - $this->endClass() + $this->endClass(). + $this->addProxyClasses() ; return $code; @@ -172,14 +177,13 @@ private function addProxyLoading($id, Definition $definition) // @todo this should happen directly through the factory class, but we have to ensure that the proxy // @todo class is generated during the dump process $methodName = 'get' . Container::camelize($id) . 'Service'; + $proxyClass = str_replace('\\', '', $definition->getClass()) . '_' . md5(spl_object_hash($definition)); return <<createProxy( - $class, + return new $proxyClass( function (& \$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) use (\$container) { \$proxy->setProxyInitializer(null); @@ -194,6 +198,42 @@ function (& \$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) EOF; } + /** + * Generates code for the proxy classes to be attached after the container class + * + * @return string + */ + private function addProxyClasses() + { + $definitions = $this->container->getDefinitions(); + + ksort($definitions); + + $proxyDefinitions = array_filter( + $this->container->getDefinitions(), + function (Definition $definition) { + return $definition->isLazy() && $definition->getClass(); + } + ); + + $proxyGenerator = new LazyLoadingValueHolderGenerator(); + $classGenerator = new DefaultGeneratorStrategy(); + $code = ''; + + /* @var $proxyDefinitions Definition[] */ + foreach ($proxyDefinitions as $definition) { + $phpClass = new PhpClass( + str_replace('\\', '', $definition->getClass()) . '_' . md5(spl_object_hash($definition)) + ); + + $proxyGenerator->generate(new ReflectionClass($definition->getClass()), $phpClass); + + $code .= "\n" . $classGenerator->generate($phpClass); + } + + return $code; + } + /** * Generates the require_once statement for service includes. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 767635aebc03d..fe1580dfc464f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -63,7 +63,7 @@ public function testDumpContainerWithProxyService() $dumper = new PhpDumper($container); $dumpedString = $dumper->dump(); - $this->assertStringEqualsFile(self::$fixturesPath.'/php/lazy_service.php', $dumpedString, '->dump() does generate proxy lazy loading logic.'); + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/lazy_service.txt', $dumpedString, '->dump() does generate proxy lazy loading logic.'); } public function testDumpOptimizationString() diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php deleted file mode 100644 index 9f4eafd0c0fa3..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php +++ /dev/null @@ -1,66 +0,0 @@ -services = - $this->scopedServices = - $this->scopeStacks = array(); - - $this->set('service_container', $this); - - $this->scopes = array(); - $this->scopeChildren = array(); - } - - /** - * Gets the 'foo' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @param boolean $lazyLoad whether to try lazy-loading the service with a proxy - * - * @return stdClass A stdClass instance. - */ - protected function getFooService($lazyLoad = true) - { - if ($lazyLoad) { - $factory = new \ProxyManager\Factory\LazyLoadingValueHolderFactory(new \ProxyManager\Configuration()); - $container = $this; - - return $factory->createProxy( - 'stdClass', - function (& $wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) { - $proxy->setProxyInitializer(null); - - $wrappedInstance = $container->getFooService(false); - - return true; - } - ); - } - - return $this->services['foo'] = new \stdClass(); - } -} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt new file mode 100644 index 0000000000000..1a27b5ae0f3cd --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt @@ -0,0 +1,190 @@ +services = + $this->scopedServices = + $this->scopeStacks = array(); + + $this->set('service_container', $this); + + $this->scopes = array(); + $this->scopeChildren = array(); + } + + /** + * Gets the 'foo' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @param boolean $lazyLoad whether to try lazy-loading the service with a proxy + * + * @return stdClass A stdClass instance. + */ + protected function getFooService($lazyLoad = true) + { + if ($lazyLoad) { + $container = $this; + + return new stdClass_%s( + function (& $wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) { + $proxy->setProxyInitializer(null); + + $wrappedInstance = $container->getFooService(false); + + return true; + } + ); + } + + return $this->services['foo'] = new \stdClass(); + } +} + +class %s extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface +{ + /** + * @var \Closure|null initializer responsible for generating the wrapped object + */ + private $%s; + /** + * @var \Closure|null initializer responsible for generating the wrapped object + */ + private $%s; + + /** + * {@inheritDoc} + */ + public function setProxyInitializer(\Closure $initializer = NULL) + { + $this->%s = $initializer; + } + + /** + * {@inheritDoc} + */ + public function isProxyInitialized() + { + return null !== $this->%s; + } + + /** + * {@inheritDoc} + */ + public function initializeProxy() + { + return $this->%s && $this->%s->__invoke($this->%s, $this, 'initializeProxy', array()); + } + + /** + * {@inheritDoc} + */ + public function getWrappedValueHolderValue() + { + return $this->%s; + } + + /** + * {@inheritDoc} + */ + public function getProxyInitializer() + { + return $this->%s; + } + + /** + */ + public function __wakeup() + { + } + + /** + * @param string $name + */ + public function __unset($name) + { + $this->%s && $this->%s->__invoke($this->%s, $this, '__unset', array('name' => $name)); + + unset($this->%s->$name); + } + + /** + */ + public function __sleep() + { + $this->%s && $this->%s->__invoke($this->%s, $this, '__sleep', array()); + + return array('%s'); + } + + /** + * @param string $name + * @param mixed $value + */ + public function __set($name, $value) + { + $this->%s && $this->%s->__invoke($this->%s, $this, '__set', array('name' => $name, 'value' => $value)); + + $this->%s->$name = $value; + } + + /** + * @param string $name + */ + public function __isset($name) + { + $this->%s && $this->%s->__invoke($this->%s, $this, '__isset', array('name' => $name)); + + return isset($this->%s->$name); + } + + /** + * @param string $name + */ + public function __get($name) + { + $this->%s && $this->%s->__invoke($this->%s, $this, '__get', array('name' => $name)); + + return $this->%s->$name; + } + + /** + * @override constructor for lazy initialization + * @param \Closure|null $initializer + */ + public function __construct($initializer) + { + $this->%s = $initializer; + } + + /** + */ + public function __clone() + { + $this->%s && $this->%s->__invoke($this->%s, $this, '__clone', array()); + + $this->%s = clone $this->%s; + } +} \ No newline at end of file From 7c1c5fd850d39f42b0cdd50079d79340de592f70 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 30 Mar 2013 11:56:42 +0100 Subject: [PATCH 04/39] Upgrading dependency to ProxyManager 0.3.* --- composer.json | 4 +- .../DependencyInjection/Dumper/PhpDumper.php | 13 ++- .../Tests/Fixtures/php/lazy_service.txt | 106 ++++++++++-------- .../DependencyInjection/composer.json | 3 +- 4 files changed, 70 insertions(+), 56 deletions(-) diff --git a/composer.json b/composer.json index a102f4705c448..bf74f0864c187 100644 --- a/composer.json +++ b/composer.json @@ -61,13 +61,13 @@ "symfony/yaml": "self.version" }, "require-dev": { - "ocramius/proxy-manager": "0.2.*", "doctrine/data-fixtures": "1.0.*", "doctrine/dbal": "~2.2", "doctrine/orm": "~2.2,>=2.2.3", "monolog/monolog": "~1.3", "propel/propel1": "1.6.*", - "ircmaxell/password-compat": "1.0.*" + "ircmaxell/password-compat": "1.0.*", + "ocramius/proxy-manager": "0.3.*" }, "autoload": { "psr-0": { "Symfony\\": "src/" }, diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index a418b0a92e5a8..02866e3ab753e 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -11,8 +11,8 @@ namespace Symfony\Component\DependencyInjection\Dumper; -use CG\Core\DefaultGeneratorStrategy; -use CG\Generator\PhpClass; +use ProxyManager\Generator\ClassGenerator; +use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy; use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator; use ReflectionClass; use Symfony\Component\DependencyInjection\Variable; @@ -216,13 +216,18 @@ function (Definition $definition) { } ); + if (empty($proxyDefinitions)) { + // avoids hard dependency to ProxyManager + return ''; + } + $proxyGenerator = new LazyLoadingValueHolderGenerator(); - $classGenerator = new DefaultGeneratorStrategy(); + $classGenerator = new BaseGeneratorStrategy(); $code = ''; /* @var $proxyDefinitions Definition[] */ foreach ($proxyDefinitions as $definition) { - $phpClass = new PhpClass( + $phpClass = new ClassGenerator( str_replace('\\', '', $definition->getClass()) . '_' . md5(spl_object_hash($definition)) ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt index 1a27b5ae0f3cd..43d5541451bc2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt @@ -63,61 +63,58 @@ class ProjectServiceContainer extends Container } } -class %s extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface +class stdClass_%s extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface { + /** * @var \Closure|null initializer responsible for generating the wrapped object */ - private $%s; + private %s = null; + /** * @var \Closure|null initializer responsible for generating the wrapped object */ - private $%s; + private %s = null; /** - * {@inheritDoc} + * @override constructor for lazy initialization + * + * @param \Closure|null $initializer */ - public function setProxyInitializer(\Closure $initializer = NULL) + public function __construct($initializer) { $this->%s = $initializer; } /** - * {@inheritDoc} + * @param string $name */ - public function isProxyInitialized() + public function __get($name) { - return null !== $this->%s; - } + $this->%s && $this->%s->__invoke($this->%s, $this, '__get', array('name' => $name)); - /** - * {@inheritDoc} - */ - public function initializeProxy() - { - return $this->%s && $this->%s->__invoke($this->%s, $this, 'initializeProxy', array()); + return $this->%s->$name; } /** - * {@inheritDoc} + * @param string $name + * @param mixed $value */ - public function getWrappedValueHolderValue() + public function __set($name, $value) { - return $this->%s; - } + $this->%s && $this->%s->__invoke($this->%s, $this, '__set', array('name' => $name, 'value' => $value)); - /** - * {@inheritDoc} - */ - public function getProxyInitializer() - { - return $this->%s; + $this->%s->$name = $value; } /** + * @param string $name */ - public function __wakeup() + public function __isset($name) { + $this->%s && $this->%s->__invoke($this->%s, $this, '__isset', array('name' => $name)); + + return isset($this->%s->$name); } /** @@ -131,6 +128,17 @@ class %s extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, } /** + * + */ + public function __clone() + { + $this->%s && $this->%s->__invoke($this->%s, $this, '__clone', array()); + + $this->%s = clone $this->%s; + } + + /** + * */ public function __sleep() { @@ -140,51 +148,51 @@ class %s extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, } /** - * @param string $name - * @param mixed $value + * */ - public function __set($name, $value) + public function __wakeup() { - $this->%s && $this->%s->__invoke($this->%s, $this, '__set', array('name' => $name, 'value' => $value)); - - $this->%s->$name = $value; } /** - * @param string $name + * {@inheritDoc} */ - public function __isset($name) + public function setProxyInitializer(\Closure $initializer = null) { - $this->%s && $this->%s->__invoke($this->%s, $this, '__isset', array('name' => $name)); - - return isset($this->%s->$name); + $this->%s = $initializer; } /** - * @param string $name + * {@inheritDoc} */ - public function __get($name) + public function getProxyInitializer() { - $this->%s && $this->%s->__invoke($this->%s, $this, '__get', array('name' => $name)); - - return $this->%s->$name; + return $this->%s; } /** - * @override constructor for lazy initialization - * @param \Closure|null $initializer + * {@inheritDoc} */ - public function __construct($initializer) + public function initializeProxy() { - $this->%s = $initializer; + return $this->%s && $this->%s->__invoke($this->%s, $this, 'initializeProxy', array()); } /** + * {@inheritDoc} */ - public function __clone() + public function isProxyInitialized() { - $this->%s && $this->%s->__invoke($this->%s, $this, '__clone', array()); + return null !== $this->%s; + } - $this->%s = clone $this->%s; + /** + * {@inheritDoc} + */ + public function getWrappedValueHolderValue() + { + return $this->%s; } + + } \ No newline at end of file diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 887686747eda3..d817b9b9b04fd 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -20,7 +20,8 @@ }, "require-dev": { "symfony/yaml": "~2.0", - "symfony/config": ">=2.2,<2.4-dev" + "symfony/config": ">=2.2,<2.4-dev", + "ocramius/proxy-manager": "0.3.*" }, "suggest": { "symfony/yaml": "2.2.*", From d0b4075db4f592334681259cc4513e9286e2aaa8 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 31 Mar 2013 07:26:17 +0200 Subject: [PATCH 05/39] Suggesting ProxyManager in composer.json, removing useless calls --- .../DependencyInjection/ContainerBuilder.php | 25 ++++++++++++++----- .../DependencyInjection/Dumper/PhpDumper.php | 11 +++----- .../DependencyInjection/composer.json | 5 ++-- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 4e3edcb352f69..9370f690b2b09 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -13,6 +13,7 @@ use ProxyManager\Configuration; use ProxyManager\Factory\LazyLoadingValueHolderFactory; +use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; use ProxyManager\Proxy\LazyLoadingInterface; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; @@ -868,6 +869,7 @@ public function findDefinition($id) * * @param Definition $definition A service definition instance * @param string $id The service identifier + * @param Boolean $tryProxy Whether to try proxying the service with a lazy proxy * * @return object The service described by the service definition * @@ -875,11 +877,26 @@ public function findDefinition($id) * @throws RuntimeException When the factory definition is incomplete * @throws RuntimeException When the service is a synthetic service * @throws InvalidArgumentException When configure callable is not callable + * + * @internal this method is public because of PHP 5.3 limitations, do not use it explicitly in your code */ public function createService(Definition $definition, $id, $tryProxy = true) { - if ($tryProxy && ($className = $definition->getClass()) && $definition->isLazy()) { - $factory = new LazyLoadingValueHolderFactory(new Configuration()); + if ($definition->isSynthetic()) { + throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); + } + + if ( + $tryProxy + && ($className = $definition->getClass()) + && $definition->isLazy() + && class_exists('ProxyManager\\Factory\\LazyLoadingValueHolderFactory') + ) { + $config = new Configuration(); + + $config->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); + + $factory = new LazyLoadingValueHolderFactory($config); $container = $this; return $factory->createProxy( @@ -894,10 +911,6 @@ function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $def ); } - if ($definition->isSynthetic()) { - throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); - } - $parameterBag = $this->getParameterBag(); if (null !== $definition->getFile()) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 02866e3ab753e..c72f791f38893 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -171,11 +171,10 @@ private function addProxyLoading($id, Definition $definition) $class = $this->dumpValue($definition->getClass()); if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { + // provided class name is not valid return ''; } - // @todo this should happen directly through the factory class, but we have to ensure that the proxy - // @todo class is generated during the dump process $methodName = 'get' . Container::camelize($id) . 'Service'; $proxyClass = str_replace('\\', '', $definition->getClass()) . '_' . md5(spl_object_hash($definition)); @@ -205,10 +204,6 @@ function (& \$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) */ private function addProxyClasses() { - $definitions = $this->container->getDefinitions(); - - ksort($definitions); - $proxyDefinitions = array_filter( $this->container->getDefinitions(), function (Definition $definition) { @@ -216,8 +211,8 @@ function (Definition $definition) { } ); - if (empty($proxyDefinitions)) { - // avoids hard dependency to ProxyManager + // avoids hard dependency to ProxyManager + if (empty($proxyDefinitions) || !class_exists('ProxyManager\\GeneratorStrategy\\BaseGeneratorStrategy')) { return ''; } diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index d817b9b9b04fd..469811a075d48 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -21,11 +21,12 @@ "require-dev": { "symfony/yaml": "~2.0", "symfony/config": ">=2.2,<2.4-dev", - "ocramius/proxy-manager": "0.3.*" + "ocramius/proxy-manager": ">=0.3.1,<0.4.x-dev" }, "suggest": { "symfony/yaml": "2.2.*", - "symfony/config": "2.2.*" + "symfony/config": "2.2.*", + "ocramius/proxy-manager": "Generate service proxies to lazy load them" }, "autoload": { "psr-0": { "Symfony\\Component\\DependencyInjection\\": "" } From d99443484412fa5efb06ab32d6987f343a0cdde9 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 31 Mar 2013 08:17:48 +0200 Subject: [PATCH 06/39] Adding failing test to demonstrate that proxy initialization breaks shared services --- .../DependencyInjection/Tests/ContainerBuilderTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 1e22d3e778843..0fd3b0f4aebc2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -276,12 +276,14 @@ public function testCreateServiceWithDelegateFactory() /* @var $foo1 \ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */ $foo1 = $builder->get('foo1'); + $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls'); $this->assertInstanceOf('\FooClass', $foo1); $this->assertInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1); $this->assertFalse($foo1->isProxyInitialized()); $foo1->initializeProxy(); + $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved after initialization'); $this->assertTrue($foo1->isProxyInitialized()); $this->assertInstanceOf('\FooClass', $foo1->getWrappedValueHolderValue()); $this->assertNotInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1->getWrappedValueHolderValue()); From 2c6bf548f888879ae99fbb904377626c21dd44f9 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 31 Mar 2013 08:18:19 +0200 Subject: [PATCH 07/39] Fixing shared service instance --- .../DependencyInjection/ContainerBuilder.php | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 9370f690b2b09..1dfe5c3bf3ad8 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -898,8 +898,7 @@ public function createService(Definition $definition, $id, $tryProxy = true) $factory = new LazyLoadingValueHolderFactory($config); $container = $this; - - return $factory->createProxy( + $proxy = $factory->createProxy( $className, function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $definition, $id) { $proxy->setProxyInitializer(null); @@ -909,6 +908,10 @@ function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $def return true; } ); + + $this->shareService($definition, $proxy, $id); + + return $proxy; } $parameterBag = $this->getParameterBag(); @@ -935,16 +938,8 @@ function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $def $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); } - if (self::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { - if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) { - throw new InactiveScopeException($id, $scope); - } - - $this->services[$lowerId = strtolower($id)] = $service; - - if (self::SCOPE_CONTAINER !== $scope) { - $this->scopedServices[$scope][$lowerId] = $service; - } + if (!$definition->isLazy()) { + $this->shareService($definition, $service, $id); } foreach ($definition->getMethodCalls() as $call) { @@ -1089,4 +1084,19 @@ private function callMethod($service, $call) call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1]))); } + + private function shareService(Definition $definition, $service, $id) + { + if (self::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { + if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) { + throw new InactiveScopeException($id, $scope); + } + + $this->services[$lowerId = strtolower($id)] = $service; + + if (self::SCOPE_CONTAINER !== $scope) { + $this->scopedServices[$scope][$lowerId] = $service; + } + } + } } From ee0d51fd3b3a36df7d616494a3710c7cc3fb1296 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 31 Mar 2013 08:27:10 +0200 Subject: [PATCH 08/39] Sharing services in the container should only happen when proxying failed --- src/Symfony/Component/DependencyInjection/ContainerBuilder.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 1dfe5c3bf3ad8..945b40ffa3f1a 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -938,7 +938,8 @@ function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $def $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); } - if (!$definition->isLazy()) { + if ($tryProxy || !$definition->isLazy()) { + // share only if proxying failed, or if not a proxy $this->shareService($definition, $service, $id); } From f986dc731e1e3594fc15d7d63b80488de2b732cb Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 31 Mar 2013 09:00:42 +0200 Subject: [PATCH 09/39] Adding tests for proxy sharing within dumped containers --- .../Tests/Dumper/PhpDumperTest.php | 31 ++- .../Tests/Fixtures/php/lazy_service.php | 199 ++++++++++++++++++ ...service.txt => lazy_service_structure.txt} | 4 +- 3 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php rename src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/{lazy_service.txt => lazy_service_structure.txt} (97%) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index fe1580dfc464f..12f88ca6b19a6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -55,15 +55,38 @@ public function testDumpFrozenContainerWithNoParameter() public function testDumpContainerWithProxyService() { $container = new ContainerBuilder(); + $container->register('foo', 'stdClass'); $container->getDefinition('foo')->setLazy(true); - $container->compile(); - $dumper = new PhpDumper($container); - + $dumper = new PhpDumper($container); $dumpedString = $dumper->dump(); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/lazy_service.txt', $dumpedString, '->dump() does generate proxy lazy loading logic.'); + + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/lazy_service_structure.txt', $dumpedString, '->dump() does generate proxy lazy loading logic.'); + } + + /** + * Verifies that the generated container retrieves the same proxy instance on multiple subsequent requests + */ + public function testDumpContainerWithProxyServiceWillShareProxies() + { + require_once self::$fixturesPath.'/php/lazy_service.php'; + + $container = new \LazyServiceProjectServiceContainer(); + + /* @var $proxy \stdClass_c1d194250ee2e2b7d2eab8b8212368a8 */ + $proxy = $container->get('foo'); + + $this->assertInstanceOf('stdClass_c1d194250ee2e2b7d2eab8b8212368a8', $proxy); + $this->assertSame($proxy, $container->get('foo')); + + $this->assertFalse($proxy->isProxyInitialized()); + + $proxy->initializeProxy(); + + $this->assertTrue($proxy->isProxyInitialized()); + $this->assertSame($proxy, $container->get('foo')); } public function testDumpOptimizationString() diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php new file mode 100644 index 0000000000000..cc69dd8247aa3 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php @@ -0,0 +1,199 @@ + +services = + $this->scopedServices = + $this->scopeStacks = array(); + + $this->set('service_container', $this); + + $this->scopes = array(); + $this->scopeChildren = array(); + } + + /** + * Gets the 'foo' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @param boolean $lazyLoad whether to try lazy-loading the service with a proxy + * + * @return stdClass A stdClass instance. + */ + protected function getFooService($lazyLoad = true) + { + if ($lazyLoad) { + $container = $this; + + return $this->services['foo'] = new stdClass_c1d194250ee2e2b7d2eab8b8212368a8( + function (& $wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) { + $proxy->setProxyInitializer(null); + + $wrappedInstance = $container->getFooService(false); + + return true; + } + ); + } + + return new \stdClass(); + } +} + +class stdClass_c1d194250ee2e2b7d2eab8b8212368a8 extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface +{ + + /** + * @var \Closure|null initializer responsible for generating the wrapped object + */ + private $valueHolder5157dd96e88c0 = null; + + /** + * @var \Closure|null initializer responsible for generating the wrapped object + */ + private $initializer5157dd96e8924 = null; + + /** + * @override constructor for lazy initialization + * + * @param \Closure|null $initializer + */ + public function __construct($initializer) + { + $this->initializer5157dd96e8924 = $initializer; + } + + /** + * @param string $name + */ + public function __get($name) + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__get', array('name' => $name)); + + return $this->valueHolder5157dd96e88c0->$name; + } + + /** + * @param string $name + * @param mixed $value + */ + public function __set($name, $value) + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__set', array('name' => $name, 'value' => $value)); + + $this->valueHolder5157dd96e88c0->$name = $value; + } + + /** + * @param string $name + */ + public function __isset($name) + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__isset', array('name' => $name)); + + return isset($this->valueHolder5157dd96e88c0->$name); + } + + /** + * @param string $name + */ + public function __unset($name) + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__unset', array('name' => $name)); + + unset($this->valueHolder5157dd96e88c0->$name); + } + + /** + * + */ + public function __clone() + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__clone', array()); + + $this->valueHolder5157dd96e88c0 = clone $this->valueHolder5157dd96e88c0; + } + + /** + * + */ + public function __sleep() + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__sleep', array()); + + return array('valueHolder5157dd96e88c0'); + } + + /** + * + */ + public function __wakeup() + { + } + + /** + * {@inheritDoc} + */ + public function setProxyInitializer(\Closure $initializer = null) + { + $this->initializer5157dd96e8924 = $initializer; + } + + /** + * {@inheritDoc} + */ + public function getProxyInitializer() + { + return $this->initializer5157dd96e8924; + } + + /** + * {@inheritDoc} + */ + public function initializeProxy() + { + return $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, 'initializeProxy', array()); + } + + /** + * {@inheritDoc} + */ + public function isProxyInitialized() + { + return null !== $this->valueHolder5157dd96e88c0; + } + + /** + * {@inheritDoc} + */ + public function getWrappedValueHolderValue() + { + return $this->valueHolder5157dd96e88c0; + } + + +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt similarity index 97% rename from src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt rename to src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt index 43d5541451bc2..9247ec9308a84 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt @@ -48,7 +48,7 @@ class ProjectServiceContainer extends Container if ($lazyLoad) { $container = $this; - return new stdClass_%s( + return $this->services['foo'] = new stdClass_%s( function (& $wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) { $proxy->setProxyInitializer(null); @@ -59,7 +59,7 @@ class ProjectServiceContainer extends Container ); } - return $this->services['foo'] = new \stdClass(); + return new \stdClass(); } } From cc56920f0288394d6c5b69aa666679f638413cc4 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 31 Mar 2013 09:01:01 +0200 Subject: [PATCH 10/39] Fixing shared proxies into the container --- .../DependencyInjection/Dumper/PhpDumper.php | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index c72f791f38893..dd001c05454ef 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -164,15 +164,16 @@ private function addServiceLocalTempVariables($cId, $definition) */ private function addProxyLoading($id, Definition $definition) { - if (!($definition->isLazy() && $definition->getClass())) { + if (!$this->isProxyCandidate($definition)) { return ''; } - $class = $this->dumpValue($definition->getClass()); + $instantiation = 'return'; - if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { - // provided class name is not valid - return ''; + if (ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { + $instantiation .= " \$this->services['$id'] ="; + } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { + $instantiation .= " \$this->services['$id'] = \$this->scopedServices['$scope']['$id'] ="; } $methodName = 'get' . Container::camelize($id) . 'Service'; @@ -182,7 +183,7 @@ private function addProxyLoading($id, Definition $definition) if (\$lazyLoad) { \$container = \$this; - return new $proxyClass( + $instantiation new $proxyClass( function (& \$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) use (\$container) { \$proxy->setProxyInitializer(null); @@ -222,13 +223,13 @@ function (Definition $definition) { /* @var $proxyDefinitions Definition[] */ foreach ($proxyDefinitions as $definition) { - $phpClass = new ClassGenerator( + $generatedClass = new ClassGenerator( str_replace('\\', '', $definition->getClass()) . '_' . md5(spl_object_hash($definition)) ); - $proxyGenerator->generate(new ReflectionClass($definition->getClass()), $phpClass); + $proxyGenerator->generate(new ReflectionClass($definition->getClass()), $generatedClass); - $code .= "\n" . $classGenerator->generate($phpClass); + $code .= "\n" . $classGenerator->generate($generatedClass); } return $code; @@ -368,9 +369,10 @@ private function addServiceInstance($id, $definition) $simple = $this->isSimpleInstance($id, $definition); $instantiation = ''; - if (ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { + + if (!$this->isProxyCandidate($definition) && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { $instantiation = "\$this->services['$id'] = ".($simple ? '' : '$instance'); - } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { + } elseif (!$this->isProxyCandidate($definition) && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { $instantiation = "\$this->services['$id'] = \$this->scopedServices['$scope']['$id'] = ".($simple ? '' : '$instance'); } elseif (!$simple) { $instantiation = '$instance'; @@ -1274,6 +1276,24 @@ private function getServiceCall($id, Reference $reference = null) } } + /** + * Tells if the given definitions are to be used for proxying + * + * @param Definition $definition + * + * @return bool + */ + private function isProxyCandidate(Definition $definition) + { + if (!($definition->isLazy() && $definition->getClass())) { + return false; + } + + $class = $this->dumpValue($definition->getClass()); + + return (boolean) preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class); + } + /** * Returns the next name to use * From a6b031e521171aada44d33d3a72e3cc032f747c3 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 31 Mar 2013 09:06:27 +0200 Subject: [PATCH 11/39] Bumping required version of ProxyManager --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index bf74f0864c187..1e3fdae52142f 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,7 @@ "monolog/monolog": "~1.3", "propel/propel1": "1.6.*", "ircmaxell/password-compat": "1.0.*", - "ocramius/proxy-manager": "0.3.*" + "ocramius/proxy-manager": ">=0.3.1,<0.4-dev" }, "autoload": { "psr-0": { "Symfony\\": "src/" }, From d8acc5ed30c60c930d6b692d889cbffc7b8d314c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 31 Mar 2013 09:07:07 +0200 Subject: [PATCH 12/39] Docblock for ContainerBuilder#shareService --- .../Component/DependencyInjection/ContainerBuilder.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 945b40ffa3f1a..50f5e4f13db12 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1086,6 +1086,15 @@ private function callMethod($service, $call) call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1]))); } + /** + * Shares a given service in the container + * + * @param Definition $definition + * @param mixed $service + * @param string $id + * + * @throws Exception\RuntimeException + */ private function shareService(Definition $definition, $service, $id) { if (self::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { From e5f6bf208475a6790476256ce43822eb8027d653 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 31 Mar 2013 10:52:31 +0200 Subject: [PATCH 13/39] Adding `ContainerBuilder#addClassResource` --- .../DependencyInjection/ContainerBuilder.php | 26 ++++++-- .../Tests/ContainerBuilderTest.php | 60 +++++++++++++++++++ 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 50f5e4f13db12..d70498137dfa0 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -15,6 +15,7 @@ use ProxyManager\Factory\LazyLoadingValueHolderFactory; use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; use ProxyManager\Proxy\LazyLoadingInterface; +use ReflectionClass; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; @@ -226,15 +227,32 @@ public function setResources(array $resources) * @api */ public function addObjectResource($object) + { + if ($this->trackResources) { + $this->addClassResource(new ReflectionClass($object)); + } + + return $this; + } + + /** + * Adds the given class hierarchy as resources. + * + * @param \ReflectionClass $class + * + * @return ContainerBuilder The current instance + * + * @api + */ + public function addClassResource(ReflectionClass $class) { if (!$this->trackResources) { return $this; } - $parent = new \ReflectionObject($object); do { - $this->addResource(new FileResource($parent->getFileName())); - } while ($parent = $parent->getParentClass()); + $this->addResource(new FileResource($class->getFileName())); + } while ($class = $class->getParentClass()); return $this; } @@ -933,7 +951,7 @@ function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $def $service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments); } else { - $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass())); + $r = new ReflectionClass($parameterBag->resolveValue($definition->getClass())); $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 0fd3b0f4aebc2..6fe92afce3db9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -491,6 +491,66 @@ public function testFindDefinition() $this->assertEquals($definition, $container->findDefinition('foobar'), '->findDefinition() returns a Definition'); } + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addObjectResource + */ + public function testAddObjectResource() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $container = new ContainerBuilder(); + + $container->setResourceTracking(false); + $container->addObjectResource(new \BarClass()); + + $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking'); + + $container->setResourceTracking(true); + $container->addObjectResource(new \BarClass()); + + $resources = $container->getResources(); + + $this->assertCount(1, $resources, '1 resource was registered'); + + /* @var $resource \Symfony\Component\Config\Resource\FileResource */ + $resource = end($resources); + + $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource); + $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource())); + } + + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addClassResource + */ + public function testAddClassResource() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $container = new ContainerBuilder(); + + $container->setResourceTracking(false); + $container->addClassResource(new \ReflectionClass('BarClass')); + + $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking'); + + $container->setResourceTracking(true); + $container->addClassResource(new \ReflectionClass('BarClass')); + + $resources = $container->getResources(); + + $this->assertCount(1, $resources, '1 resource was registered'); + + /* @var $resource \Symfony\Component\Config\Resource\FileResource */ + $resource = end($resources); + + $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource); + $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource())); + } + /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getResources * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addResource From fa46c93ccfb3351feaf2743045d515d37f8de920 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Mon, 1 Apr 2013 13:03:54 +0200 Subject: [PATCH 14/39] Adding test to check that class resources are registered for lazy services --- .../Tests/ContainerBuilderTest.php | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 6fe92afce3db9..b1b0a040f5776 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -14,6 +14,7 @@ require_once __DIR__.'/Fixtures/includes/classes.php'; require_once __DIR__.'/Fixtures/includes/ProjectExtension.php'; +use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -551,6 +552,35 @@ public function testAddClassResource() $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource())); } + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::compile + */ + public function testCompilesClassDefinitionsOfLazyServices() + { + if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { + $this->markTestSkipped('The "Config" component is not available'); + } + + $container = new ContainerBuilder(); + + $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking'); + + $container->register('foo', 'BarClass'); + $container->getDefinition('foo')->setLazy(true); + + $container->compile(); + + $classesPath = realpath(__DIR__.'/Fixtures/includes/classes.php'); + $matchingResources = array_filter( + $container->getResources(), + function (ResourceInterface $resource) use ($classesPath) { + return $resource instanceof FileResource && $classesPath === realpath($resource->getResource()); + } + ); + + $this->assertNotEmpty($matchingResources); + } + /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getResources * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addResource From b90b35923741ca386267cfaac193acc24fb8683c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Mon, 1 Apr 2013 13:04:25 +0200 Subject: [PATCH 15/39] Fixing tests, registering class resources for lazy services --- .../Component/DependencyInjection/ContainerBuilder.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index d70498137dfa0..1bd112170ca25 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -606,6 +606,12 @@ public function compile() foreach ($this->compiler->getPassConfig()->getPasses() as $pass) { $this->addObjectResource($pass); } + + foreach ($this->definitions as $definition) { + if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) { + $this->addClassResource(new ReflectionClass($class)); + } + } } $this->compiler->compile($this); From eb3d7035d9f56ca26d7c25f917a57e4cc9deb188 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 2 Apr 2013 20:43:26 +0200 Subject: [PATCH 16/39] Reverting import of global namespace classes --- .../Component/DependencyInjection/ContainerBuilder.php | 9 ++++----- .../Component/DependencyInjection/Dumper/PhpDumper.php | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 1bd112170ca25..1ccbf34e55d66 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -15,7 +15,6 @@ use ProxyManager\Factory\LazyLoadingValueHolderFactory; use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; use ProxyManager\Proxy\LazyLoadingInterface; -use ReflectionClass; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; @@ -229,7 +228,7 @@ public function setResources(array $resources) public function addObjectResource($object) { if ($this->trackResources) { - $this->addClassResource(new ReflectionClass($object)); + $this->addClassResource(new \ReflectionClass($object)); } return $this; @@ -244,7 +243,7 @@ public function addObjectResource($object) * * @api */ - public function addClassResource(ReflectionClass $class) + public function addClassResource(\ReflectionClass $class) { if (!$this->trackResources) { return $this; @@ -609,7 +608,7 @@ public function compile() foreach ($this->definitions as $definition) { if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) { - $this->addClassResource(new ReflectionClass($class)); + $this->addClassResource(new \ReflectionClass($class)); } } } @@ -957,7 +956,7 @@ function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $def $service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments); } else { - $r = new ReflectionClass($parameterBag->resolveValue($definition->getClass())); + $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass())); $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index dd001c05454ef..18523dc0f3560 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -14,7 +14,6 @@ use ProxyManager\Generator\ClassGenerator; use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy; use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator; -use ReflectionClass; use Symfony\Component\DependencyInjection\Variable; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -227,7 +226,7 @@ function (Definition $definition) { str_replace('\\', '', $definition->getClass()) . '_' . md5(spl_object_hash($definition)) ); - $proxyGenerator->generate(new ReflectionClass($definition->getClass()), $generatedClass); + $proxyGenerator->generate(new \ReflectionClass($definition->getClass()), $generatedClass); $code .= "\n" . $classGenerator->generate($generatedClass); } From e3646161b6a6f2d4ef04606faa87c9a6cb0cf9ff Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 25 Apr 2013 21:50:41 +0200 Subject: [PATCH 17/39] Lazier checks on the proxy structure (avoiding whitespace-based test failures --- .../Fixtures/php/lazy_service_structure.txt | 133 ++++-------------- 1 file changed, 30 insertions(+), 103 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt index 9247ec9308a84..a0bd62e8dbb2a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt @@ -64,135 +64,62 @@ class ProjectServiceContainer extends Container } class stdClass_%s extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface -{ - - /** - * @var \Closure|null initializer responsible for generating the wrapped object - */ +{%a + /**%a*/ private %s = null; - /** - * @var \Closure|null initializer responsible for generating the wrapped object - */ + /**%a*/ private %s = null; - /** - * @override constructor for lazy initialization - * - * @param \Closure|null $initializer - */ + /**%a*/ public function __construct($initializer) - { - $this->%s = $initializer; - } + {%a} - /** - * @param string $name - */ + /**%a*/ public function __get($name) - { - $this->%s && $this->%s->__invoke($this->%s, $this, '__get', array('name' => $name)); + {%a} - return $this->%s->$name; - } - - /** - * @param string $name - * @param mixed $value - */ + /**%a*/ public function __set($name, $value) - { - $this->%s && $this->%s->__invoke($this->%s, $this, '__set', array('name' => $name, 'value' => $value)); - - $this->%s->$name = $value; - } + {%a} - /** - * @param string $name - */ + /**%a*/ public function __isset($name) - { - $this->%s && $this->%s->__invoke($this->%s, $this, '__isset', array('name' => $name)); - - return isset($this->%s->$name); - } + {%a} - /** - * @param string $name - */ + /**%a*/ public function __unset($name) - { - $this->%s && $this->%s->__invoke($this->%s, $this, '__unset', array('name' => $name)); - - unset($this->%s->$name); - } + {%a} - /** - * - */ + /**%a*/ public function __clone() - { - $this->%s && $this->%s->__invoke($this->%s, $this, '__clone', array()); + {%a} - $this->%s = clone $this->%s; - } - - /** - * - */ + /**%a*/ public function __sleep() - { - $this->%s && $this->%s->__invoke($this->%s, $this, '__sleep', array()); - - return array('%s'); - } + {%a} - /** - * - */ + /**%a*/ public function __wakeup() - { - } + {%a} - /** - * {@inheritDoc} - */ + /**%a*/ public function setProxyInitializer(\Closure $initializer = null) - { - $this->%s = $initializer; - } + {%a} - /** - * {@inheritDoc} - */ + /**%a*/ public function getProxyInitializer() - { - return $this->%s; - } + {%a} - /** - * {@inheritDoc} - */ + /**%a*/ public function initializeProxy() - { - return $this->%s && $this->%s->__invoke($this->%s, $this, 'initializeProxy', array()); - } + {%a} - /** - * {@inheritDoc} - */ + /**%a*/ public function isProxyInitialized() - { - return null !== $this->%s; - } + {%a} - /** - * {@inheritDoc} - */ + /**%a*/ public function getWrappedValueHolderValue() - { - return $this->%s; - } - - -} \ No newline at end of file + {%a} +%a} \ No newline at end of file From ba3a232e06a0bcb38d4e6235173a0ff41625cf9d Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 25 Apr 2013 22:06:27 +0200 Subject: [PATCH 18/39] Getters for proxied services are public for 5.3.3 compatibility --- .../DependencyInjection/ContainerBuilder.php | 11 ++++++----- .../DependencyInjection/Dumper/PhpDumper.php | 9 ++++++--- .../Tests/Fixtures/php/lazy_service.php | 2 +- .../Tests/Fixtures/php/lazy_service_structure.txt | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 1ccbf34e55d66..030551a955782 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -434,13 +434,14 @@ public function has($id) * Gets a service. * * @param string $id The service identifier - * @param integer $invalidBehavior The behavior when the service does not exist + * @param int $invalidBehavior The behavior when the service does not exist * + * @throws InvalidArgumentException + * @throws InactiveScopeException + * @throws LogicException + * @throws \Exception * @return object The associated service * - * @throws InvalidArgumentException if the service is not defined - * @throws LogicException if the service has a circular reference to itself - * * @see Reference * * @api @@ -1116,7 +1117,7 @@ private function callMethod($service, $call) * @param mixed $service * @param string $id * - * @throws Exception\RuntimeException + * @throws InactiveScopeException */ private function shareService(Definition $definition, $service, $id) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 18523dc0f3560..64b7b7af2f22f 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -578,19 +578,22 @@ private function addService($id, $definition) $lazyInitializationDoc = ''; } - $code = <<isProxyCandidate($definition); + $visibility = $isProxyCandidate ? 'public' : 'protected'; + $code = <<addProxyLoading($id, $definition); + $code .= $isProxyCandidate ? $this->addProxyLoading($id, $definition) : ''; if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) { $code .= << Date: Thu, 25 Apr 2013 23:33:15 +0200 Subject: [PATCH 19/39] Enforcing soft dependency to ProxyManager --- .../DependencyInjection/Dumper/PhpDumper.php | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 64b7b7af2f22f..b502bdc6f99d8 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -176,7 +176,7 @@ private function addProxyLoading($id, Definition $definition) } $methodName = 'get' . Container::camelize($id) . 'Service'; - $proxyClass = str_replace('\\', '', $definition->getClass()) . '_' . md5(spl_object_hash($definition)); + $proxyClass = str_replace('\\', '', $definition->getClass()) . '_' . spl_object_hash($definition); return <<container->getDefinitions(), - function (Definition $definition) { - return $definition->isLazy() && $definition->getClass(); + $proxyDefinitions = array(); + + foreach ($this->container->getDefinitions() as $definition) { + if ($this->isProxyCandidate($definition)) { + $proxyDefinitions[] = $definition; } - ); + } // avoids hard dependency to ProxyManager - if (empty($proxyDefinitions) || !class_exists('ProxyManager\\GeneratorStrategy\\BaseGeneratorStrategy')) { + if (empty($proxyDefinitions)) { return ''; } @@ -365,13 +366,13 @@ private function addServiceInstance($id, $definition) throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id)); } - $simple = $this->isSimpleInstance($id, $definition); - - $instantiation = ''; + $simple = $this->isSimpleInstance($id, $definition); + $isProxyCandidate = $this->isProxyCandidate($definition); + $instantiation = ''; - if (!$this->isProxyCandidate($definition) && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { + if (!$isProxyCandidate && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { $instantiation = "\$this->services['$id'] = ".($simple ? '' : '$instance'); - } elseif (!$this->isProxyCandidate($definition) && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { + } elseif (!$isProxyCandidate && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { $instantiation = "\$this->services['$id'] = \$this->scopedServices['$scope']['$id'] = ".($simple ? '' : '$instance'); } elseif (!$simple) { $instantiation = '$instance'; @@ -1279,7 +1280,8 @@ private function getServiceCall($id, Reference $reference = null) } /** - * Tells if the given definitions are to be used for proxying + * Tells if the given definitions are to be used for proxying, and if proxying is possible, + * since ProxyManager may not be available * * @param Definition $definition * @@ -1287,7 +1289,11 @@ private function getServiceCall($id, Reference $reference = null) */ private function isProxyCandidate(Definition $definition) { - if (!($definition->isLazy() && $definition->getClass())) { + if (!( + $definition->isLazy() + && $definition->getClass() + && class_exists('ProxyManager\\Factory\\LazyLoadingValueHolderFactory') + )) { return false; } From 2881fccae60820eb3a89f97ff2d54c2a9776f8b8 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 25 Apr 2013 23:38:19 +0200 Subject: [PATCH 20/39] Reverting documentation changes, adding exception types description in `@throws` --- .../DependencyInjection/ContainerBuilder.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 030551a955782..654c42b302b3f 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -434,14 +434,15 @@ public function has($id) * Gets a service. * * @param string $id The service identifier - * @param int $invalidBehavior The behavior when the service does not exist + * @param integer $invalidBehavior The behavior when the service does not exist * - * @throws InvalidArgumentException - * @throws InactiveScopeException - * @throws LogicException - * @throws \Exception * @return object The associated service * + * @throws InvalidArgumentException when no definitions are available + * @throws InactiveScopeException when the current scope is not active + * @throws LogicException when a circular dependency is detected + * @throws \Exception + * * @see Reference * * @api From 1439e0bb87ef88f3b9e4032b59cd87b5a3354f57 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 27 Apr 2013 21:30:48 +0200 Subject: [PATCH 21/39] Lazier checks on the proxy structure --- .../Fixtures/php/lazy_service_structure.txt | 60 +------------------ 1 file changed, 1 insertion(+), 59 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt index a9210c6d35eaf..1eaf8cad606c3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt @@ -64,62 +64,4 @@ class ProjectServiceContainer extends Container } class stdClass_%s extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface -{%a - /**%a*/ - private %s = null; - - /**%a*/ - private %s = null; - - /**%a*/ - public function __construct($initializer) - {%a} - - /**%a*/ - public function __get($name) - {%a} - - /**%a*/ - public function __set($name, $value) - {%a} - - /**%a*/ - public function __isset($name) - {%a} - - /**%a*/ - public function __unset($name) - {%a} - - /**%a*/ - public function __clone() - {%a} - - /**%a*/ - public function __sleep() - {%a} - - /**%a*/ - public function __wakeup() - {%a} - - /**%a*/ - public function setProxyInitializer(\Closure $initializer = null) - {%a} - - /**%a*/ - public function getProxyInitializer() - {%a} - - /**%a*/ - public function initializeProxy() - {%a} - - /**%a*/ - public function isProxyInitialized() - {%a} - - /**%a*/ - public function getWrappedValueHolderValue() - {%a} -%a} \ No newline at end of file +{%a} \ No newline at end of file From 95db92afa6fc87cd6915f5d4500057fe5a7bcc19 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 30 Apr 2013 20:05:43 +0200 Subject: [PATCH 22/39] Adding ProxyManager bridge structure --- composer.json | 3 +- src/Symfony/Bridge/ProxyManager/.gitignore | 4 +++ src/Symfony/Bridge/ProxyManager/CHANGELOG.md | 7 ++++ src/Symfony/Bridge/ProxyManager/LICENSE | 19 ++++++++++ .../LazyProxy/Dumper/ProxyDumper.php | 21 +++++++++++ .../Instantiator/RuntimeInstantiator.php | 21 +++++++++++ src/Symfony/Bridge/ProxyManager/README.md | 13 +++++++ src/Symfony/Bridge/ProxyManager/composer.json | 36 +++++++++++++++++++ .../Bridge/ProxyManager/phpunit.xml.dist | 30 ++++++++++++++++ 9 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Bridge/ProxyManager/.gitignore create mode 100644 src/Symfony/Bridge/ProxyManager/CHANGELOG.md create mode 100644 src/Symfony/Bridge/ProxyManager/LICENSE create mode 100644 src/Symfony/Bridge/ProxyManager/LazyProxy/Dumper/ProxyDumper.php create mode 100644 src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php create mode 100644 src/Symfony/Bridge/ProxyManager/README.md create mode 100644 src/Symfony/Bridge/ProxyManager/composer.json create mode 100644 src/Symfony/Bridge/ProxyManager/phpunit.xml.dist diff --git a/composer.json b/composer.json index 1e3fdae52142f..3fed8f0a03e0b 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,8 @@ "monolog/monolog": "~1.3", "propel/propel1": "1.6.*", "ircmaxell/password-compat": "1.0.*", - "ocramius/proxy-manager": ">=0.3.1,<0.4-dev" + "ocramius/proxy-manager": ">=0.3.1,<0.4-dev", + "zendframework/zend-code": "2.*" }, "autoload": { "psr-0": { "Symfony\\": "src/" }, diff --git a/src/Symfony/Bridge/ProxyManager/.gitignore b/src/Symfony/Bridge/ProxyManager/.gitignore new file mode 100644 index 0000000000000..44de97a36a6df --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/.gitignore @@ -0,0 +1,4 @@ +vendor/ +composer.lock +phpunit.xml + diff --git a/src/Symfony/Bridge/ProxyManager/CHANGELOG.md b/src/Symfony/Bridge/ProxyManager/CHANGELOG.md new file mode 100644 index 0000000000000..1f8f60c48bfed --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +2.3.0 +----- + + * First introduction of `Symfony\Bridge\ProxyManager` diff --git a/src/Symfony/Bridge/ProxyManager/LICENSE b/src/Symfony/Bridge/ProxyManager/LICENSE new file mode 100644 index 0000000000000..88a57f8d8da49 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2013 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Dumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Dumper/ProxyDumper.php new file mode 100644 index 0000000000000..3f31dcb495e55 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Dumper/ProxyDumper.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\ProxyManager\LazyProxy\Dumper; + +/** + * Runtime lazy loading proxy generator + * + * @author Marco Pivetta + */ +class ProxyDumper +{ +} \ No newline at end of file diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php new file mode 100644 index 0000000000000..e7aa79d8b0796 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\ProxyManager\LazyProxy; + +/** + * Runtime lazy loading proxy generator + * + * @author Marco Pivetta + */ +class RuntimeInstantiator +{ +} diff --git a/src/Symfony/Bridge/ProxyManager/README.md b/src/Symfony/Bridge/ProxyManager/README.md new file mode 100644 index 0000000000000..7319ddbbf4550 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/README.md @@ -0,0 +1,13 @@ +ProxyManager Bridge +=================== + +Provides integration for [ProxyManager](https://github.com/Ocramius/ProxyManager) with various Symfony2 components. + +Resources +--------- + +You can run the unit tests with the following command: + + $ cd path/to/Symfony/Bridge/ProxyManager/ + $ composer.phar install --dev + $ phpunit diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json new file mode 100644 index 0000000000000..e3fca38fc3f10 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -0,0 +1,36 @@ +{ + "name": "symfony/proxy-manager-bridge", + "type": "symfony-bridge", + "description": "Symfony ProxyManager Bridge", + "keywords": [], + "homepage": "http://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3", + "symfony/dependency-injection": ">=2.3-dev,<2.4-dev", + "ocramius/proxy-manager": "0.3.*", + "zendframework/zend-code": "2.*" + }, + "autoload": { + "psr-0": { + "Symfony\\Bridge\\ProxyManager\\": "" + } + }, + "target-dir": "Symfony/Bridge/ProxyManager", + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + } +} diff --git a/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist b/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist new file mode 100644 index 0000000000000..0e2acb60d2752 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist @@ -0,0 +1,30 @@ + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + + + + From 5a4513c6ab1ef4d425532c66aad7f033a0e8cfd5 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 30 Apr 2013 21:15:42 +0200 Subject: [PATCH 23/39] Adding implementation of the proxy dumper and instantiator --- .../LazyProxy/Dumper/ProxyDumper.php | 21 ---- .../Instantiator/RuntimeInstantiator.php | 43 ++++++- .../LazyProxy/PhpDumper/ProxyDumper.php | 115 ++++++++++++++++++ .../Instantiator/InstantiatorInterface.php | 39 ++++++ .../Instantiator/RealServiceInstantiator.php | 33 +++++ .../LazyProxy/PhpDumper/DumperInterface.php | 59 +++++++++ .../LazyProxy/PhpDumper/NullDumper.php | 47 +++++++ 7 files changed, 335 insertions(+), 22 deletions(-) delete mode 100644 src/Symfony/Bridge/ProxyManager/LazyProxy/Dumper/ProxyDumper.php create mode 100644 src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php create mode 100644 src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php create mode 100644 src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php create mode 100644 src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php create mode 100644 src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Dumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Dumper/ProxyDumper.php deleted file mode 100644 index 3f31dcb495e55..0000000000000 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/Dumper/ProxyDumper.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\ProxyManager\LazyProxy\Dumper; - -/** - * Runtime lazy loading proxy generator - * - * @author Marco Pivetta - */ -class ProxyDumper -{ -} \ No newline at end of file diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php index e7aa79d8b0796..bbb196f77b0cd 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php @@ -11,11 +11,52 @@ namespace Symfony\Bridge\ProxyManager\LazyProxy; +use ProxyManager\Configuration; +use ProxyManager\Factory\LazyLoadingValueHolderFactory; +use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; +use ProxyManager\Proxy\LazyLoadingInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; + /** * Runtime lazy loading proxy generator * * @author Marco Pivetta */ -class RuntimeInstantiator +class RuntimeInstantiator implements InstantiatorInterface { + /** + * @var \ProxyManager\Factory\LazyLoadingValueHolderFactory + */ + protected $factory; + + /** + * Constructor + */ + public function __construct() + { + $config = new Configuration(); + + $config->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); + + $this->factory = new LazyLoadingValueHolderFactory($config); + } + + /** + * {@inheritDoc} + */ + public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator) + { + return $this->factory->createProxy( + $definition->getClass(), + function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($realInstantiator) { + $proxy->setProxyInitializer(null); + + $wrappedInstance = call_user_func($realInstantiator); + + return true; + } + ); + } } diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php new file mode 100644 index 0000000000000..80e3683dad590 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper; + +use ProxyManager\Generator\ClassGenerator; +use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy; +use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface; + +/** + * Generates dumped php code of proxies via reflection + * + * @author Marco Pivetta + */ +class ProxyDumper implements DumperInterface +{ + /** + * @var \ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator + */ + protected $proxyGenerator; + + /** + * @var \ProxyManager\GeneratorStrategy\BaseGeneratorStrategy + */ + protected $classGenerator; + + /** + * Constructor + */ + public function __construct() + { + $this->proxyGenerator = new LazyLoadingValueHolderGenerator(); + $this->classGenerator = new BaseGeneratorStrategy(); + } + /** + * {@inheritDoc} + */ + public function isProxyCandidate(Definition $definition) + { + return $definition->isLazy() + && ($class = $definition->getClass()) + && class_exists($class); + } + + /** + * {@inheritDoc} + */ + public function getProxyFactoryCode(Definition $definition, $id) + { + $instantiation = 'return'; + + if (ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { + $instantiation .= " \$this->services['$id'] ="; + } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { + $instantiation .= " \$this->services['$id'] = \$this->scopedServices['$scope']['$id'] ="; + } + + $methodName = 'get' . Container::camelize($id) . 'Service'; + $proxyClass = $this->getProxyClassName($definition); + + return <<setProxyInitializer(null); + + \$wrappedInstance = \$container->$methodName(false); + + return true; + } + ); + } + + +EOF; + } + + /** + * {@inheritDoc} + */ + public function getProxyCode(Definition $definition) + { + $generatedClass = new ClassGenerator($this->getProxyClassName($definition)); + + $this->proxyGenerator->generate(new \ReflectionClass($definition->getClass()), $generatedClass); + + return $this->classGenerator->generate($generatedClass); + } + + /** + * Produces the proxy class name for the given definition + * + * @param Definition $definition + * + * @return string + */ + private function getProxyClassName(Definition $definition) + { + return str_replace('\\', '', $definition->getClass()) . '_' . spl_object_hash($definition); + } +} diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php new file mode 100644 index 0000000000000..bfafd0271ce2b --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Lazy proxy instantiator, capable of instantiating a proxy given a container, the + * service definitions and a callback that produces the real service instance + * + * @author Marco Pivetta + * + * @api + */ +interface InstantiatorInterface +{ + /** + * @param ContainerInterface $container the container from which the service is being requested + * @param Definition $definition the definitions of the requested service + * @param string $id identifier of the requested service + * @param callable $realInstantiator zero-argument callback that is capable of producing the real + * service instance + * + * @return object + * + * @api + */ + public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator); +} diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php new file mode 100644 index 0000000000000..a39bb430b1f4e --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; + +/** + * {@inheritDoc} + * + * Noop proxy instantiator - simply produces the real service instead of a proxy instance + * + * @author Marco Pivetta + */ +class RealServiceInstantiator implements InstantiatorInterface +{ + /** + * {@inheritDoc} + */ + public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator) + { + return call_user_func($realInstantiator); + } +} diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php new file mode 100644 index 0000000000000..e41ed25899c67 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Lazy proxy dumper capable of generating the instantiation logic php code for proxied services + * + * @author Marco Pivetta + * + * @api + */ +interface DumperInterface +{ + /** + * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container + * + * @param Definition $definition + * + * @return bool + * + * @api + */ + public function isProxyCandidate(Definition $definition); + + /** + * Generates the code to be used to instantiate a proxy in the dumped factory code + * + * @param Definition $definition + * @param string $id service identifier + * + * @return string + * + * @api + */ + public function getProxyFactoryCode(Definition $definition, $id); + + /** + * Generates the code for the lazy proxy + * + * @param Definition $definition + * + * @return string + * + * @api + */ + public function getProxyCode(Definition $definition); +} diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php new file mode 100644 index 0000000000000..b2ff41d69fd62 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Null dumper, negates any proxy code generation for any given service definition + * + * @author Marco Pivetta + */ +class NullDumper implements DumperInterface +{ + /** + * {@inheritDoc} + */ + public function isProxyCandidate(Definition $definition) + { + return false; + } + + /** + * {@inheritDoc} + */ + public function getProxyFactoryCode(Definition $definition, $id) + { + return ''; + } + + /** + * {@inheritDoc} + */ + public function getProxyCode(Definition $definition) + { + return ''; + } +} From fa2445c528cbbfa783b57972f27edce37f12a49b Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 30 Apr 2013 21:24:39 +0200 Subject: [PATCH 24/39] Using the proxy dumper in the php dumper --- .../Instantiator/RuntimeInstantiator.php | 2 +- .../DependencyInjection/Dumper/PhpDumper.php | 106 ++---------------- 2 files changed, 12 insertions(+), 96 deletions(-) diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php index bbb196f77b0cd..e8df0e032d9d7 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Bridge\ProxyManager\LazyProxy; +namespace Symfony\Bridge\ProxyManager\LazyProxy\Instantiator; use ProxyManager\Configuration; use ProxyManager\Factory\LazyLoadingValueHolderFactory; diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index b502bdc6f99d8..17833a542185d 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -53,6 +53,8 @@ class PhpDumper extends Dumper private $variableCount; private $reservedVariables = array('instance', 'class'); + private $proxyDumper; + /** * {@inheritDoc} * @@ -63,6 +65,7 @@ public function __construct(ContainerBuilder $container) parent::__construct($container); $this->inlinedDefinitions = new \SplObjectStorage; + $this->proxyDumper = new \Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; } /** @@ -154,82 +157,18 @@ private function addServiceLocalTempVariables($cId, $definition) } /** - * Generates the logic required for proxy lazy loading - * - * @param string $id The service id - * @param Definition $definition - * - * @return string - */ - private function addProxyLoading($id, Definition $definition) - { - if (!$this->isProxyCandidate($definition)) { - return ''; - } - - $instantiation = 'return'; - - if (ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { - $instantiation .= " \$this->services['$id'] ="; - } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { - $instantiation .= " \$this->services['$id'] = \$this->scopedServices['$scope']['$id'] ="; - } - - $methodName = 'get' . Container::camelize($id) . 'Service'; - $proxyClass = str_replace('\\', '', $definition->getClass()) . '_' . spl_object_hash($definition); - - return <<setProxyInitializer(null); - - \$wrappedInstance = \$container->$methodName(false); - - return true; - } - ); - } - - -EOF; - } - - /** - * Generates code for the proxy classes to be attached after the container class + * Generates code for the proxies to be attached after the container class * * @return string */ private function addProxyClasses() { - $proxyDefinitions = array(); - - foreach ($this->container->getDefinitions() as $definition) { - if ($this->isProxyCandidate($definition)) { - $proxyDefinitions[] = $definition; - } - } - - // avoids hard dependency to ProxyManager - if (empty($proxyDefinitions)) { - return ''; - } - - $proxyGenerator = new LazyLoadingValueHolderGenerator(); - $classGenerator = new BaseGeneratorStrategy(); - $code = ''; - /* @var $proxyDefinitions Definition[] */ - foreach ($proxyDefinitions as $definition) { - $generatedClass = new ClassGenerator( - str_replace('\\', '', $definition->getClass()) . '_' . md5(spl_object_hash($definition)) - ); - - $proxyGenerator->generate(new \ReflectionClass($definition->getClass()), $generatedClass); + $definitions = array_filter($this->container->getDefinitions(), array($this->proxyDumper, 'isProxyCandidate')); + $code = ''; - $code .= "\n" . $classGenerator->generate($generatedClass); + foreach ($definitions as $definition) { + $code .= "\n" . $this->proxyDumper->getProxyCode($definition); } return $code; @@ -367,7 +306,7 @@ private function addServiceInstance($id, $definition) } $simple = $this->isSimpleInstance($id, $definition); - $isProxyCandidate = $this->isProxyCandidate($definition); + $isProxyCandidate = $this->proxyDumper->isProxyCandidate($definition); $instantiation = ''; if (!$isProxyCandidate && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { @@ -580,7 +519,7 @@ private function addService($id, $definition) } // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer - $isProxyCandidate = $this->isProxyCandidate($definition); + $isProxyCandidate = $this->proxyDumper->isProxyCandidate($definition); $visibility = $isProxyCandidate ? 'public' : 'protected'; $code = <<addProxyLoading($id, $definition) : ''; + $code .= $isProxyCandidate ? $this->proxyDumper->getProxyFactoryCode($definition, $id) : ''; if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) { $code .= <<isLazy() - && $definition->getClass() - && class_exists('ProxyManager\\Factory\\LazyLoadingValueHolderFactory') - )) { - return false; - } - - $class = $this->dumpValue($definition->getClass()); - - return (boolean) preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class); - } - /** * Returns the next name to use * From eba1909247cd899e61e6b1c9de2d5f0c76dd9fec Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 30 Apr 2013 21:53:42 +0200 Subject: [PATCH 25/39] Re-configuring the container builder to get proxy generators injected from the kernel --- .../DependencyInjection/ContainerBuilder.php | 103 +++++++++++++----- .../DependencyInjection/Dumper/PhpDumper.php | 5 +- src/Symfony/Component/HttpKernel/Kernel.php | 11 +- 3 files changed, 90 insertions(+), 29 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 654c42b302b3f..d2b6e595df103 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -11,10 +11,8 @@ namespace Symfony\Component\DependencyInjection; -use ProxyManager\Configuration; -use ProxyManager\Factory\LazyLoadingValueHolderFactory; -use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; -use ProxyManager\Proxy\LazyLoadingInterface; +use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; +use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; @@ -26,6 +24,10 @@ use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; +use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; +use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface; +use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; /** * ContainerBuilder is a DI container that provides an API to easily describe services. @@ -75,6 +77,16 @@ class ContainerBuilder extends Container implements TaggedContainerInterface private $trackResources = true; + /** + * @var InstantiatorInterface|null + */ + private $proxyInstantiator; + + /** + * @var DumperInterface|null + */ + private $proxyDumper; + /** * Sets the track resources flag. * @@ -98,6 +110,58 @@ public function isTrackingResources() return $this->trackResources; } + /** + * Sets the instantiator to be used when fetching proxies + * + * @param InstantiatorInterface $proxyInstantiator + */ + public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) + { + $this->proxyInstantiator = $proxyInstantiator; + } + + /** + * Retrieves the currently set proxy instantiator + * + * @return InstantiatorInterface + */ + public function getProxyInstantiator() + { + if (!$this->proxyInstantiator) { + //$this->proxyInstantiator = new RealServiceInstantiator(); + $this->proxyInstantiator = new RuntimeInstantiator(); + } + + return $this->proxyInstantiator; + } + + /** + * Sets the dumper to be used when dumping proxies in the generated container + * + * @todo not responsibility of the ContainerBuilder? + * + * @param DumperInterface $proxyInstantiator + */ + public function setProxyDumper(DumperInterface $proxyDumper) + { + $this->proxyDumper = $proxyDumper; + } + + /** + * Retrieves the currently set proxy dumper used when dumping proxies in the generated container + * + * @return DumperInterface + */ + public function getProxyDumper() + { + if (!$this->proxyDumper) { + //$this->proxyDumper = new NullDumper(); + $this->proxyDumper = new ProxyDumper(); + } + + return $this->proxyDumper; + } + /** * Registers an extension. * @@ -911,29 +975,18 @@ public function createService(Definition $definition, $id, $tryProxy = true) throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); } - if ( - $tryProxy - && ($className = $definition->getClass()) - && $definition->isLazy() - && class_exists('ProxyManager\\Factory\\LazyLoadingValueHolderFactory') - ) { - $config = new Configuration(); - - $config->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); - - $factory = new LazyLoadingValueHolderFactory($config); + if ($tryProxy && $definition->isLazy()) { $container = $this; - $proxy = $factory->createProxy( - $className, - function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $definition, $id) { - $proxy->setProxyInitializer(null); - - $wrappedInstance = $container->createService($definition, $id, false); - - return true; - } - ); + $proxy = $this + ->getProxyInstantiator() + ->instantiateProxy( + $container, + $definition, + $id, function () use ($definition, $id, $container) { + return $container->createService($definition, $id, false); + } + ); $this->shareService($definition, $proxy, $id); return $proxy; diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 17833a542185d..dd6c82b993c10 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -11,9 +11,7 @@ namespace Symfony\Component\DependencyInjection\Dumper; -use ProxyManager\Generator\ClassGenerator; -use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy; -use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator; +use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; use Symfony\Component\DependencyInjection\Variable; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -66,6 +64,7 @@ public function __construct(ContainerBuilder $container) $this->inlinedDefinitions = new \SplObjectStorage; $this->proxyDumper = new \Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; + //$this->proxyDumper = new NullDumper(); } /** diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 48d2a8ce893b2..4657fd51a1c31 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -11,6 +11,8 @@ namespace Symfony\Component\HttpKernel; +use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; +use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; @@ -684,7 +686,14 @@ protected function prepareContainer(ContainerBuilder $container) */ protected function getContainerBuilder() { - return new ContainerBuilder(new ParameterBag($this->getKernelParameters())); + $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters())); + + if (class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) { + $container->setProxyInstantiator(new RuntimeInstantiator()); + $container->setProxyDumper(new ProxyDumper()); + } + + return $container; } /** From d34bdf40cd9da22dd027a1d564dc70c083225092 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 30 Apr 2013 21:54:58 +0200 Subject: [PATCH 26/39] Passing the proxy dumper to the PhpDumper via ContainerBuilder --- .../Component/DependencyInjection/Dumper/PhpDumper.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index dd6c82b993c10..49a8985263207 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -11,7 +11,6 @@ namespace Symfony\Component\DependencyInjection\Dumper; -use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; use Symfony\Component\DependencyInjection\Variable; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -51,6 +50,9 @@ class PhpDumper extends Dumper private $variableCount; private $reservedVariables = array('instance', 'class'); + /** + * @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface + */ private $proxyDumper; /** @@ -63,8 +65,7 @@ public function __construct(ContainerBuilder $container) parent::__construct($container); $this->inlinedDefinitions = new \SplObjectStorage; - $this->proxyDumper = new \Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; - //$this->proxyDumper = new NullDumper(); + $this->proxyDumper = $container->getProxyDumper(); } /** From 7bb0bddbb4b574c2b449805b3d4daa2a243ceaf9 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 30 Apr 2013 22:03:47 +0200 Subject: [PATCH 27/39] Adding tests for the runtime proxy instantiator --- .../Instantiator/RuntimeInstantiatorTest.php | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php new file mode 100644 index 0000000000000..3e8c00dd28b8e --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\ProxyManager\LazyProxy\Instantiator; + +use ProxyManager\Configuration; +use ProxyManager\Proxy\LazyLoadingInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Tests for {@see \Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator} + * + * @author Marco Pivetta + * + * @covers \Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator + */ +class RuntimeInstantiatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var RuntimeInstantiator + */ + protected $instantiator; + + /** + * {@inheritDoc} + */ + public function setUp() + { + $this->instantiator = new RuntimeInstantiator(); + } + + public function testInstantiateProxy() + { + $instance = new \stdClass(); + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $definition = new Definition('stdClass'); + $instantiator = function () use ($instance) { + return $instance; + }; + + /* @var $proxy \ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */ + $proxy = $this->instantiator->instantiateProxy($container, $definition, 'foo', $instantiator); + + $this->assertInstanceOf('ProxyManager\Proxy\LazyLoadingInterface', $proxy); + $this->assertInstanceOf('ProxyManager\Proxy\ValueHolderInterface', $proxy); + $this->assertFalse($proxy->isProxyInitialized()); + + $proxy->initializeProxy(); + + $this->assertSame($instance, $proxy->getWrappedValueHolderValue()); + } +} From 57c1d760c2c709097cfe792d009d254477faaf69 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 30 Apr 2013 22:37:42 +0200 Subject: [PATCH 28/39] Adding tests for the ProxyDumper --- .../Instantiator/RuntimeInstantiatorTest.php | 3 +- .../LazyProxy/PhpDumper/ProxyDumperTest.php | 106 ++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php index 3e8c00dd28b8e..1fb4c01c7660c 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php @@ -9,10 +9,11 @@ * file that was distributed with this source code. */ -namespace Symfony\Bridge\ProxyManager\LazyProxy\Instantiator; +namespace Symfony\Bridge\ProxyManager\LazyProxy\Tests\Instantiator; use ProxyManager\Configuration; use ProxyManager\Proxy\LazyLoadingInterface; +use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php new file mode 100644 index 0000000000000..1a61a0565c4f4 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\ProxyManager\LazyProxy\Tests\Instantiator; + +use ProxyManager\Configuration; +use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Tests for {@see \Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper} + * + * @author Marco Pivetta + * + * @covers \Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper + */ +class ProxyDumperTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ProxyDumper + */ + protected $dumper; + + /** + * {@inheritDoc} + */ + public function setUp() + { + $this->dumper = new ProxyDumper(); + } + + /** + * @dataProvider getProxyCandidates + * + * @param Definition $definition + * @param bool $expected + */ + public function testIsProxyCandidate(Definition $definition, $expected) + { + $this->assertSame($expected, $this->dumper->isProxyCandidate($definition)); + } + + public function testGetProxyCode() + { + $definition = new Definition(__CLASS__); + + $definition->setLazy(true); + + $code = $this->dumper->getProxyCode($definition); + + $this->assertStringMatchesFormat( + '%Aclass SymfonyBridgeProxyManagerLazyProxyTestsInstantiatorProxyDumperTest%aextends%w' + . '\Symfony\Bridge\ProxyManager\LazyProxy\Tests\Instantiator%a', + $code + ); + } + + public function testGetProxyFactoryCode() + { + $definition = new Definition(__CLASS__); + + $definition->setLazy(true); + + $code = $this->dumper->getProxyFactoryCode($definition, 'foo'); + + $this->assertStringMatchesFormat( + '%wif ($lazyLoad) {%w$container = $this;%wreturn $this->services[\'foo\'] = new ' + . 'SymfonyBridgeProxyManagerLazyProxyTestsInstantiatorProxyDumperTest_%s(%wfunction ' + . '(& $wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) {' + . '%w$proxy->setProxyInitializer(null);%w$wrappedInstance = $container->getFooService(false);' + . '%wreturn true;%w}%w);%w}%w', + $code + ); + } + + /** + * @return array + */ + public function getProxyCandidates() + { + $definitions = array( + array(new Definition(__CLASS__), true), + array(new Definition('stdClass'), true), + array(new Definition('foo' . uniqid()), false), + array(new Definition(), false), + ); + + array_map( + function ($definition) { + $definition[0]->setLazy(true); + }, + $definitions + ); + + return $definitions; + } +} From 57b270bc73c87b88d82e74c962b1e9bf3568f3d6 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 30 Apr 2013 23:08:31 +0200 Subject: [PATCH 29/39] Moving lazy service instantiation features/tests to ProxyManager bridge --- .../Tests/LazyProxy/ContainerBuilderTest.php | 56 +++++++++++++++ .../Tests/LazyProxy/Dumper/PhpDumperTest.php | 71 +++++++++++++++++++ .../Tests/LazyProxy/Fixtures/includes/foo.php | 36 ++++++++++ .../LazyProxy}/Fixtures/php/lazy_service.php | 0 .../Fixtures/php/lazy_service_structure.txt | 27 +++++++ .../DependencyInjection/ContainerBuilder.php | 8 +-- .../Tests/ContainerBuilderTest.php | 14 +--- .../Tests/Dumper/PhpDumperTest.php | 37 ---------- .../Fixtures/php/lazy_service_structure.txt | 67 ----------------- .../RealServiceInstantiatorTest.php | 37 ++++++++++ .../LazyProxy/PhpDumper/NullDumperTest.php | 35 +++++++++ 11 files changed, 266 insertions(+), 122 deletions(-) create mode 100644 src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php create mode 100644 src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php create mode 100644 src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php rename src/Symfony/{Component/DependencyInjection/Tests => Bridge/ProxyManager/Tests/LazyProxy}/Fixtures/php/lazy_service.php (100%) create mode 100644 src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt create mode 100644 src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php new file mode 100644 index 0000000000000..ebe8f2c666420 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\ProxyManager\LazyProxy\Tests; + +require_once __DIR__ . '/Fixtures/includes/foo.php'; + +use ProxyManager\Configuration; +use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Integration tests for {@see \Symfony\Component\DependencyInjection\ContainerBuilder} combined + * with the ProxyManager bridge + * + * @author Marco Pivetta + */ +class ContainerBuilderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService + */ + public function testCreateProxyServiceWithRuntimeInstantiator() + { + $builder = new ContainerBuilder(); + + $builder->setProxyInstantiator(new RuntimeInstantiator()); + + $builder->register('foo1', 'ProxyManagerBridgeFooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php'); + $builder->getDefinition('foo1')->setLazy(true); + + /* @var $foo1 \ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */ + $foo1 = $builder->get('foo1'); + + $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls'); + $this->assertInstanceOf('\ProxyManagerBridgeFooClass', $foo1); + $this->assertInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1); + $this->assertFalse($foo1->isProxyInitialized()); + + $foo1->initializeProxy(); + + $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved after initialization'); + $this->assertTrue($foo1->isProxyInitialized()); + $this->assertInstanceOf('\ProxyManagerBridgeFooClass', $foo1->getWrappedValueHolderValue()); + $this->assertNotInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1->getWrappedValueHolderValue()); + } +} diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php new file mode 100644 index 0000000000000..a334ac51b38c2 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\ProxyManager\LazyProxy\Tests\Dumper; + +use ProxyManager\Configuration; +use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Dumper\PhpDumper; + +/** + * Integration tests for {@see \Symfony\Component\DependencyInjection\Dumper\PhpDumper} combined + * with the ProxyManager bridge + * + * @author Marco Pivetta + */ +class PhpDumperTest extends \PHPUnit_Framework_TestCase +{ + public function testDumpContainerWithProxyService() + { + $container = new ContainerBuilder(); + + $container->setProxyDumper(new ProxyDumper()); + + $container->register('foo', 'stdClass'); + $container->getDefinition('foo')->setLazy(true); + $container->compile(); + + $dumper = new PhpDumper($container); + $dumpedString = $dumper->dump(); + + $this->assertStringMatchesFormatFile( + __DIR__ . '/../Fixtures/php/lazy_service_structure.txt', + $dumpedString, + '->dump() does generate proxy lazy loading logic.' + ); + } + + + /** + * Verifies that the generated container retrieves the same proxy instance on multiple subsequent requests + */ + public function testDumpContainerWithProxyServiceWillShareProxies() + { + require_once __DIR__ . '/../Fixtures/php/lazy_service.php'; + + $container = new \LazyServiceProjectServiceContainer(); + + /* @var $proxy \stdClass_c1d194250ee2e2b7d2eab8b8212368a8 */ + $proxy = $container->get('foo'); + + $this->assertInstanceOf('stdClass_c1d194250ee2e2b7d2eab8b8212368a8', $proxy); + $this->assertSame($proxy, $container->get('foo')); + + $this->assertFalse($proxy->isProxyInitialized()); + + $proxy->initializeProxy(); + + $this->assertTrue($proxy->isProxyInitialized()); + $this->assertSame($proxy, $container->get('foo')); + } +} diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php new file mode 100644 index 0000000000000..1013a8c572325 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php @@ -0,0 +1,36 @@ +arguments = $arguments; + } + + public static function getInstance($arguments = array()) + { + $obj = new self($arguments); + $obj->called = true; + + return $obj; + } + + public function initialize() + { + $this->initialized = true; + } + + public function configure() + { + $this->configured = true; + } + + public function setBar($value = null) + { + $this->bar = $value; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service.php similarity index 100% rename from src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service.php rename to src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service.php diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt new file mode 100644 index 0000000000000..1f855950528e3 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt @@ -0,0 +1,27 @@ +services['foo'] = new stdClass_%s( + function (& $wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) { + $proxy->setProxyInitializer(null); + + $wrappedInstance = $container->getFooService(false); + + return true; + } + ); + } + + return new \stdClass(); + } +} + +class stdClass_%s extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface +{%a}%A \ No newline at end of file diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index d2b6e595df103..8307d89009aed 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -11,8 +11,6 @@ namespace Symfony\Component\DependencyInjection; -use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; -use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; @@ -128,8 +126,7 @@ public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) public function getProxyInstantiator() { if (!$this->proxyInstantiator) { - //$this->proxyInstantiator = new RealServiceInstantiator(); - $this->proxyInstantiator = new RuntimeInstantiator(); + $this->proxyInstantiator = new RealServiceInstantiator(); } return $this->proxyInstantiator; @@ -155,8 +152,7 @@ public function setProxyDumper(DumperInterface $proxyDumper) public function getProxyDumper() { if (!$this->proxyDumper) { - //$this->proxyDumper = new NullDumper(); - $this->proxyDumper = new ProxyDumper(); + $this->proxyDumper = new NullDumper(); } return $this->proxyDumper; diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index b1b0a040f5776..a5e7531b68af0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -267,27 +267,17 @@ public function testCreateService() /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService */ - public function testCreateServiceWithDelegateFactory() + public function testCreateProxyWithRealServiceInstantiator() { $builder = new ContainerBuilder(); $builder->register('foo1', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php'); $builder->getDefinition('foo1')->setLazy(true); - /* @var $foo1 \ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */ $foo1 = $builder->get('foo1'); $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls'); - $this->assertInstanceOf('\FooClass', $foo1); - $this->assertInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1); - $this->assertFalse($foo1->isProxyInitialized()); - - $foo1->initializeProxy(); - - $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved after initialization'); - $this->assertTrue($foo1->isProxyInitialized()); - $this->assertInstanceOf('\FooClass', $foo1->getWrappedValueHolderValue()); - $this->assertNotInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1->getWrappedValueHolderValue()); + $this->assertSame('FooClass', get_class($foo1)); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 12f88ca6b19a6..72d587ff070fc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -52,43 +52,6 @@ public function testDumpFrozenContainerWithNoParameter() $this->assertNotRegexp("/function getDefaultParameters\(/", $dumpedString, '->dump() does not add getDefaultParameters() method definition.'); } - public function testDumpContainerWithProxyService() - { - $container = new ContainerBuilder(); - - $container->register('foo', 'stdClass'); - $container->getDefinition('foo')->setLazy(true); - $container->compile(); - - $dumper = new PhpDumper($container); - $dumpedString = $dumper->dump(); - - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/lazy_service_structure.txt', $dumpedString, '->dump() does generate proxy lazy loading logic.'); - } - - /** - * Verifies that the generated container retrieves the same proxy instance on multiple subsequent requests - */ - public function testDumpContainerWithProxyServiceWillShareProxies() - { - require_once self::$fixturesPath.'/php/lazy_service.php'; - - $container = new \LazyServiceProjectServiceContainer(); - - /* @var $proxy \stdClass_c1d194250ee2e2b7d2eab8b8212368a8 */ - $proxy = $container->get('foo'); - - $this->assertInstanceOf('stdClass_c1d194250ee2e2b7d2eab8b8212368a8', $proxy); - $this->assertSame($proxy, $container->get('foo')); - - $this->assertFalse($proxy->isProxyInitialized()); - - $proxy->initializeProxy(); - - $this->assertTrue($proxy->isProxyInitialized()); - $this->assertSame($proxy, $container->get('foo')); - } - public function testDumpOptimizationString() { $definition = new Definition(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt deleted file mode 100644 index 1eaf8cad606c3..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_service_structure.txt +++ /dev/null @@ -1,67 +0,0 @@ -services = - $this->scopedServices = - $this->scopeStacks = array(); - - $this->set('service_container', $this); - - $this->scopes = array(); - $this->scopeChildren = array(); - } - - /** - * Gets the 'foo' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @param boolean $lazyLoad whether to try lazy-loading the service with a proxy - * - * @return stdClass A stdClass instance. - */ - public function getFooService($lazyLoad = true) - { - if ($lazyLoad) { - $container = $this; - - return $this->services['foo'] = new stdClass_%s( - function (& $wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) { - $proxy->setProxyInitializer(null); - - $wrappedInstance = $container->getFooService(false); - - return true; - } - ); - } - - return new \stdClass(); - } -} - -class stdClass_%s extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface -{%a} \ No newline at end of file diff --git a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php new file mode 100644 index 0000000000000..023ecd1997de2 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\LazyProxy\Instantiator; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; + +/** + * Tests for {@see \Symfony\Component\DependencyInjection\Instantiator\RealServiceInstantiator} + * + * @author Marco Pivetta + * + * @covers \Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator + */ +class RealServiceInstantiatorTest extends \PHPUnit_Framework_TestCase +{ + public function testInstantiateProxy() + { + $instantiator = new RealServiceInstantiator(); + $instance = new \stdClass(); + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $callback = function () use ($instance) { + return $instance; + }; + + $this->assertSame($instance, $instantiator->instantiateProxy($container, new Definition(), 'foo', $callback)); + } +} \ No newline at end of file diff --git a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php new file mode 100644 index 0000000000000..d909ec916c2f8 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\LazyProxy\PhpDumper; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; + +/** + * Tests for {@see \Symfony\Component\DependencyInjection\PhpDumper\NullDumper} + * + * @author Marco Pivetta + * + * @covers \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper + */ +class NullDumperTest extends \PHPUnit_Framework_TestCase +{ + public function testNullDumper() + { + $dumper = new NullDumper(); + $definition = new Definition('stdClass'); + + $this->assertFalse($dumper->isProxyCandidate($definition)); + $this->assertSame('', $dumper->getProxyFactoryCode($definition, 'foo')); + $this->assertSame('', $dumper->getProxyCode($definition)); + } +} \ No newline at end of file From eaf358545cde7450e92c74af49a5fe4aa3f0750e Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 30 Apr 2013 23:24:08 +0200 Subject: [PATCH 30/39] Removing useless dependencies --- src/Symfony/Bridge/ProxyManager/composer.json | 3 +-- src/Symfony/Component/DependencyInjection/composer.json | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index e3fca38fc3f10..bf1b76768c857 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -18,8 +18,7 @@ "require": { "php": ">=5.3.3", "symfony/dependency-injection": ">=2.3-dev,<2.4-dev", - "ocramius/proxy-manager": "0.3.*", - "zendframework/zend-code": "2.*" + "ocramius/proxy-manager": "0.3.*" }, "autoload": { "psr-0": { diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 469811a075d48..34a7006782bd4 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -20,13 +20,12 @@ }, "require-dev": { "symfony/yaml": "~2.0", - "symfony/config": ">=2.2,<2.4-dev", - "ocramius/proxy-manager": ">=0.3.1,<0.4.x-dev" + "symfony/config": ">=2.2,<2.4-dev" }, "suggest": { "symfony/yaml": "2.2.*", "symfony/config": "2.2.*", - "ocramius/proxy-manager": "Generate service proxies to lazy load them" + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them" }, "autoload": { "psr-0": { "Symfony\\Component\\DependencyInjection\\": "" } From 64b452c90f174e86a2eb3bda05639c0383a8b1e3 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 30 Apr 2013 23:25:43 +0200 Subject: [PATCH 31/39] CS fixes (EOF EOL) --- .../LazyProxy/Instantiator/RealServiceInstantiatorTest.php | 2 +- .../Tests/LazyProxy/PhpDumper/NullDumperTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php index 023ecd1997de2..5fb202696492a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php @@ -34,4 +34,4 @@ public function testInstantiateProxy() $this->assertSame($instance, $instantiator->instantiateProxy($container, new Definition(), 'foo', $callback)); } -} \ No newline at end of file +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php index d909ec916c2f8..646673662a61c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php @@ -32,4 +32,4 @@ public function testNullDumper() $this->assertSame('', $dumper->getProxyFactoryCode($definition, 'foo')); $this->assertSame('', $dumper->getProxyCode($definition)); } -} \ No newline at end of file +} From 41237ee57d30c7ffcb9cc3364f52fb58a6f1aa12 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 1 May 2013 07:41:20 +0200 Subject: [PATCH 32/39] Removing zendframework/zend-code from dev dependencies --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 3fed8f0a03e0b..1e3fdae52142f 100644 --- a/composer.json +++ b/composer.json @@ -67,8 +67,7 @@ "monolog/monolog": "~1.3", "propel/propel1": "1.6.*", "ircmaxell/password-compat": "1.0.*", - "ocramius/proxy-manager": ">=0.3.1,<0.4-dev", - "zendframework/zend-code": "2.*" + "ocramius/proxy-manager": ">=0.3.1,<0.4-dev" }, "autoload": { "psr-0": { "Symfony\\": "src/" }, From dcfc38880c6f6e9f25d1dacb32f66aeebf232711 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 1 May 2013 07:42:17 +0200 Subject: [PATCH 33/39] Adding vendor dir to ignored coverage directories --- src/Symfony/Bridge/ProxyManager/phpunit.xml.dist | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist b/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist index 0e2acb60d2752..5e7c4337f91b5 100644 --- a/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist +++ b/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist @@ -24,6 +24,7 @@ ./Resources ./Tests + ./vendor From 0e52e9648b708b737ccfbf23814d3a86e72f4ed3 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 1 May 2013 07:47:17 +0200 Subject: [PATCH 34/39] Applying CS fixes as of @Stof's review --- .../LazyProxy/Instantiator/RuntimeInstantiator.php | 2 +- .../Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php | 5 +++-- src/Symfony/Bridge/ProxyManager/composer.json | 2 +- .../Component/DependencyInjection/Dumper/PhpDumper.php | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php index e8df0e032d9d7..7550b9a55ec56 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php @@ -29,7 +29,7 @@ class RuntimeInstantiator implements InstantiatorInterface /** * @var \ProxyManager\Factory\LazyLoadingValueHolderFactory */ - protected $factory; + private $factory; /** * Constructor diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index 80e3683dad590..23361e04a4af0 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -29,12 +29,12 @@ class ProxyDumper implements DumperInterface /** * @var \ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator */ - protected $proxyGenerator; + private $proxyGenerator; /** * @var \ProxyManager\GeneratorStrategy\BaseGeneratorStrategy */ - protected $classGenerator; + private $classGenerator; /** * Constructor @@ -44,6 +44,7 @@ public function __construct() $this->proxyGenerator = new LazyLoadingValueHolderGenerator(); $this->classGenerator = new BaseGeneratorStrategy(); } + /** * {@inheritDoc} */ diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index bf1b76768c857..1dd4afaf84200 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.3.3", "symfony/dependency-injection": ">=2.3-dev,<2.4-dev", - "ocramius/proxy-manager": "0.3.*" + "ocramius/proxy-manager": ">=0.3.1,<0.4-dev" }, "autoload": { "psr-0": { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 49a8985263207..4674420ed20ae 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -65,7 +65,7 @@ public function __construct(ContainerBuilder $container) parent::__construct($container); $this->inlinedDefinitions = new \SplObjectStorage; - $this->proxyDumper = $container->getProxyDumper(); + $this->proxyDumper = $container->getProxyDumper(); } /** From 48f0ac255e6c8641c72c33398e88896393809f92 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 May 2013 21:36:40 +0200 Subject: [PATCH 35/39] Moving proxy dumper instantiation from container builder to kernel --- .../Tests/LazyProxy/Dumper/PhpDumperTest.php | 7 ++-- .../DependencyInjection/ContainerBuilder.php | 31 -------------- .../DependencyInjection/Dumper/PhpDumper.php | 42 +++++++++++++++---- src/Symfony/Component/HttpKernel/Kernel.php | 6 ++- 4 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php index a334ac51b38c2..0b51235bf0191 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php @@ -29,13 +29,14 @@ public function testDumpContainerWithProxyService() { $container = new ContainerBuilder(); - $container->setProxyDumper(new ProxyDumper()); - $container->register('foo', 'stdClass'); $container->getDefinition('foo')->setLazy(true); $container->compile(); - $dumper = new PhpDumper($container); + $dumper = new PhpDumper($container); + + $dumper->setProxyDumper(new ProxyDumper()); + $dumpedString = $dumper->dump(); $this->assertStringMatchesFormatFile( diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 8307d89009aed..e5d8d08297488 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -80,11 +80,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface */ private $proxyInstantiator; - /** - * @var DumperInterface|null - */ - private $proxyDumper; - /** * Sets the track resources flag. * @@ -132,32 +127,6 @@ public function getProxyInstantiator() return $this->proxyInstantiator; } - /** - * Sets the dumper to be used when dumping proxies in the generated container - * - * @todo not responsibility of the ContainerBuilder? - * - * @param DumperInterface $proxyInstantiator - */ - public function setProxyDumper(DumperInterface $proxyDumper) - { - $this->proxyDumper = $proxyDumper; - } - - /** - * Retrieves the currently set proxy dumper used when dumping proxies in the generated container - * - * @return DumperInterface - */ - public function getProxyDumper() - { - if (!$this->proxyDumper) { - $this->proxyDumper = new NullDumper(); - } - - return $this->proxyDumper; - } - /** * Registers an extension. * diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 4674420ed20ae..1a01d7e27d9e3 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -21,6 +21,8 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper; +use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; /** * PhpDumper dumps a service container as a PHP class. @@ -65,7 +67,30 @@ public function __construct(ContainerBuilder $container) parent::__construct($container); $this->inlinedDefinitions = new \SplObjectStorage; - $this->proxyDumper = $container->getProxyDumper(); + } + + /** + * Sets the dumper to be used when dumping proxies in the generated container + * + * @param ProxyDumper $proxyDumper + */ + public function setProxyDumper(ProxyDumper $proxyDumper) + { + $this->proxyDumper = $proxyDumper; + } + + /** + * Retrieves the currently set proxy dumper used when dumping proxies in the generated container + * + * @return ProxyDumper + */ + public function getProxyDumper() + { + if (!$this->proxyDumper) { + $this->proxyDumper = new NullDumper(); + } + + return $this->proxyDumper; } /** @@ -164,11 +189,14 @@ private function addServiceLocalTempVariables($cId, $definition) private function addProxyClasses() { /* @var $proxyDefinitions Definition[] */ - $definitions = array_filter($this->container->getDefinitions(), array($this->proxyDumper, 'isProxyCandidate')); - $code = ''; + $definitions = array_filter( + $this->container->getDefinitions(), + array($this->getProxyDumper(), 'isProxyCandidate') + ); + $code = ''; foreach ($definitions as $definition) { - $code .= "\n" . $this->proxyDumper->getProxyCode($definition); + $code .= "\n" . $this->getProxyDumper()->getProxyCode($definition); } return $code; @@ -306,7 +334,7 @@ private function addServiceInstance($id, $definition) } $simple = $this->isSimpleInstance($id, $definition); - $isProxyCandidate = $this->proxyDumper->isProxyCandidate($definition); + $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); $instantiation = ''; if (!$isProxyCandidate && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { @@ -519,7 +547,7 @@ private function addService($id, $definition) } // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer - $isProxyCandidate = $this->proxyDumper->isProxyCandidate($definition); + $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); $visibility = $isProxyCandidate ? 'public' : 'protected'; $code = <<proxyDumper->getProxyFactoryCode($definition, $id) : ''; + $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id) : ''; if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) { $code .= <<setProxyInstantiator(new RuntimeInstantiator()); - $container->setProxyDumper(new ProxyDumper()); } return $container; @@ -708,6 +707,11 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container { // cache the container $dumper = new PhpDumper($container); + + if (class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) { + $dumper->setProxyDumper(new ProxyDumper()); + } + $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass)); if (!$this->debug) { $content = self::stripComments($content); From 194b9b5762a9af59e68f32178f3e0107605b2aa8 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 May 2013 21:39:11 +0200 Subject: [PATCH 36/39] Removing `@api` annotation --- src/Symfony/Component/DependencyInjection/ContainerBuilder.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index e5d8d08297488..d4a9519e79e29 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -269,8 +269,6 @@ public function addObjectResource($object) * @param \ReflectionClass $class * * @return ContainerBuilder The current instance - * - * @api */ public function addClassResource(\ReflectionClass $class) { From 73f79cc3998a62e0d952d260471bb14e1c6c376f Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 May 2013 21:48:13 +0200 Subject: [PATCH 37/39] Removing @api annotations, moving getters to private visibility --- .../DependencyInjection/ContainerBuilder.php | 30 +++++++++---------- .../DependencyInjection/Dumper/PhpDumper.php | 28 ++++++++--------- .../Instantiator/InstantiatorInterface.php | 4 --- .../LazyProxy/PhpDumper/DumperInterface.php | 8 ----- 4 files changed, 28 insertions(+), 42 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index d4a9519e79e29..d06a7c30fca57 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -24,8 +24,6 @@ use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; -use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface; -use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; /** * ContainerBuilder is a DI container that provides an API to easily describe services. @@ -113,20 +111,6 @@ public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) $this->proxyInstantiator = $proxyInstantiator; } - /** - * Retrieves the currently set proxy instantiator - * - * @return InstantiatorInterface - */ - public function getProxyInstantiator() - { - if (!$this->proxyInstantiator) { - $this->proxyInstantiator = new RealServiceInstantiator(); - } - - return $this->proxyInstantiator; - } - /** * Registers an extension. * @@ -1088,6 +1072,20 @@ public static function getServiceConditionals($value) return $services; } + /** + * Retrieves the currently set proxy instantiator or instantiates one + * + * @return InstantiatorInterface + */ + private function getProxyInstantiator() + { + if (!$this->proxyInstantiator) { + $this->proxyInstantiator = new RealServiceInstantiator(); + } + + return $this->proxyInstantiator; + } + /** * Synchronizes a service change. * diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 1a01d7e27d9e3..4501bb1ff5fdf 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -79,20 +79,6 @@ public function setProxyDumper(ProxyDumper $proxyDumper) $this->proxyDumper = $proxyDumper; } - /** - * Retrieves the currently set proxy dumper used when dumping proxies in the generated container - * - * @return ProxyDumper - */ - public function getProxyDumper() - { - if (!$this->proxyDumper) { - $this->proxyDumper = new NullDumper(); - } - - return $this->proxyDumper; - } - /** * Dumps the service container as a PHP class. * @@ -132,6 +118,20 @@ public function dump(array $options = array()) return $code; } + /** + * Retrieves the currently set proxy dumper or instantiates one + * + * @return ProxyDumper + */ + private function getProxyDumper() + { + if (!$this->proxyDumper) { + $this->proxyDumper = new NullDumper(); + } + + return $this->proxyDumper; + } + /** * Generates Service local temp variables. * diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php index bfafd0271ce2b..38b34adedb03d 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php @@ -19,8 +19,6 @@ * service definitions and a callback that produces the real service instance * * @author Marco Pivetta - * - * @api */ interface InstantiatorInterface { @@ -32,8 +30,6 @@ interface InstantiatorInterface * service instance * * @return object - * - * @api */ public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator); } diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php index e41ed25899c67..5e5ea9de10f7f 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php @@ -18,8 +18,6 @@ * Lazy proxy dumper capable of generating the instantiation logic php code for proxied services * * @author Marco Pivetta - * - * @api */ interface DumperInterface { @@ -29,8 +27,6 @@ interface DumperInterface * @param Definition $definition * * @return bool - * - * @api */ public function isProxyCandidate(Definition $definition); @@ -41,8 +37,6 @@ public function isProxyCandidate(Definition $definition); * @param string $id service identifier * * @return string - * - * @api */ public function getProxyFactoryCode(Definition $definition, $id); @@ -52,8 +46,6 @@ public function getProxyFactoryCode(Definition $definition, $id); * @param Definition $definition * * @return string - * - * @api */ public function getProxyCode(Definition $definition); } From d582131878b92a8450f0660117859dd7b8e3e6e8 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 May 2013 21:58:46 +0200 Subject: [PATCH 38/39] Removing last `@api` occurrences in Definition --- src/Symfony/Component/DependencyInjection/Definition.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 803dc1640d785..1168444389ef1 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -607,8 +607,6 @@ public function isSynchronized() * @param Boolean $lazy * * @return Definition The current instance - * - * @api */ public function setLazy($lazy) { @@ -621,8 +619,6 @@ public function setLazy($lazy) * Whether this service is lazy. * * @return Boolean - * - * @api */ public function isLazy() { From f4d3e8a677dbe61e0ba2f5daa4a2de7a84fb54ea Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 May 2013 22:13:33 +0200 Subject: [PATCH 39/39] EOL dots in docblock sentences --- .../Component/DependencyInjection/ContainerBuilder.php | 4 ++-- .../Component/DependencyInjection/Dumper/PhpDumper.php | 4 ++-- .../LazyProxy/Instantiator/InstantiatorInterface.php | 2 +- .../LazyProxy/Instantiator/RealServiceInstantiator.php | 2 +- .../LazyProxy/PhpDumper/DumperInterface.php | 8 ++++---- .../LazyProxy/PhpDumper/NullDumper.php | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index d06a7c30fca57..6f842270fc9ed 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -102,7 +102,7 @@ public function isTrackingResources() } /** - * Sets the instantiator to be used when fetching proxies + * Sets the instantiator to be used when fetching proxies. * * @param InstantiatorInterface $proxyInstantiator */ @@ -1073,7 +1073,7 @@ public static function getServiceConditionals($value) } /** - * Retrieves the currently set proxy instantiator or instantiates one + * Retrieves the currently set proxy instantiator or instantiates one. * * @return InstantiatorInterface */ diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 4501bb1ff5fdf..9d6878050fe9e 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -70,7 +70,7 @@ public function __construct(ContainerBuilder $container) } /** - * Sets the dumper to be used when dumping proxies in the generated container + * Sets the dumper to be used when dumping proxies in the generated container. * * @param ProxyDumper $proxyDumper */ @@ -119,7 +119,7 @@ public function dump(array $options = array()) } /** - * Retrieves the currently set proxy dumper or instantiates one + * Retrieves the currently set proxy dumper or instantiates one. * * @return ProxyDumper */ diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php index 38b34adedb03d..4e4a00a547e2b 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php @@ -16,7 +16,7 @@ /** * Lazy proxy instantiator, capable of instantiating a proxy given a container, the - * service definitions and a callback that produces the real service instance + * service definitions and a callback that produces the real service instance. * * @author Marco Pivetta */ diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php index a39bb430b1f4e..6495df2813db1 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php @@ -17,7 +17,7 @@ /** * {@inheritDoc} * - * Noop proxy instantiator - simply produces the real service instead of a proxy instance + * Noop proxy instantiator - simply produces the real service instead of a proxy instance. * * @author Marco Pivetta */ diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php index 5e5ea9de10f7f..d8d5dac47095c 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php @@ -15,14 +15,14 @@ use Symfony\Component\DependencyInjection\Definition; /** - * Lazy proxy dumper capable of generating the instantiation logic php code for proxied services + * Lazy proxy dumper capable of generating the instantiation logic php code for proxied services. * * @author Marco Pivetta */ interface DumperInterface { /** - * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container + * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container. * * @param Definition $definition * @@ -31,7 +31,7 @@ interface DumperInterface public function isProxyCandidate(Definition $definition); /** - * Generates the code to be used to instantiate a proxy in the dumped factory code + * Generates the code to be used to instantiate a proxy in the dumped factory code. * * @param Definition $definition * @param string $id service identifier @@ -41,7 +41,7 @@ public function isProxyCandidate(Definition $definition); public function getProxyFactoryCode(Definition $definition, $id); /** - * Generates the code for the lazy proxy + * Generates the code for the lazy proxy. * * @param Definition $definition * diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php index b2ff41d69fd62..e1d4ff4dea900 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php @@ -15,7 +15,7 @@ use Symfony\Component\DependencyInjection\Definition; /** - * Null dumper, negates any proxy code generation for any given service definition + * Null dumper, negates any proxy code generation for any given service definition. * * @author Marco Pivetta */ 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