From 2429d964d69a05f30fcc6381611dd51cc03e3d86 Mon Sep 17 00:00:00 2001 From: Chuck Hagenbuch Date: Tue, 27 Apr 2010 23:52:56 -0400 Subject: [PATCH] Next take on setter injection - an alternate implementation binder, which is also the default "magic" implementation binder. --- framework/Injector/lib/Horde/Injector.php | 30 ------------- .../lib/Horde/Injector/Binder/Implementation.php | 44 ++++++++++++++++--- .../Injector/Binder/ImplementationWithSetters.php | 50 ++++++++++++++++++++++ framework/Injector/lib/Horde/Injector/TopLevel.php | 4 +- framework/Injector/package.xml | 2 + 5 files changed, 91 insertions(+), 39 deletions(-) create mode 100644 framework/Injector/lib/Horde/Injector/Binder/ImplementationWithSetters.php diff --git a/framework/Injector/lib/Horde/Injector.php b/framework/Injector/lib/Horde/Injector.php index e2d377140..eefb3ef84 100644 --- a/framework/Injector/lib/Horde/Injector.php +++ b/framework/Injector/lib/Horde/Injector.php @@ -234,34 +234,4 @@ class Horde_Injector implements Horde_Injector_Scope return $this->_instances[$interface]; } - - /** - */ - public function getMethodDependencies(ReflectionMethod $method) - { - $dependencies = array(); - - try { - foreach ($method->getParameters() as $parameter) { - $dependencies[] = $this->_getParameterDependency($parameter); - } - } catch (Exception $e) { - throw new Horde_Injector_Exception("$method has unfulfilled dependencies ($parameter)", 0, $e); - } - - return $dependencies; - } - - /** - */ - private function _getParameterDependency(ReflectionParameter $parameter) - { - if ($parameter->getClass()) { - return $this->getInstance($parameter->getClass()->getName()); - } elseif ($parameter->isOptional()) { - return $parameter->getDefaultValue(); - } - - throw new Horde_Injector_Exception("Untyped parameter \$" . $parameter->getName() . "can't be fulfilled"); - } } diff --git a/framework/Injector/lib/Horde/Injector/Binder/Implementation.php b/framework/Injector/lib/Horde/Injector/Binder/Implementation.php index a5c9e597e..f188e3816 100644 --- a/framework/Injector/lib/Horde/Injector/Binder/Implementation.php +++ b/framework/Injector/lib/Horde/Injector/Binder/Implementation.php @@ -12,12 +12,12 @@ class Horde_Injector_Binder_Implementation implements Horde_Injector_Binder /** * TODO */ - private $_implementation; + protected $_implementation; /** * TODO */ - private $_setters; + protected $_setters; /** * TODO @@ -69,7 +69,7 @@ class Horde_Injector_Binder_Implementation implements Horde_Injector_Binder /** * TODO */ - private function _validateImplementation(ReflectionClass $reflectionClass) + protected function _validateImplementation(ReflectionClass $reflectionClass) { if ($reflectionClass->isAbstract() || $reflectionClass->isInterface()) { throw new Horde_Injector_Exception('Cannot bind interfaces or abstract classes "' . $this->_implementation . '" to an interface.'); @@ -79,24 +79,54 @@ class Horde_Injector_Binder_Implementation implements Horde_Injector_Binder /** * TODO */ - private function _getInstance(Horde_Injector $injector, ReflectionClass $class) + protected function _getInstance(Horde_Injector $injector, ReflectionClass $class) { return $class->getConstructor() - ? $class->newInstanceArgs($injector->getMethodDependencies($class->getConstructor())) + ? $class->newInstanceArgs($this->_getMethodDependencies($injector, $class->getConstructor())) : $class->newInstance(); } /** * TODO */ - private function _callSetters(Horde_Injector $injector, $instance) + protected function _callSetters(Horde_Injector $injector, $instance) { foreach ($this->_setters as $setter) { $reflectionMethod = new ReflectionMethod($instance, $setter); $reflectionMethod->invokeArgs( $instance, - $injector->getMethodDependencies($reflectionMethod) + $this->_getMethodDependencies($injector, $reflectionMethod) ); } } + + /** + */ + protected function _getMethodDependencies(Horde_Injector $injector, ReflectionMethod $method) + { + $dependencies = array(); + + try { + foreach ($method->getParameters() as $parameter) { + $dependencies[] = $this->_getParameterDependency($injector, $parameter); + } + } catch (Horde_Injector_Exception $e) { + throw new Horde_Injector_Exception("$method has unfulfilled dependencies ($parameter)", 0, $e); + } + + return $dependencies; + } + + /** + */ + protected function _getParameterDependency(Horde_Injector $injector, ReflectionParameter $parameter) + { + if ($parameter->getClass()) { + return $injector->getInstance($parameter->getClass()->getName()); + } elseif ($parameter->isOptional()) { + return $parameter->getDefaultValue(); + } + + throw new Horde_Injector_Exception("Untyped parameter \$" . $parameter->getName() . "can't be fulfilled"); + } } diff --git a/framework/Injector/lib/Horde/Injector/Binder/ImplementationWithSetters.php b/framework/Injector/lib/Horde/Injector/Binder/ImplementationWithSetters.php new file mode 100644 index 000000000..2053bd905 --- /dev/null +++ b/framework/Injector/lib/Horde/Injector/Binder/ImplementationWithSetters.php @@ -0,0 +1,50 @@ + + * @author James Pepin + * @category Horde + * @package Horde_Injector + */ +class Horde_Injector_Binder_ImplementationWithSetters extends Horde_Injector_Binder_Implementation +{ + /** + * TODO + */ + public function create(Horde_Injector $injector) + { + $reflectionClass = new ReflectionClass($this->_implementation); + $this->_validateImplementation($reflectionClass); + $instance = $this->_getInstance($injector, $reflectionClass); + $setters = $this->_findSetters($reflectionClass); + foreach ($setters as $setter) { + $this->bindSetter($setter); + } + $this->_callSetters($injector, $instance); + return $instance; + } + + /** + * Find all public methods in $reflectionClass that are annotated with + * @inject. + * + * @param ReflectionClass $reflectionClass + * + * @return array + */ + private function _findSetters(ReflectionClass $reflectionClass) + { + $setters = array(); + foreach ($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $reflectionMethod) { + $docBlock = $reflectionMethod->getDocComment(); + if ($docBlock) { + if (strpos($docBlock, '@inject') !== false) { + $setters[] = $reflectionMethod->name; + } + } + } + + return $setters; + } +} diff --git a/framework/Injector/lib/Horde/Injector/TopLevel.php b/framework/Injector/lib/Horde/Injector/TopLevel.php index 76d5650e5..130d3f8ad 100644 --- a/framework/Injector/lib/Horde/Injector/TopLevel.php +++ b/framework/Injector/lib/Horde/Injector/TopLevel.php @@ -18,11 +18,11 @@ class Horde_Injector_TopLevel implements Horde_Injector_Scope * Get an Implementation Binder that maps the $interface to itself * * @param string $interface The interface to retrieve binding information for - * @return Horde_Injector_Binder_Implementation a new binding object that maps the interface to itself + * @return Horde_Injector_Binder_ImplementationWithSetters a new binding object that maps the interface to itself, with setter injection */ public function getBinder($interface) { - return new Horde_Injector_Binder_Implementation($interface, $interface); + return new Horde_Injector_Binder_ImplementationWithSetters($interface, $interface); } /** diff --git a/framework/Injector/package.xml b/framework/Injector/package.xml index 7b77ebc29..93651eb43 100644 --- a/framework/Injector/package.xml +++ b/framework/Injector/package.xml @@ -62,6 +62,7 @@ + @@ -109,6 +110,7 @@ + -- 2.11.0