From 37ad0636dd1ec1e517f2b8d1c6cd1d5a58576bd2 Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Mon, 9 May 2011 07:33:31 +0200 Subject: [PATCH 1/8] [DependencyInjection] adds #835 (method injection) --- .../DependencyInjection/Definition.php | 22 +++++++++++++++++++ .../DependencyInjection/Dumper/XmlDumper.php | 4 ++++ .../DependencyInjection/Dumper/YamlDumper.php | 4 ++++ .../Loader/XmlFileLoader.php | 2 +- .../Loader/YamlFileLoader.php | 4 ++++ .../schema/dic/services/services-1.0.xsd | 1 + .../DependencyInjection/DefinitionTest.php | 18 +++++++++++++++ 7 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 5962480b529d..2ed5112986bf 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -15,6 +15,7 @@ * Definition represents a service definition. * * @author Fabien Potencier + * @author Johannes M. Schmitt */ class Definition { @@ -31,6 +32,7 @@ class Definition private $public; private $synthetic; private $abstract; + private $lookupMethods; protected $arguments; @@ -51,6 +53,7 @@ public function __construct($class = null, array $arguments = array()) $this->synthetic = false; $this->abstract = false; $this->properties = array(); + $this->lookupMethods = array(); } /** @@ -546,4 +549,23 @@ public function getConfigurator() { return $this->configurator; } + + public function setLookupMethod($name, $value) + { + $this->lookupMethods[$name] = $value; + + return $this; + } + + public function getLookupMethods() + { + return $this->lookupMethods; + } + + public function setLookupMethods(array $methods) + { + $this->lookupMethods = $methods; + + return $this; + } } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index 00a2acf2b9e0..90248ef76e0a 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -150,6 +150,10 @@ private function addService($definition, $id, \DOMElement $parent) $this->convertParameters($parameters, 'property', $service, 'name'); } + if ($parameters = $definition->getLookupMethods()) { + $this->convertParameters($parameters, 'lookup_method', $service, 'name'); + } + $this->addMethodCalls($definition->getMethodCalls(), $service); if ($callable = $definition->getConfigurator()) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index 0bdf1dd4e9ee..888e4a56a934 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -85,6 +85,10 @@ private function addService($id, $definition) $code .= sprintf(" properties: %s\n", Yaml::dump($this->dumpValue($definition->getProperties()), 0)); } + if ($definition->getLookupMethods()) { + $code .= sprintf(" lookup_methods: %s\n", Yaml::dump($this->dumpValue($definition->getLookupMethods()), 0)); + } + if ($definition->getMethodCalls()) { $code .= sprintf(" calls:\n %s\n", str_replace("\n", "\n ", Yaml::dump($this->dumpValue($definition->getMethodCalls()), 1))); } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 45c639045214..ccf2d3539220 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -12,7 +12,6 @@ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\DefinitionDecorator; - use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Definition; @@ -164,6 +163,7 @@ private function parseDefinition($id, $service, $file) $definition->setArguments($service->getArgumentsAsPhp('argument')); $definition->setProperties($service->getArgumentsAsPhp('property')); + $definition->setLookupMethods($service->getArgumentsAsPhp('lookup-method')); if (isset($service->configurator)) { if (isset($service->configurator['function'])) { diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 7885421a5dd9..798e594b974f 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -186,6 +186,10 @@ private function parseDefinition($id, $service, $file) $definition->setProperties($this->resolveServices($service['properties'])); } + if (isset($service['lookup_methods'])) { + $definition->setLookupMethods($this->resolveServices($service['lookup_methods'])); + } + if (isset($service['configurator'])) { if (is_string($service['configurator'])) { $definition->setConfigurator($service['configurator']); 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 7d46e8caa6e8..b7862e51ada5 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 @@ -80,6 +80,7 @@ + diff --git a/tests/Symfony/Tests/Component/DependencyInjection/DefinitionTest.php b/tests/Symfony/Tests/Component/DependencyInjection/DefinitionTest.php index 9ff87e09b731..26fdc2da3362 100644 --- a/tests/Symfony/Tests/Component/DependencyInjection/DefinitionTest.php +++ b/tests/Symfony/Tests/Component/DependencyInjection/DefinitionTest.php @@ -238,4 +238,22 @@ public function testSetProperty() $this->assertSame($def, $def->setProperty('foo', 'bar')); $this->assertEquals(array('foo' => 'bar'), $def->getProperties()); } + + public function testSetLookupMethod() + { + $def = new Definition('stdClass'); + + $this->assertEquals(array(), $def->getLookupMethods()); + $this->assertSame($def, $def->setLookupMethod('foo', 'bar')); + $this->assertEquals(array('foo' => 'bar'), $def->getLookupMethods()); + } + + public function testSetLookupMethods() + { + $def = new Definition('stdClass'); + + $this->assertEquals(array(), $def->getLookupMethods()); + $this->assertSame($def, $def->setLookupMethods(array('foo' => 'bar'))); + $this->assertEquals(array('foo' => 'bar'), $def->getLookupMethods()); + } } From 1628ab950db9a1c04f510b0dec3b54b2ffd6019d Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Mon, 9 May 2011 19:04:12 +0200 Subject: [PATCH 2/8] [DependencyInjection] added merging logic --- .../Compiler/ResolveDefinitionTemplatesPass.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php index 9473b788c023..78953d9c4901 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php @@ -68,6 +68,7 @@ private function resolveDefinition($id, DefinitionDecorator $definition) $def->setArguments($parentDef->getArguments()); $def->setMethodCalls($parentDef->getMethodCalls()); $def->setProperties($parentDef->getProperties()); + $def->setLookupMethods($parentDef->getLookupMethods()); $def->setFactoryClass($parentDef->getFactoryClass()); $def->setFactoryMethod($parentDef->getFactoryMethod()); $def->setFactoryService($parentDef->getFactoryService()); @@ -119,6 +120,11 @@ private function resolveDefinition($id, DefinitionDecorator $definition) $def->setProperty($k, $v); } + // merge lookup methods + foreach ($definition->getLookupMethods() as $k => $v) { + $def->setLookupMethod($k, $v); + } + // append method calls if (count($calls = $definition->getMethodCalls()) > 0) { $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); From 10107caf648751822e9b7297e9ec5245ad2b3377 Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Mon, 9 May 2011 22:32:36 +0200 Subject: [PATCH 3/8] [DependencyInjection] added generation pass --- .../GenerateLookupMethodClassesPass.php | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php new file mode 100644 index 000000000000..cc8cdff19081 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php @@ -0,0 +1,125 @@ +generatedClasses = array(); + $this->cleanUpCacheDir($cacheDir = $container->getParameter('kernel.cache_dir').'/lookup_method_classes'); + + foreach ($container->getDefinitions() as $id => $definition) { + if ($definition->isSynthetic() || $definition->isAbstract()) { + continue; + } + if (!$methods = $definition->getLookupMethods()) { + continue; + } + + $this->generateClass($definition, $cacheDir); + } + } + + private function cleanUpCacheDir($dir) + { + if (!is_dir($dir)) { + if (false === @mkdir($dir, 0777, true)) { + throw new \RuntimeException(sprintf('The cache directory "%s" could not be created.', $dir)); + } + + return; + } + + if (!is_writable($dir)) { + throw new \RuntimeException(sprintf('The cache directory "%s" is not writable.', $dir)); + } + + foreach (new \DirectoryIterator($dir) as $file) { + if ('.' === $file->getFileName() || !is_file($file->getPathName())) { + continue; + } + + if (false === @unlink($file->getPathName())) { + throw new \RuntimeException(sprintf('Could not delete auto-generated file "%s".', $file->getPathName())); + } + } + } + + private function generateClass(Definition $definition, $cacheDir) + { + $code = <<<'EOF' +getFile()) { + $require = sprintf("\nrequire_once %s;\n", var_export($file, true)); + } else { + $require = ''; + } + + // get class name + $class = new \ReflectionClass($definition->getClass()); + $i = 1; + do { + $className = $class->getShortName(); + + if ($i > 1) { + $className .= '_'.$i; + } + + $i += 1; + } while (isset($this->generatedClasses[$className])); + $this->generatedClasses[$className] = true; + + $lookupMethod = <<<'EOF' + + %s function %s() + { + return %s; + } +EOF; + $lookupMethods = ''; + foreach ($definition->getLookupMethods() as $name => $value) { + if (!$class->hasMethod($name)) { + throw new \RuntimeException(sprintf('The class "%s" has no method named "%s".', $class->getName(), $name)); + } + $method = $class->getMethod($name); + if ($method->isFinal()) { + throw new \RuntimeException(sprintf('The method "%s::%s" is marked as final and cannot be declared as lookup-method.', $class->getName(), $name)); + } + if ($method->isPrivate()) { + throw new \RuntimeException(sprintf('The method "%s::%s" is marked as private and cannot be declared as lookup-method.', $class->getName(), $name)); + } + if ($method->getParameters()) { + throw new \RuntimeException(sprintf('The method "%s::%s" must have a no-arguments signature if you want to use it as lookup-method.', $class->getName(), $name)); + } + + $lookupMethods .= sprintf($lookupMethod, + $method->isPublic() ? 'public' : 'protected', + $name, + 'foo' // FIXME: refactor PhpDumper::dumpValue code + ); + } + + $code = sprintf($code, $require, $className, $class->getName(), $lookupMethods); + file_put_contents($cacheDir.'/'.$className.'.php', $code); + $definition->setFile($cacheDir.'/'.$className.'.php'); + $definition->setProperty('__symfonyDependencyInjectionContainer', new Reference('service_container')); + } +} \ No newline at end of file From 2b7ab78788e7e72309978efd61a937668945bbd9 Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Tue, 10 May 2011 14:51:12 +0200 Subject: [PATCH 4/8] [DependencyInjection] added doc comment --- .../GenerateLookupMethodClassesPass.php | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php index cc8cdff19081..5221b45debc8 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php @@ -2,9 +2,9 @@ namespace Symfony\Component\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; class GenerateLookupMethodClassesPass implements CompilerPassInterface { @@ -23,7 +23,7 @@ public function process(ContainerBuilder $container) continue; } - $this->generateClass($definition, $cacheDir); + $this->generateClass($id, $definition, $cacheDir); } } @@ -52,13 +52,22 @@ private function cleanUpCacheDir($dir) } } - private function generateClass(Definition $definition, $cacheDir) + private function generateClass($id, Definition $definition, $cacheDir) { $code = <<<'EOF' getName(), $lookupMethods); + $code = sprintf($code, $require, $id, $className, $class->getName(), $lookupMethods); file_put_contents($cacheDir.'/'.$className.'.php', $code); + require_once $cacheDir.'/'.$className.'.php'; + $definition->setClass('Symfony\Component\DependencyInjection\LookupMethodClasses\\'.$className); $definition->setFile($cacheDir.'/'.$className.'.php'); $definition->setProperty('__symfonyDependencyInjectionContainer', new Reference('service_container')); } From bdcf802b6388d3601aac951bb897778009103fa5 Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Tue, 10 May 2011 16:02:28 +0200 Subject: [PATCH 5/8] [DependencyInjection] added dumpValue --- .../GenerateLookupMethodClassesPass.php | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php index 5221b45debc8..35766b7b7744 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php @@ -2,6 +2,8 @@ namespace Symfony\Component\DependencyInjection\Compiler; +use Symfony\Component\DependencyInjection\Parameter; + use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; @@ -9,9 +11,12 @@ class GenerateLookupMethodClassesPass implements CompilerPassInterface { private $generatedClasses = array(); + private $container; + private $currentId; public function process(ContainerBuilder $container) { + $this->container = $container; $this->generatedClasses = array(); $this->cleanUpCacheDir($cacheDir = $container->getParameter('kernel.cache_dir').'/lookup_method_classes'); @@ -23,7 +28,8 @@ public function process(ContainerBuilder $container) continue; } - $this->generateClass($id, $definition, $cacheDir); + $this->currentId = $id; + $this->generateClass($definition, $cacheDir); } } @@ -52,7 +58,7 @@ private function cleanUpCacheDir($dir) } } - private function generateClass($id, Definition $definition, $cacheDir) + private function generateClass(Definition $definition, $cacheDir) { $code = <<<'EOF' isPublic() ? 'public' : 'protected', $name, - 'foo' // FIXME: refactor PhpDumper::dumpValue code + $this->dumpValue($value) ); } - $code = sprintf($code, $require, $id, $className, $class->getName(), $lookupMethods); + $code = sprintf($code, $require, $this->currentId, $className, $class->getName(), $lookupMethods); file_put_contents($cacheDir.'/'.$className.'.php', $code); require_once $cacheDir.'/'.$className.'.php'; $definition->setClass('Symfony\Component\DependencyInjection\LookupMethodClasses\\'.$className); $definition->setFile($cacheDir.'/'.$className.'.php'); $definition->setProperty('__symfonyDependencyInjectionContainer', new Reference('service_container')); + $definition->setLookupMethods(array()); + } + + private function dumpValue($value) + { + if ($value instanceof Parameter) { + return var_export($this->container->getParameter((string) $value), true); + } else if ($value instanceof Reference) { + $id = (string) $value; + if ($this->container->hasAlias($id)) { + $this->container->setAlias($id, (string) $this->container->getAlias()); + } else if ($this->container->hasDefinition($id)) { + $this->container->getDefinition($id)->setPublic(true); + } + + return '$this->__symfonyDependencyInjectionContainer->get('.var_export($id, true).', '.var_export($value->getInvalidBehavior(), true).');'; + } else if (is_array($value) || is_scalar($value) || null === $value) { + return var_export($value, true); + } + + throw new \RuntimeException(sprintf('Invalid value for lookup method of service "%s": %s', $this->currentId, json_encode($value))); } } \ No newline at end of file From a8679cc6b23ec1791a6e7153b27aca45dfbb3f47 Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Tue, 10 May 2011 23:37:34 +0200 Subject: [PATCH 6/8] [DependencyInjection] added some doc comments --- .../Compiler/GenerateLookupMethodClassesPass.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php index 35766b7b7744..e27ef0dba2c0 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php @@ -2,12 +2,16 @@ namespace Symfony\Component\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\Parameter; - use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; +/** + * Generates the classes which implement the requested lookup methods. + * + * @author Johannes M. Schmitt + */ class GenerateLookupMethodClassesPass implements CompilerPassInterface { private $generatedClasses = array(); From 648c778f54350c66c0d6dd7485862fdb2b51e627 Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Wed, 11 May 2011 00:19:34 +0200 Subject: [PATCH 7/8] [DependencyInjection] updated PassConfig --- .../Compiler/AnalyzeServiceReferencesPass.php | 1 + .../GenerateLookupMethodClassesPass.php | 4 +- .../Compiler/PassConfig.php | 1 + .../Compiler/ResolveInvalidReferencesPass.php | 3 + .../ResolveReferencesToAliasesPass.php | 1 + .../GenerateLookupMethodClassesPassTest.php | 69 +++++++++++++++++++ 6 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 tests/Symfony/Tests/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPassTest.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php index 2399f6ca1218..fed33ff11f01 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php @@ -73,6 +73,7 @@ public function process(ContainerBuilder $container) if (!$this->onlyConstructorArguments) { $this->processArguments($definition->getMethodCalls()); $this->processArguments($definition->getProperties()); + $this->processArguments($definition->getLookupMethods()); } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php index e27ef0dba2c0..9a79a2533351 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php @@ -78,7 +78,7 @@ private function generateClass(Definition $definition, $cacheDir) * You can modify this class by changing your "lookup_method" configuration * for service "%s". */ -class %s extends %s +class %s extends \%s { private $__symfonyDependencyInjectionContainer; %s @@ -157,7 +157,7 @@ private function dumpValue($value) $this->container->getDefinition($id)->setPublic(true); } - return '$this->__symfonyDependencyInjectionContainer->get('.var_export($id, true).', '.var_export($value->getInvalidBehavior(), true).');'; + return '$this->__symfonyDependencyInjectionContainer->get('.var_export($id, true).', '.var_export($value->getInvalidBehavior(), true).')'; } else if (is_array($value) || is_scalar($value) || null === $value) { return var_export($value, true); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index faf7f804da81..26a6a25c36f2 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -56,6 +56,7 @@ public function __construct() ); $this->removingPasses = array( + new GenerateLookupMethodClassesPass(), new RemovePrivateAliasesPass(), new RemoveAbstractDefinitionsPass(), new ReplaceAliasByActualDefinitionPass(), diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php index 1ed10058c989..fe813eba0e41 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php @@ -41,6 +41,9 @@ public function process(ContainerBuilder $container) $definition->setArguments( $this->processArguments($definition->getArguments()) ); + $definition->setLookupMethods( + $this->processArguments($definition->getLookupMethods()) + ); $calls = array(); foreach ($definition->getMethodCalls() as $call) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php index f00bb75595ef..2e7c4587f522 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php @@ -41,6 +41,7 @@ public function process(ContainerBuilder $container) $definition->setArguments($this->processArguments($definition->getArguments())); $definition->setMethodCalls($this->processArguments($definition->getMethodCalls())); $definition->setProperties($this->processArguments($definition->getProperties())); + $definition->setLookupMethods($this->processArguments($definition->getLookupMethods())); } foreach ($container->getAliases() as $id => $alias) { diff --git a/tests/Symfony/Tests/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPassTest.php b/tests/Symfony/Tests/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPassTest.php new file mode 100644 index 000000000000..8780eea43503 --- /dev/null +++ b/tests/Symfony/Tests/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPassTest.php @@ -0,0 +1,69 @@ +dir = sys_get_temp_dir().'/lookup_method_classes'; + + if (!is_dir($this->dir) && false === @mkdir($this->dir, 0777, true)) { + $this->markTestIncomplete('Cache dir could not be created.'); + } + + $this->container = new ContainerBuilder(); + $this->container->setParameter('kernel.cache_dir', sys_get_temp_dir()); + } + + protected function tearDown() + { + foreach (new \DirectoryIterator($this->dir) as $file) { + if ('.' === $file->getFileName()) { + continue; + } + + @unlink($file->getPathName()); + } + + @rmdir($this->dir); + } + + public function testProcess() + { + $defFoobar = $this->container + ->register('foobar', 'Symfony\Tests\Component\DependencyInjection\Compiler\FooBarService') + ->setPublic(false) + ; + $def = $this->container + ->register('test', 'Symfony\Tests\Component\DependencyInjection\Compiler\LookupMethodTestClass') + ->setLookupMethod('getFooBar', new Reference('foobar')) + ; + + $this->process(); + + $service = $this->container->get('test'); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\LookupMethodClasses\LookupMethodTestClass', $service); + $this->assertInstanceOf('Symfony\Tests\Component\DependencyInjection\Compiler\FooBarService', $service->getFooBar()); + $this->assertEquals($this->dir.'/LookupMethodTestClass.php', $def->getFile()); + $this->assertEquals('Symfony\Component\DependencyInjection\LookupMethodClasses\LookupMethodTestClass', $def->getClass()); + $this->assertTrue($defFoobar->isPublic()); + } + + private function process() + { + $pass = new GenerateLookupMethodClassesPass(); + $pass->process($this->container); + } +} + +class FooBarService {} + +abstract class LookupMethodTestClass +{ + abstract public function getFooBar(); +} From 15f35f1ad3540638ba1fc710dcdb8e65f2c84572 Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Wed, 11 May 2011 00:44:27 +0200 Subject: [PATCH 8/8] [HttpKernel][DependencyInjection] fixed integration --- .../Compiler/GenerateLookupMethodClassesPass.php | 10 ++++++++-- .../DependencyInjection/Compiler/PassConfig.php | 1 - .../Component/DependencyInjection/Dumper/PhpDumper.php | 4 ++++ src/Symfony/Component/HttpKernel/Kernel.php | 10 +++++++++- .../Compiler/GenerateLookupMethodClassesPassTest.php | 3 +-- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php index 9a79a2533351..627b3b94f4a1 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPass.php @@ -17,12 +17,18 @@ class GenerateLookupMethodClassesPass implements CompilerPassInterface private $generatedClasses = array(); private $container; private $currentId; + private $cacheDir; + + public function __construct($cacheDir) + { + $this->cacheDir = $cacheDir; + } public function process(ContainerBuilder $container) { $this->container = $container; $this->generatedClasses = array(); - $this->cleanUpCacheDir($cacheDir = $container->getParameter('kernel.cache_dir').'/lookup_method_classes'); + $this->cleanUpCacheDir($this->cacheDir); foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { @@ -33,7 +39,7 @@ public function process(ContainerBuilder $container) } $this->currentId = $id; - $this->generateClass($definition, $cacheDir); + $this->generateClass($definition, $this->cacheDir); } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 26a6a25c36f2..faf7f804da81 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -56,7 +56,6 @@ public function __construct() ); $this->removingPasses = array( - new GenerateLookupMethodClassesPass(), new RemovePrivateAliasesPass(), new RemoveAbstractDefinitionsPass(), new ReplaceAliasByActualDefinitionPass(), diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 69d4195eff33..302b4a926ee0 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -459,6 +459,10 @@ private function addService($id, $definition) $this->referenceVariables = array(); $this->variableCount = 0; + if ($definition->getLookupMethods()) { + throw new \RuntimeException(sprintf('You have set lookup methods for service "%s", but the GenerateLookupMethodClassesPass was not enabled.', $id)); + } + $return = ''; if ($definition->isSynthetic()) { $return = sprintf('@throws \RuntimeException always since this service is expected to be injected dynamically'); diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 797a09df050a..2e92edfe7882 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -27,6 +27,7 @@ use Symfony\Component\HttpKernel\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass; +use Symfony\Component\DependencyInjection\Compiler\GenerateLookupMethodClassesPass; use Symfony\Component\HttpKernel\DependencyInjection\Extension as DIExtension; use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\Config\Loader\DelegatingLoader; @@ -577,8 +578,15 @@ protected function buildContainer() } $container->addObjectResource($this); + $passConfig = $container->getCompilerPassConfig(); + // ensure these extensions are implicitly loaded - $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); + $passConfig->setMergePass(new MergeExtensionConfigurationPass($extensions)); + + // enable method injection + $passes = $passConfig->getRemovingPasses(); + array_unshift($passes, new GenerateLookupMethodClassesPass($this->getCacheDir().'/lookup_method_classes')); + $passConfig->setRemovingPasses($passes); if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) { $container->merge($cont); diff --git a/tests/Symfony/Tests/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPassTest.php b/tests/Symfony/Tests/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPassTest.php index 8780eea43503..f027aa17e291 100644 --- a/tests/Symfony/Tests/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPassTest.php +++ b/tests/Symfony/Tests/Component/DependencyInjection/Compiler/GenerateLookupMethodClassesPassTest.php @@ -17,7 +17,6 @@ protected function setUp() } $this->container = new ContainerBuilder(); - $this->container->setParameter('kernel.cache_dir', sys_get_temp_dir()); } protected function tearDown() @@ -56,7 +55,7 @@ public function testProcess() private function process() { - $pass = new GenerateLookupMethodClassesPass(); + $pass = new GenerateLookupMethodClassesPass($this->dir); $pass->process($this->container); } }