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 */