diff --git a/src/Configuration.php b/src/Configuration.php index f6e5a140..855bec97 100644 --- a/src/Configuration.php +++ b/src/Configuration.php @@ -3,6 +3,7 @@ namespace Zend\Di; use Traversable; +use Zend\Stdlib\ArrayUtils; class Configuration { @@ -12,21 +13,22 @@ class Configuration * @var Zend\Di\DependencyInjector */ protected $di = null; - - public function __construct($data) + + /** + * @param array|Traversable $options + */ + public function __construct($options) { - if ($data instanceof Traversable) { - if (method_exists($data, 'toArray')) { - $data = $data->toArray(); - } else { - $data = iterator_to_array($data, true); - } - } elseif (!is_array($data)) { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (!is_array($options)) { throw new Exception\InvalidArgumentException( - 'Configuration data must be of type Zend\Config\Config or an array' + 'Configuration data must be of type Traversable or an array' ); } - $this->data = $data; + $this->data = $options; } public function configure(Di $di) @@ -46,10 +48,28 @@ public function configureDefinition(Di $di, $definition) foreach ($definition as $definitionType => $definitionData) { switch ($definitionType) { case 'compiler': - // @todo + foreach ($definitionData as $filename) { + if (is_readable($filename)) { + $di->definitions()->addDefinition(new \Zend\Di\Definition\ArrayDefinition(include $filename), false); + } + } break; case 'runtime': - // @todo + if (isset($definitionData['enabled']) && !$definitionData['enabled']) { + // Remove runtime from definition list if not enabled + $definitions = array(); + foreach ($di->definitions() as $definition) { + if (!$definition instanceof \Zend\Di\Definition\RuntimeDefinition) { + $definitions[] = $definition; + } + } + $definitions = new DefinitionList($definitions); + $di->setDefinitionList($definitions); + } elseif (isset($definitionData['use_annotations']) && $definitionData['use_annotations']) { + $di->definitions()->getDefinitionByType('\Zend\Di\Definition\RuntimeDefinition') + ->getIntrospectionStrategy() + ->setUseAnnotations(true); + } break; case 'class': foreach ($definitionData as $className => $classData) { @@ -137,6 +157,10 @@ public function configureInstance(Di $di, $instanceData) case 'injection': $im->setInjections($target, $v); break; + case 'shared': + case 'share': + $im->setShared($target, $v); + break; } } } diff --git a/src/Definition/Annotation/Inject.php b/src/Definition/Annotation/Inject.php index 0366b2c9..7f0cc16e 100644 --- a/src/Definition/Annotation/Inject.php +++ b/src/Definition/Annotation/Inject.php @@ -2,9 +2,9 @@ namespace Zend\Di\Definition\Annotation; -use Zend\Code\Annotation\Annotation; +use Zend\Code\Annotation\AnnotationInterface; -class Inject implements Annotation +class Inject implements AnnotationInterface { protected $content = null; @@ -13,4 +13,4 @@ public function initialize($content) { $this->content = $content; } -} \ No newline at end of file +} diff --git a/src/Definition/Annotation/Instantiator.php b/src/Definition/Annotation/Instantiator.php index 4344179c..ce90de6c 100644 --- a/src/Definition/Annotation/Instantiator.php +++ b/src/Definition/Annotation/Instantiator.php @@ -2,9 +2,9 @@ namespace Zend\Di\Definition\Annotation; -use Zend\Code\Annotation\Annotation; +use Zend\Code\Annotation\AnnotationInterface; -class Instantiator implements Annotation +class Instantiator implements AnnotationInterface { protected $content = null; @@ -13,4 +13,4 @@ public function initialize($content) { $this->content = $content; } -} \ No newline at end of file +} diff --git a/src/Definition/ArrayDefinition.php b/src/Definition/ArrayDefinition.php index 2a0552fc..13641fb8 100644 --- a/src/Definition/ArrayDefinition.php +++ b/src/Definition/ArrayDefinition.php @@ -2,7 +2,7 @@ namespace Zend\Di\Definition; -class ArrayDefinition implements Definition +class ArrayDefinition implements DefinitionInterface { protected $dataArray = array(); diff --git a/src/Definition/Builder/PhpClass.php b/src/Definition/Builder/PhpClass.php index 71d0823a..5939abeb 100644 --- a/src/Definition/Builder/PhpClass.php +++ b/src/Definition/Builder/PhpClass.php @@ -8,6 +8,7 @@ class PhpClass protected $name = null; protected $instantiator = '__construct'; protected $injectionMethods = array(); + protected $superTypes = array(); public function setName($name) { diff --git a/src/Definition/BuilderDefinition.php b/src/Definition/BuilderDefinition.php index bc233ae6..734edc95 100644 --- a/src/Definition/BuilderDefinition.php +++ b/src/Definition/BuilderDefinition.php @@ -4,7 +4,7 @@ use Zend\Di\Exception; -class BuilderDefinition implements Definition +class BuilderDefinition implements DefinitionInterface { protected $defaultClassBuilder = 'Zend\Di\Definition\Builder\PhpClass'; protected $classes = array(); diff --git a/src/Definition/ClassDefinition.php b/src/Definition/ClassDefinition.php index 1c49db11..0f0fe3ce 100644 --- a/src/Definition/ClassDefinition.php +++ b/src/Definition/ClassDefinition.php @@ -2,7 +2,7 @@ namespace Zend\Di\Definition; -class ClassDefinition implements Definition, PartialMarker +class ClassDefinition implements DefinitionInterface, PartialMarker { protected $class = null; @@ -20,11 +20,13 @@ public function __construct($class) public function setInstantiator($instantiator) { $this->instantiator = $instantiator; + return $this; } public function setSupertypes(array $supertypes) { $this->supertypes = $supertypes; + return $this; } public function addMethod($method, $isRequired = null) @@ -33,6 +35,8 @@ public function addMethod($method, $isRequired = null) $isRequired = ($method === '__construct') ? true : false; } $this->methods[$method] = (bool) $isRequired; + + return $this; } /** @@ -57,6 +61,8 @@ public function addMethodParameter($method, $parameterName, array $parameterInfo $this->methodParameters[$method][$fqName] = array( $parameterName, $type, $required ); + + return $this; } /** @@ -160,4 +166,4 @@ public function getMethodParameters($class, $method) } return null; } -} \ No newline at end of file +} diff --git a/src/Definition/CompilerDefinition.php b/src/Definition/CompilerDefinition.php index 24db5e56..0f1b0882 100644 --- a/src/Definition/CompilerDefinition.php +++ b/src/Definition/CompilerDefinition.php @@ -5,13 +5,14 @@ use Zend\Code\Scanner\DerivedClassScanner, Zend\Code\Scanner\AggregateDirectoryScanner, Zend\Code\Scanner\DirectoryScanner, + Zend\Code\Scanner\FileScanner, Zend\Di\Definition\Annotation, Zend\Code\Annotation\AnnotationManager, Zend\Code\Reflection, Zend\Code\Annotation\AnnotationCollection; -class CompilerDefinition implements Definition +class CompilerDefinition implements DefinitionInterface { protected $isCompiled = false; @@ -107,6 +108,19 @@ protected function processClass($class) } } + $rTarget = $rClass; + $supertypes = array(); + do { + $supertypes = array_merge($supertypes, $rTarget->getInterfaceNames()); + if (!($rTargetParent = $rTarget->getParentClass())) { + break; + } + $supertypes[] = $rTargetParent->getName(); + $rTarget = $rTargetParent; + } while (true); + + $def['supertypes'] = $supertypes; + if ($def['instantiator'] == null) { if ($rClass->isInstantiable()) { $def['instantiator'] = '__construct'; @@ -395,7 +409,7 @@ public function hasClass($class) */ public function getClassSupertypes($class) { - if (!array_key_exists($class, $this->classes[$class])) { + if (!array_key_exists($class, $this->classes)) { $this->processClass($class); } return $this->classes[$class]['supertypes']; diff --git a/src/Definition/Definition.php b/src/Definition/DefinitionInterface.php similarity index 98% rename from src/Definition/Definition.php rename to src/Definition/DefinitionInterface.php index dd864594..45ea83a5 100644 --- a/src/Definition/Definition.php +++ b/src/Definition/DefinitionInterface.php @@ -2,7 +2,7 @@ namespace Zend\Di\Definition; -interface Definition +interface DefinitionInterface { /** * @abstract diff --git a/src/Definition/PartialMarker.php b/src/Definition/PartialMarker.php index f99f596f..459b26e5 100644 --- a/src/Definition/PartialMarker.php +++ b/src/Definition/PartialMarker.php @@ -5,4 +5,4 @@ interface PartialMarker { -} \ No newline at end of file +} diff --git a/src/Definition/RuntimeDefinition.php b/src/Definition/RuntimeDefinition.php index d5942d80..20a512a1 100644 --- a/src/Definition/RuntimeDefinition.php +++ b/src/Definition/RuntimeDefinition.php @@ -7,7 +7,7 @@ Zend\Code\Annotation\AnnotationCollection, Zend\Code\Reflection; -class RuntimeDefinition implements Definition +class RuntimeDefinition implements DefinitionInterface { /** @@ -105,7 +105,7 @@ public function hasClass($class) */ public function getClassSupertypes($class) { - if (!array_key_exists($class, $this->classes[$class])) { + if (!array_key_exists($class, $this->classes)) { $this->processClass($class); } return $this->classes[$class]['supertypes']; diff --git a/src/DefinitionList.php b/src/DefinitionList.php index 7d3f0cf6..22c504d8 100644 --- a/src/DefinitionList.php +++ b/src/DefinitionList.php @@ -4,7 +4,7 @@ use SplDoublyLinkedList; -class DefinitionList extends SplDoublyLinkedList implements Definition\Definition +class DefinitionList extends SplDoublyLinkedList implements Definition\DefinitionInterface { public function __construct($definitions) @@ -17,7 +17,7 @@ public function __construct($definitions) } } - public function addDefinition(Definition\Definition $definition, $addToBackOfList = true) + public function addDefinition(Definition\DefinitionInterface $definition, $addToBackOfList = true) { if ($addToBackOfList) { $this->push($definition); @@ -57,7 +57,7 @@ public function getDefinitionByType($type) public function getDefinitionForClass($class) { - /** @var $definition Definition\Definition */ + /** @var $definition Definition\DefinitionInterface */ foreach ($this as $definition) { if ($definition->hasClass($class)) { return $definition; @@ -75,7 +75,7 @@ public function forClass($class) public function getClasses() { $classes = array(); - /** @var $definition Definition\Definition */ + /** @var $definition Definition\DefinitionInterface */ foreach ($this as $definition) { $classes = array_merge($classes, $definition->getClasses()); } @@ -84,7 +84,7 @@ public function getClasses() public function hasClass($class) { - /** @var $definition Definition\Definition */ + /** @var $definition Definition\DefinitionInterface */ foreach ($this as $definition) { if ($definition->hasClass($class)) { return true; @@ -96,7 +96,7 @@ public function hasClass($class) public function getClassSupertypes($class) { $supertypes = array(); - /** @var $definition Definition\Definition */ + /** @var $definition Definition\DefinitionInterface */ foreach ($this as $definition) { $supertypes = array_merge($supertypes, $definition->getClassSupertypes($class)); } @@ -106,7 +106,7 @@ public function getClassSupertypes($class) public function getInstantiator($class) { - /** @var $definition Definition\Definition */ + /** @var $definition Definition\DefinitionInterface */ foreach ($this as $definition) { if ($definition->hasClass($class)) { $value = $definition->getInstantiator($class); @@ -122,7 +122,7 @@ public function getInstantiator($class) public function hasMethods($class) { - /** @var $definition Definition\Definition */ + /** @var $definition Definition\DefinitionInterface */ foreach ($this as $definition) { if ($definition->hasClass($class)) { if ($definition->hasMethods($class) === false && $definition instanceof Definition\PartialMarker) { @@ -137,7 +137,7 @@ public function hasMethods($class) public function hasMethod($class, $method) { - /** @var $definition Definition\Definition */ + /** @var $definition Definition\DefinitionInterface */ foreach ($this as $definition) { if ($definition->hasClass($class)) { if ($definition->hasMethods($class) === false && $definition instanceof Definition\PartialMarker) { @@ -152,7 +152,7 @@ public function hasMethod($class, $method) public function getMethods($class) { - /** @var $definition Definition\Definition */ + /** @var $definition Definition\DefinitionInterface */ $methods = array(); foreach ($this as $definition) { if ($definition->hasClass($class)) { @@ -174,7 +174,7 @@ public function hasMethodParameters($class, $method) public function getMethodParameters($class, $method) { - /** @var $definition Definition\Definition */ + /** @var $definition Definition\DefinitionInterface */ foreach ($this as $definition) { if ($definition->hasClass($class) && $definition->hasMethod($class, $method) && $definition->hasMethodParameters($class, $method)) { return $definition->getMethodParameters($class, $method); @@ -183,4 +183,4 @@ public function getMethodParameters($class, $method) return array(); } -} \ No newline at end of file +} diff --git a/src/DependencyInjection.php b/src/DependencyInjectionInterface.php similarity index 87% rename from src/DependencyInjection.php rename to src/DependencyInjectionInterface.php index 4e37f597..e09c3e57 100644 --- a/src/DependencyInjection.php +++ b/src/DependencyInjectionInterface.php @@ -2,7 +2,7 @@ namespace Zend\Di; -interface DependencyInjection extends Locator +interface DependencyInjectionInterface extends LocatorInterface { /** * Retrieve a new instance of a class diff --git a/src/Di.php b/src/Di.php index f7d4acd7..b6117b76 100644 --- a/src/Di.php +++ b/src/Di.php @@ -2,7 +2,7 @@ namespace Zend\Di; -class Di implements DependencyInjection +class Di implements DependencyInjectionInterface { /** * @var DefinitionList @@ -34,8 +34,10 @@ class Di implements DependencyInjection protected $references = array(); /** + * @param null|DefinitionList $definitions + * @param null|InstanceManager $instanceManager * @param null|Configuration $config - * @return \Di\Di\DependencyInjector + * @return Di */ public function __construct(DefinitionList $definitions = null, InstanceManager $instanceManager = null, Configuration $config = null) { @@ -59,7 +61,7 @@ public function configure(Configuration $config) } /** - * @param Definition $definition + * @param DefinitionList $definition * @return Di */ public function setDefinitionList(DefinitionList $definitions) @@ -145,8 +147,8 @@ public function get($name, array $params = array()) */ public function newInstance($name, array $params = array(), $isShared = true) { - // localize dependencies (this also will serve as poka-yoke) - $definitions = $this->definitions; + // localize dependencies + $definitions = $this->definitions; $instanceManager = $this->instanceManager(); if ($instanceManager->hasAlias($name)) { @@ -167,11 +169,11 @@ public function newInstance($name, array $params = array(), $isShared = true) } $instantiator = $definitions->getInstantiator($class); - $injectionMethods = $definitions->getMethods($class); + $injectionMethods = array(); + $injectionMethods[$class] = $definitions->getMethods($class); - $supertypeInjectionMethods = array(); foreach ($definitions->getClassSupertypes($class) as $supertype) { - $supertypeInjectionMethods[$supertype] = $definitions->getMethods($supertype); + $injectionMethods[$supertype] = $definitions->getMethods($supertype); } if ($instantiator === '__construct') { @@ -195,7 +197,7 @@ public function newInstance($name, array $params = array(), $isShared = true) $name ); } - throw new \RuntimeException($msg); + throw new Exception\RuntimeException($msg); } if ($isShared) { @@ -206,105 +208,115 @@ public function newInstance($name, array $params = array(), $isShared = true) } } - if ($injectionMethods || $supertypeInjectionMethods) { - foreach ($injectionMethods as $injectionMethod => $methodIsRequired) { - if ($injectionMethod !== '__construct'){ - $this->handleInjectionMethodForInstance($instance, $injectionMethod, $params, $alias, $methodIsRequired); - } + $this->handleInjectDependencies($instance, $injectionMethods, $params, $class, $alias, $name); + + array_pop($this->instanceContext); + return $instance; + } + + /** + * @param object $instance + * @param array $params + * @return void + */ + public function injectDependencies($instance, array $params = array()) + { + $definitions = $this->definitions(); + $class = get_class($instance); + $injectionMethods = array( + $class => ($definitions->hasClass($class)) ? $definitions->getMethods($class) : array() + ); + $parent = $class; + while ($parent = get_parent_class($parent)) { + if ($definitions->hasClass($parent)) { + $injectionMethods[$parent] = $definitions->getMethods($parent); } - foreach ($supertypeInjectionMethods as $supertype => $supertypeInjectionMethod) { - foreach ($supertypeInjectionMethod as $injectionMethod => $methodIsRequired) { - if ($injectionMethod !== '__construct') { - $this->handleInjectionMethodForInstance($instance, $injectionMethod, $params, $alias, $methodIsRequired, $supertype); + } + foreach (class_implements($class) as $interface) { + if ($definitions->hasClass($interface)) { + $injectionMethods[$interface] = $definitions->getMethods($interface); + } + } + $this->handleInjectDependencies($instance, $injectionMethods, $params, $class, null, null); + } + + + protected function handleInjectDependencies($instance, $injectionMethods, $params, $instanceClass, $instanceAlias, $requestedName) + { + // localize dependencies + $definitions = $this->definitions; + $instanceManager = $this->instanceManager(); + + $calledMethods = array('__construct' => true); + + if ($injectionMethods) { + foreach ($injectionMethods as $type => $typeInjectionMethods) { + foreach ($typeInjectionMethods as $typeInjectionMethod => $methodIsRequired) { + if (!isset($calledMethods[$typeInjectionMethod])) { + if ($this->resolveAndCallInjectionMethodForInstance($instance, $typeInjectionMethod, $params, $instanceAlias, $methodIsRequired, $type)) { + $calledMethods[$typeInjectionMethod] = true; + } } } } - $instanceConfiguration = $instanceManager->getConfiguration($name); - - if ($instanceConfiguration['injections']) { - $objectsToInject = $methodsToCall = array(); - foreach ($instanceConfiguration['injections'] as $injectName => $injectValue) { - if (is_int($injectName) && is_string($injectValue)) { - $objectsToInject[] = $this->get($injectValue, $params); - } elseif (is_string($injectName) && is_array($injectValue)) { - if (is_string(key($injectValue))) { - $methodsToCall[] = array('method' => $injectName, 'args' => $injectValue); - } else { - foreach ($injectValue as $methodCallArgs) { - $methodsToCall[] = array('method' => $injectName, 'args' => $methodCallArgs); + if ($requestedName) { + $instanceConfiguration = $instanceManager->getConfiguration($requestedName); + + if ($instanceConfiguration['injections']) { + $objectsToInject = $methodsToCall = array(); + foreach ($instanceConfiguration['injections'] as $injectName => $injectValue) { + if (is_int($injectName) && is_string($injectValue)) { + $objectsToInject[] = $this->get($injectValue, $params); + } elseif (is_string($injectName) && is_array($injectValue)) { + if (is_string(key($injectValue))) { + $methodsToCall[] = array('method' => $injectName, 'args' => $injectValue); + } else { + foreach ($injectValue as $methodCallArgs) { + $methodsToCall[] = array('method' => $injectName, 'args' => $methodCallArgs); + } } + } elseif (is_object($injectValue)) { + $objectsToInject[] = $injectValue; + } elseif (is_int($injectName) && is_array($injectValue)) { + throw new Exception\RuntimeException( + 'An injection was provided with a keyed index and an array of data, try using' + . ' the name of a particular method as a key for your injection data.' + ); } - } elseif (is_object($injectValue)) { - $objectsToInject[] = $injectValue; - } elseif (is_int($injectName) && is_array($injectValue)) { - // @todo must find method name somehow - throw new Exception\RuntimeException( - 'An injection was provided with a keyed index and an array of data, try using' - . ' the name of a particular method as a key for your injection data.' - ); } - } - if ($objectsToInject) { - foreach ($objectsToInject as $objectToInject) { - foreach ($injectionMethods as $injectionMethod => $methodIsRequired) { - $methodParams = $definitions->getMethodParameters($class, $injectionMethod); - if ($methodParams) { - foreach ($methodParams as $methodParam) { - if (get_class($objectToInject) == $methodParam[1] || - $this->isSubclassOf(get_class($objectToInject), $methodParam[1])) { - $callParams = $this->resolveMethodParameters(get_class($instance), $injectionMethod, - array($methodParam[0] => $objectToInject), false, $alias, true - ); - if ($callParams) { - call_user_func_array(array($instance, $injectionMethod), $callParams); + if ($objectsToInject) { + foreach ($objectsToInject as $objectToInject) { + $calledMethods = array('__construct' => true); + foreach ($injectionMethods as $type => $typeInjectionMethods) { + foreach ($typeInjectionMethods as $typeInjectionMethod => $methodIsRequired) { + if (!isset($calledMethods[$typeInjectionMethod])) { + $methodParams = $definitions->getMethodParameters($type, $typeInjectionMethod); + if ($methodParams) { + foreach ($methodParams as $methodParam) { + if (get_class($objectToInject) == $methodParam[1] || $this->isSubclassOf(get_class($objectToInject), $methodParam[1])) { + if ($this->resolveAndCallInjectionMethodForInstance($instance, $typeInjectionMethod, array($methodParam[0] => $objectToInject), $instanceAlias, true, $type)) { + $calledMethods[$typeInjectionMethod] = true; + } + continue 3; + } + } } - continue 3; } } } } } - } - if ($methodsToCall) { - foreach ($methodsToCall as $methodInfo) { - $callParams = $this->resolveMethodParameters(get_class($instance), $methodInfo['method'], - $methodInfo['args'], false, $alias, true - ); - call_user_func_array(array($instance, $methodInfo['method']), $callParams); + if ($methodsToCall) { + foreach ($methodsToCall as $methodInfo) { + $this->resolveAndCallInjectionMethodForInstance($instance, $methodInfo['method'], $methodInfo['args'], $instanceAlias, true, get_class($instance)); + } } } } } - - - - array_pop($this->instanceContext); - return $instance; } - /** - * @todo - * @param unknown_type $object - */ - /* - public function injectObjects($targetObject, array $objects = array()) - { - if ($objects === array()) { - throw new \Exception('Not yet implmeneted'); - } - - $targetClass = get_class($targetObject); - if (!$this->definitions()->hasClass($targetClass)) { - throw new Exception\RuntimeException('A definition for this object type cannot be found'); - } - - foreach ($objects as $objectToInject) { - - } - } - */ - /** * Retrieve a class instance based on class name * @@ -321,7 +333,7 @@ protected function createInstanceViaConstructor($class, $params, $alias = null) { $callParameters = array(); if ($this->definitions->hasMethod($class, '__construct')) { - $callParameters = $this->resolveMethodParameters($class, '__construct', $params, true, $alias, true); + $callParameters = $this->resolveMethodParameters($class, '__construct', $params, $alias, true, true); } // Hack to avoid Reflection in most common use cases @@ -366,7 +378,7 @@ protected function createInstanceViaCallback($callback, $params, $alias) $callParameters = array(); if ($this->definitions->hasMethod($class, $method)) { - $callParameters = $this->resolveMethodParameters($class, $method, $params, true, $alias, true); + $callParameters = $this->resolveMethodParameters($class, $method, $params, $alias, true, true); } return call_user_func_array($callback, $callParameters); } @@ -380,17 +392,18 @@ protected function createInstanceViaCallback($callback, $params, $alias) * @param array $params * @param string $alias */ - protected function handleInjectionMethodForInstance($instance, $method, $params, $alias, $methodIsRequired, $methodClass = null) + protected function resolveAndCallInjectionMethodForInstance($instance, $method, $params, $alias, $methodIsRequired, $methodClass = null) { $methodClass = ($methodClass) ?: get_class($instance); - // @todo make sure to resolve the supertypes for both the object & definition - $callParameters = $this->resolveMethodParameters($methodClass, $method, $params, false, $alias, $methodIsRequired); + $callParameters = $this->resolveMethodParameters($methodClass, $method, $params, $alias, $methodIsRequired); if ($callParameters == false) { - return; + return false; } if ($callParameters !== array_fill(0, count($callParameters), null)) { call_user_func_array(array($instance, $method), $callParameters); + return true; } + return false; } /** @@ -403,7 +416,7 @@ protected function handleInjectionMethodForInstance($instance, $method, $params, * @param string $alias * @return array */ - protected function resolveMethodParameters($class, $method, array $callTimeUserParams, $isInstantiator, $alias, $methodIsRequired) + protected function resolveMethodParameters($class, $method, array $callTimeUserParams, $alias, $methodIsRequired, $isInstantiator = false) { // parameters for this method, in proper order, to be returned $resolvedParams = array(); @@ -433,9 +446,13 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP } // for the parent class, provided we are deeper than one node - list($requestedClass, $requestedAlias) = ($this->instanceContext[0][0] == 'NEW') - ? array($this->instanceContext[0][1], $this->instanceContext[0][2]) - : array($this->instanceContext[1][1], $this->instanceContext[1][2]); + if (isset($this->instanceContext[0])) { + list($requestedClass, $requestedAlias) = ($this->instanceContext[0][0] == 'NEW') + ? array($this->instanceContext[0][1], $this->instanceContext[0][2]) + : array($this->instanceContext[1][1], $this->instanceContext[1][2]); + } else { + $requestedClass = $requestedAlias = null; + } if ($requestedClass != $class && $this->instanceManager->hasConfiguration($requestedClass)) { $iConfig['requestedClass'] = $this->instanceManager->getConfiguration($requestedClass); @@ -456,7 +473,6 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP // PRIORITY 1 - consult user provided parameters if (isset($callTimeUserParams[$fqParamPos]) || isset($callTimeUserParams[$name])) { - // @todo FQ Name in call time params if (isset($callTimeUserParams[$fqParamPos])) { $callTimeCurValue =& $callTimeUserParams[$fqParamPos]; } elseif (isset($callTimeUserParams[$fqParamName])) { @@ -501,7 +517,6 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP || isset($iConfig[$thisIndex]['parameters'][$fqParamName]) || isset($iConfig[$thisIndex]['parameters'][$name])) { - // @todo FQ Name in config parameters if (isset($iConfig[$thisIndex]['parameters'][$fqParamPos])) { $iConfigCurValue =& $iConfig[$thisIndex]['parameters'][$fqParamPos]; } elseif (isset($iConfig[$thisIndex]['parameters'][$fqParamName])) { @@ -602,7 +617,13 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP ); } array_push($this->currentDependencies, $class); - $resolvedParams[$index] = $this->get($computedParams['required'][$fqParamPos][0], $callTimeUserParams); + $dConfig = $this->instanceManager->getConfiguration($computedParams['required'][$fqParamPos][0]); + if ($dConfig['shared'] === false) { + $resolvedParams[$index] = $this->newInstance($computedParams['required'][$fqParamPos][0], $callTimeUserParams, false); + } else { + $resolvedParams[$index] = $this->get($computedParams['required'][$fqParamPos][0], $callTimeUserParams); + } + array_pop($this->currentDependencies); } elseif (!array_key_exists($fqParamPos, $computedParams['optional'])) { diff --git a/src/Exception.php b/src/Exception.php deleted file mode 100644 index 4827dbd3..00000000 --- a/src/Exception.php +++ /dev/null @@ -1,6 +0,0 @@ - array of ordered method params */ 'injections' => array(), + /** + * alias|class => bool + */ + 'shared' => true ); /** @@ -74,7 +78,7 @@ public function getSharedInstance($classOrAlias) public function addSharedInstance($instance, $classOrAlias) { if (!is_object($instance)) { - throw new Exception\InvalidArgumentException('This method requires an object to be shared'); + throw new Exception\InvalidArgumentException('This method requires an object to be shared. Class or Alias given: '.$classOrAlias); } $this->sharedInstances[$classOrAlias] = $instance; @@ -240,6 +244,7 @@ public function setConfiguration($aliasOrClass, array $configuration, $append = $configuration = array( 'parameters' => isset($configuration['parameters']) ? $configuration['parameters'] : array(), 'injections' => isset($configuration['injections']) ? $configuration['injections'] : array(), + 'shared' => isset($configuration['shared']) ? $configuration['shared'] : true ); $this->configurations[$key] = array_replace_recursive($this->configurations[$key], $configuration); } @@ -273,7 +278,7 @@ public function getConfiguration($aliasOrClass) */ public function setParameters($aliasOrClass, array $parameters) { - return $this->setConfiguration($aliasOrClass, array('parameters' => $parameters), true); + $this->setConfiguration($aliasOrClass, array('parameters' => $parameters), true); } /** @@ -285,9 +290,13 @@ public function setParameters($aliasOrClass, array $parameters) */ public function setInjections($aliasOrClass, array $injections) { - return $this->setConfiguration($aliasOrClass, array('injections' => $injections), true); + $this->setConfiguration($aliasOrClass, array('injections' => $injections), true); + } + + public function setShared($aliasOrClass, $isShared) + { + $this->setConfiguration($aliasOrClass, array('shared' => $isShared), true); } - public function hasTypePreferences($interfaceOrAbstract) { diff --git a/src/Locator.php b/src/LocatorInterface.php similarity index 92% rename from src/Locator.php rename to src/LocatorInterface.php index acf8a79b..71483737 100644 --- a/src/Locator.php +++ b/src/LocatorInterface.php @@ -1,7 +1,7 @@ getMethods() as $key => $methodData) { + foreach ($meta->getMethods() as $methodData) { if (!isset($methodData['name']) && !isset($methodData['method'])) { continue; } @@ -171,7 +173,7 @@ public function getCodeGenerator($filename = null) // Create fetch of stored service if ($im->hasSharedInstance($name, $params)) { - $getterBody .= sprintf("if (isset(\$this->services['%s'])) {\n", $name); + $getterBody .= sprintf("if (isset(\$this->services['%s'])) {\n", $name); $getterBody .= sprintf("%sreturn \$this->services['%s'];\n}\n\n", $indent, $name); } @@ -185,7 +187,7 @@ public function getCodeGenerator($filename = null) // End getter body $getterBody .= "return \$object;\n"; - $getterDef = new CodeGen\PhpMethod(); + $getterDef = new CodeGen\MethodGenerator(); $getterDef->setName($getter) ->setBody($getterBody); $getters[] = $getterDef; @@ -212,16 +214,14 @@ public function getCodeGenerator($filename = null) $switch .= "}\n\n"; // Build get() method - $nameParam = new CodeGen\PhpParameter(); + $nameParam = new CodeGen\ParameterGenerator(); $nameParam->setName('name'); - $defaultParams = new CodeGen\PhpParameterDefaultValue(); - $defaultParams->setValue(array()); - $paramsParam = new CodeGen\PhpParameter(); + $paramsParam = new CodeGen\ParameterGenerator(); $paramsParam->setName('params') ->setType('array') - ->setDefaultValue($defaultParams); + ->setDefaultValue(array()); - $get = new CodeGen\PhpMethod(); + $get = new CodeGen\MethodGenerator(); $get->setName('get'); $get->setParameters(array( $nameParam, @@ -238,15 +238,15 @@ public function getCodeGenerator($filename = null) } // Create class code generation object - $container = new CodeGen\PhpClass(); + $container = new CodeGen\ClassGenerator(); $container->setName($this->containerClass) ->setExtendedClass('ServiceLocator') - ->setMethod($get) - ->setMethods($getters) - ->setMethods($aliasMethods); + ->addMethodFromGenerator($get) + ->addMethods($getters) + ->addMethods($aliasMethods); // Create PHP file code generation object - $classFile = new CodeGen\PhpFile(); + $classFile = new CodeGen\FileGenerator(); $classFile->setUse('Zend\Di\ServiceLocator') ->setClass($container); @@ -275,8 +275,7 @@ protected function reduceAliases(array $aliasList) { $reduced = array(); $aliases = array_keys($aliasList); - foreach ($aliasList as $alias => $service) - { + foreach ($aliasList as $alias => $service) { if (in_array($service, $aliases)) { do { $service = $aliasList[$service]; @@ -295,12 +294,12 @@ protected function reduceAliases(array $aliasList) * * @param string $alias * @param class $class Class to which alias refers - * @return CodeGen\PhpMethod + * @return CodeGen\MethodGenerator */ protected function getCodeGenMethodFromAlias($alias, $class) { $alias = $this->normalizeAlias($alias); - $method = new CodeGen\PhpMethod(); + $method = new CodeGen\MethodGenerator(); $method->setName($alias) ->setBody(sprintf('return $this->get(\'%s\');', $class)); return $method; diff --git a/src/ServiceLocation.php b/src/ServiceLocatorInterface.php similarity index 54% rename from src/ServiceLocation.php rename to src/ServiceLocatorInterface.php index b130dfa4..ca773bd0 100644 --- a/src/ServiceLocation.php +++ b/src/ServiceLocatorInterface.php @@ -1,7 +1,7 @@ assertContains('my-dbAdapter', $im->getTypePreferences('my-mapper')); $this->assertTrue($im->hasConfiguration('My\DbAdapter')); - $expected = array('parameters' => array('username' => 'readonly', 'password' => 'mypassword'), 'injections' => array()); + $expected = array('parameters' => array('username' => 'readonly', 'password' => 'mypassword'), 'injections' => array(), 'shared' => true); $this->assertEquals($expected, $im->getConfiguration('My\DbAdapter')); $this->assertTrue($im->hasConfiguration('my-dbAdapter')); - $expected = array('parameters' => array('username' => 'readwrite'), 'injections' => array()); + $expected = array('parameters' => array('username' => 'readwrite'), 'injections' => array(), 'shared' => true); $this->assertEquals($expected, $im->getConfiguration('my-dbAdapter')); } @@ -72,7 +72,51 @@ public function testConfigurationCanConfigureBuilderDefinitionFromIni() ); } - - + public function testConfigurationCanConfigureRuntimeDefinitionDefaultFromIni() + { + $ini = ConfigFactory::fromFile(__DIR__ . '/_files/sample.ini', true)->get('section-c'); + $config = new Configuration($ini->di); + $di = new Di(); + $di->configure($config); + $definition = $di->definitions()->getDefinitionByType('Zend\Di\Definition\RuntimeDefinition'); + $this->assertInstanceOf('Zend\Di\Definition\RuntimeDefinition', $definition); + $this->assertFalse($definition->getIntrospectionStrategy()->getUseAnnotations()); + } + + public function testConfigurationCanConfigureRuntimeDefinitionDisabledFromIni() + { + $ini = ConfigFactory::fromFile(__DIR__ . '/_files/sample.ini', true)->get('section-d'); + $config = new Configuration($ini->di); + $di = new Di(); + $di->configure($config); + $definition = $di->definitions()->getDefinitionByType('Zend\Di\Definition\RuntimeDefinition'); + $this->assertFalse($definition); + } + + public function testConfigurationCanConfigureRuntimeDefinitionUseAnnotationFromIni() + { + $ini = ConfigFactory::fromFile(__DIR__ . '/_files/sample.ini', true)->get('section-e'); + $config = new Configuration($ini->di); + $di = new Di(); + $di->configure($config); + $definition = $di->definitions()->getDefinitionByType('Zend\Di\Definition\RuntimeDefinition'); + $this->assertTrue($definition->getIntrospectionStrategy()->getUseAnnotations()); + } + + public function testConfigurationCanConfigureCompiledDefinition() + { + $config = ConfigFactory::fromFile(__DIR__ . '/_files/sample.php', true); + $config = new Configuration($config->di); + $di = new Di(); + $di->configure($config); + $definition = $di->definitions()->getDefinitionByType('Zend\Di\Definition\ArrayDefinition'); + $this->assertInstanceOf('Zend\Di\Definition\ArrayDefinition', $definition); + $this->assertTrue($di->definitions()->hasClass('My\DbAdapter')); + $this->assertTrue($di->definitions()->hasClass('My\EntityA')); + $this->assertTrue($di->definitions()->hasClass('My\Mapper')); + $this->assertTrue($di->definitions()->hasClass('My\RepositoryA')); + $this->assertTrue($di->definitions()->hasClass('My\RepositoryB')); + $this->assertFalse($di->definitions()->hasClass('My\Foo')); + } } diff --git a/test/Definition/BuilderDefinitionTest.php b/test/Definition/BuilderDefinitionTest.php index 04dd4ed8..5e006510 100644 --- a/test/Definition/BuilderDefinitionTest.php +++ b/test/Definition/BuilderDefinitionTest.php @@ -13,7 +13,7 @@ class BuilderDefinitionTest extends TestCase public function testBuilderImplementsDefinition() { $builder = new BuilderDefinition(); - $this->assertInstanceOf('Zend\Di\Definition\Definition', $builder); + $this->assertInstanceOf('Zend\Di\Definition\DefinitionInterface', $builder); } public function testBuilderCanBuildClassWithMethods() diff --git a/test/Definition/CompilerDefinitionTest.php b/test/Definition/CompilerDefinitionTest.php index be30bcb8..e2be05b4 100644 --- a/test/Definition/CompilerDefinitionTest.php +++ b/test/Definition/CompilerDefinitionTest.php @@ -4,6 +4,7 @@ use Zend\Di\Definition\CompilerDefinition, Zend\Code\Scanner\DirectoryScanner, + Zend\Code\Scanner\FileScanner, PHPUnit_Framework_TestCase as TestCase; class CompilerDefinitionTest extends TestCase @@ -42,4 +43,40 @@ public function testCompilerCompilesAgainstConstructorInjectionAssets() $definition->getMethodParameters('ZendTest\Di\TestAsset\CompilerClasses\C', 'setB') ); } + + public function testCompilerSupertypes() + { + $definition = new CompilerDefinition; + $definition->addDirectory(__DIR__ . '/../TestAsset/CompilerClasses'); + $definition->compile(); + $this->assertEquals(0, count($definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\C'))); + $this->assertEquals(1, count($definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\D'))); + $this->assertEquals(2, count($definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\E'))); + $this->assertContains('ZendTest\Di\TestAsset\CompilerClasses\C', $definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\D')); + $this->assertContains('ZendTest\Di\TestAsset\CompilerClasses\C', $definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\E')); + $this->assertContains('ZendTest\Di\TestAsset\CompilerClasses\D', $definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\E')); + } + + public function testCompilerDirectoryScannerAndFileScanner() + { + $definition = new CompilerDefinition; + $definition->addDirectoryScanner(new DirectoryScanner(__DIR__ . '/../TestAsset/CompilerClasses')); + $definition->addCodeScannerFile(new FileScanner(__DIR__ . '/../TestAsset/CompilerClasses/A.php')); + $definition->compile(); + $this->assertContains('ZendTest\Di\TestAsset\CompilerClasses\C', $definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\D')); + $this->assertContains('ZendTest\Di\TestAsset\CompilerClasses\C', $definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\E')); + $this->assertContains('ZendTest\Di\TestAsset\CompilerClasses\D', $definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\E')); + } + + public function testCompilerFileScanner() + { + $definition = new CompilerDefinition; + $definition->addCodeScannerFile(new FileScanner(__DIR__ . '/../TestAsset/CompilerClasses/C.php')); + $definition->addCodeScannerFile(new FileScanner(__DIR__ . '/../TestAsset/CompilerClasses/D.php')); + $definition->addCodeScannerFile(new FileScanner(__DIR__ . '/../TestAsset/CompilerClasses/E.php')); + $definition->compile(); + $this->assertContains('ZendTest\Di\TestAsset\CompilerClasses\C', $definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\D')); + $this->assertContains('ZendTest\Di\TestAsset\CompilerClasses\C', $definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\E')); + $this->assertContains('ZendTest\Di\TestAsset\CompilerClasses\D', $definition->getClassSupertypes('ZendTest\Di\TestAsset\CompilerClasses\E')); + } } diff --git a/test/DiTest.php b/test/DiTest.php index d52cdadd..d84b9de2 100644 --- a/test/DiTest.php +++ b/test/DiTest.php @@ -43,18 +43,18 @@ public function testDiConstructorCanTakeDependencies() public function testPassingInvalidDefinitionRaisesException() { $di = new Di(); - + $this->setExpectedException('PHPUnit_Framework_Error'); $di->setDefinitionList(array('foo')); } - + public function testGetRetrievesObjectWithMatchingClassDefinition() { $di = new Di(); $obj = $di->get('ZendTest\Di\TestAsset\BasicClass'); $this->assertInstanceOf('ZendTest\Di\TestAsset\BasicClass', $obj); } - + public function testGetRetrievesSameInstanceOnSubsequentCalls() { $di = new Di(); @@ -64,23 +64,23 @@ public function testGetRetrievesSameInstanceOnSubsequentCalls() $this->assertInstanceOf('ZendTest\Di\TestAsset\BasicClass', $obj2); $this->assertSame($obj1, $obj2); } - + public function testGetThrowsExceptionWhenUnknownClassIsUsed() { $di = new Di(); - + $this->setExpectedException('Zend\Di\Exception\ClassNotFoundException', 'could not be located in'); $obj1 = $di->get('ZendTest\Di\TestAsset\NonExistentClass'); } - + public function testGetThrowsExceptionWhenMissingParametersAreEncountered() { $di = new Di(); - + $this->setExpectedException('Zend\Di\Exception\MissingPropertyException', 'Missing instance/object for '); $obj1 = $di->get('ZendTest\Di\TestAsset\BasicClassWithParam'); } - + public function testNewInstanceReturnsDifferentInstances() { $di = new Di(); @@ -90,7 +90,7 @@ public function testNewInstanceReturnsDifferentInstances() $this->assertInstanceOf('ZendTest\Di\TestAsset\BasicClass', $obj2); $this->assertNotSame($obj1, $obj2); } - + public function testNewInstanceReturnsInstanceThatIsSharedWithGet() { $di = new Di(); @@ -100,7 +100,7 @@ public function testNewInstanceReturnsInstanceThatIsSharedWithGet() $this->assertInstanceOf('ZendTest\Di\TestAsset\BasicClass', $obj2); $this->assertSame($obj1, $obj2); } - + public function testNewInstanceReturnsInstanceThatIsNotSharedWithGet() { $di = new Di(); @@ -204,7 +204,7 @@ public function testGetWillResolveConstructorInjectionDependencies() $this->assertInstanceOf('ZendTest\Di\TestAsset\ConstructorInjection\B', $b); $this->assertInstanceOf('ZendTest\Di\TestAsset\ConstructorInjection\A', $b->a); } - + /** * @group ConstructorInjection */ @@ -214,15 +214,15 @@ public function testGetWillResolveConstructorInjectionDependenciesAndInstanceAre $b = $di->get('ZendTest\Di\TestAsset\ConstructorInjection\B'); $this->assertInstanceOf('ZendTest\Di\TestAsset\ConstructorInjection\B', $b); $this->assertInstanceOf('ZendTest\Di\TestAsset\ConstructorInjection\A', $b->a); - + $b2 = $di->get('ZendTest\Di\TestAsset\ConstructorInjection\B'); $this->assertInstanceOf('ZendTest\Di\TestAsset\ConstructorInjection\B', $b2); $this->assertInstanceOf('ZendTest\Di\TestAsset\ConstructorInjection\A', $b2->a); - + $this->assertSame($b, $b2); $this->assertSame($b->a, $b2->a); } - + /** * @group ConstructorInjection */ @@ -233,48 +233,48 @@ public function testNewInstanceWillResolveConstructorInjectionDependencies() $this->assertInstanceOf('ZendTest\Di\TestAsset\ConstructorInjection\B', $b); $this->assertInstanceOf('ZendTest\Di\TestAsset\ConstructorInjection\A', $b->a); } - + /** * @group ConstructorInjection */ public function testNewInstanceWillResolveConstructorInjectionDependenciesWithProperties() { $di = new Di(); - + $im = $di->instanceManager(); $im->setParameters('ZendTest\Di\TestAsset\ConstructorInjection\X', array('one' => 1, 'two' => 2)); - + $y = $di->newInstance('ZendTest\Di\TestAsset\ConstructorInjection\Y'); $this->assertEquals(1, $y->x->one); $this->assertEquals(2, $y->x->two); } - + /** * @group ConstructorInjection */ public function testNewInstanceWillThrowExceptionOnConstructorInjectionDependencyWithMissingParameter() { $di = new Di(); - + $this->setExpectedException('Zend\Di\Exception\MissingPropertyException', 'Missing instance/object for parameter'); $b = $di->newInstance('ZendTest\Di\TestAsset\ConstructorInjection\X'); } - + /** * @group ConstructorInjection */ public function testNewInstanceWillResolveConstructorInjectionDependenciesWithMoreThan2Dependencies() { $di = new Di(); - + $im = $di->instanceManager(); $im->setParameters('ZendTest\Di\TestAsset\ConstructorInjection\X', array('one' => 1, 'two' => 2)); - + $z = $di->newInstance('ZendTest\Di\TestAsset\ConstructorInjection\Z'); $this->assertInstanceOf('ZendTest\Di\TestAsset\ConstructorInjection\Y', $z->y); $this->assertInstanceOf('ZendTest\Di\TestAsset\ConstructorInjection\X', $z->y->x); } - + /** * @group SetterInjection */ @@ -290,7 +290,7 @@ public function testGetWillResolveSetterInjectionDependencies() $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\B', $b); $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\A', $b->a); } - + /** * @group SetterInjection */ @@ -306,16 +306,16 @@ public function testGetWillResolveSetterInjectionDependenciesAndInstanceAreTheSa $b = $di->get('ZendTest\Di\TestAsset\SetterInjection\B'); $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\B', $b); $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\A', $b->a); - + $b2 = $di->get('ZendTest\Di\TestAsset\SetterInjection\B'); $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\B', $b2); $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\A', $b2->a); - + $this->assertSame($b, $b2); $this->assertSame($b->a, $a); $this->assertSame($b2->a, $a); } - + /** * @group SetterInjection */ @@ -332,7 +332,7 @@ public function testNewInstanceWillResolveSetterInjectionDependencies() $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\B', $b); $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\A', $b->a); } - + /** * @todo Setter Injections is not automatic, find a way to test this logically * @@ -341,7 +341,7 @@ public function testNewInstanceWillResolveSetterInjectionDependencies() public function testNewInstanceWillResolveSetterInjectionDependenciesWithProperties() { $di = new Di(); - + $im = $di->instanceManager(); $im->setParameters('ZendTest\Di\TestAsset\SetterInjection\X', array('one' => 1, 'two' => 2)); @@ -351,10 +351,10 @@ public function testNewInstanceWillResolveSetterInjectionDependenciesWithPropert $this->assertEquals(1, $y->x->one); $this->assertEquals(2, $y->x->two); } - + /** * Test for Circular Dependencies (case 1) - * + * * A->B, B->A * @group CircularDependencyCheck */ @@ -365,10 +365,10 @@ public function testNewInstanceThrowsExceptionOnBasicCircularDependency() $this->setExpectedException('Zend\Di\Exception\CircularDependencyException'); $di->newInstance('ZendTest\Di\TestAsset\CircularClasses\A'); } - + /** * Test for Circular Dependencies (case 2) - * + * * C->D, D->E, E->C * @group CircularDependencyCheck */ @@ -382,10 +382,10 @@ public function testNewInstanceThrowsExceptionOnThreeLevelCircularDependency() ); $di->newInstance('ZendTest\Di\TestAsset\CircularClasses\C'); } - + /** * Test for Circular Dependencies (case 2) - * + * * C->D, D->E, E->C * @group CircularDependencyCheck */ @@ -399,10 +399,10 @@ public function testNewInstanceThrowsExceptionWhenEnteringInMiddleOfCircularDepe ); $di->newInstance('ZendTest\Di\TestAsset\CircularClasses\D'); } - + /** * Fix for PHP bug in is_subclass_of - * + * * @see https://bugs.php.net/bug.php?id=53727 */ public function testNewInstanceWillUsePreferredClassForInterfaceHints() @@ -412,7 +412,7 @@ public function testNewInstanceWillUsePreferredClassForInterfaceHints() 'ZendTest\Di\TestAsset\PreferredImplClasses\A', 'ZendTest\Di\TestAsset\PreferredImplClasses\BofA' ); - + $c = $di->get('ZendTest\Di\TestAsset\PreferredImplClasses\C'); $a = $c->a; $this->assertInstanceOf('ZendTest\Di\TestAsset\PreferredImplClasses\BofA', $a); @@ -590,5 +590,78 @@ public function testInjectionForSetterInjectionWillConsultSupertypeDefinitionInC $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\C', $c); $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\A', $c->a); } - + + /** + * @group SharedInstance + */ + public function testMarkingClassAsNotSharedInjectsNewInstanceIntoAllRequestersButDependentsAreShared() + { + $di = new Di(); + $di->configure(new Configuration(array( + 'instance' => array( + 'ZendTest\Di\TestAsset\SharedInstance\Lister' => array( + 'shared' => false + ) + ) + ))); + $movie = $di->get('ZendTest\Di\TestAsset\SharedInstance\Movie'); + $venue = $di->get('ZendTest\Di\TestAsset\SharedInstance\Venue'); + + $this->assertNotSame($movie->lister, $venue->lister); + $this->assertSame($movie->lister->sharedLister, $venue->lister->sharedLister); + } + + public function testDiWillInjectDependenciesForInstance() + { + $di = new Di; + + // for setter injection, the dependency is not required, thus it must be forced + $classDef = new Definition\ClassDefinition('ZendTest\Di\TestAsset\SetterInjection\B'); + $classDef->addMethod('setA', true); + $di->definitions()->addDefinition($classDef, false); // top of stack b/c Runtime is already there + + $b = new TestAsset\SetterInjection\B; + $di->injectDependencies($b); + $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\A', $b->a); + } + + public function testDiWillInjectDependenciesForAlias() + { + $di = new Di; + + // for setter injection, the dependency is not required, thus it must be forced + $classDef = new Definition\ClassDefinition('ZendTest\Di\TestAsset\SetterInjection\B'); + $classDef->addMethod('setA', false); + $classDef->addMethodParameter('setA', 'a', array('type' => 'ZendTest\Di\TestAsset\SetterInjection\A', 'required' => false)); + $di->definitions()->addDefinition($classDef, false); + $di->instanceManager()->addAlias('b_alias', 'ZendTest\Di\TestAsset\SetterInjection\B'); + $di->instanceManager()->setInjections('b_alias', array('ZendTest\Di\TestAsset\SetterInjection\A')); + + $b = $di->get('b_alias'); + $this->assertInstanceOf('ZendTest\Di\TestAsset\SetterInjection\A', $b->a); + } + + /* + * @group SetterInjection + * @group SupertypeResolution + */ + public function testInjectionForSetterInjectionWillNotUseSupertypeWhenChildParamIsExplicitlyDefined() + { + $di = new Di(); + // for setter injection, the dependency is not required, thus it must be forced + $di->instanceManager()->setParameters( + 'ZendTest\Di\TestAsset\InheritanceClasses\B', + array('test' => 'b') + ); + $di->instanceManager()->setParameters( + 'ZendTest\Di\TestAsset\InheritanceClasses\A', + array('test' => 'a') + ); + + $b = $di->get('ZendTest\Di\TestAsset\InheritanceClasses\B'); + $this->assertEquals('b', $b->test); + + $c = $di->get('ZendTest\Di\TestAsset\InheritanceClasses\C'); + $this->assertEquals('b', $c->test); + } } diff --git a/test/InstanceManagerTest.php b/test/InstanceManagerTest.php index 8a0092dc..207f4974 100644 --- a/test/InstanceManagerTest.php +++ b/test/InstanceManagerTest.php @@ -71,6 +71,7 @@ public function testInstanceManagerResolvesRecursiveAliasesForConfiguration() $im->setConfiguration('bar-alias', $config); $config['injections'] = array(); + $config['shared'] = true; $this->assertEquals($config, $im->getConfiguration('foo-alias')); } diff --git a/test/TestAsset/BasicClass.php b/test/TestAsset/BasicClass.php index 348e30fe..a822806d 100644 --- a/test/TestAsset/BasicClass.php +++ b/test/TestAsset/BasicClass.php @@ -5,4 +5,4 @@ class BasicClass { -} \ No newline at end of file +} diff --git a/test/TestAsset/BasicClassWithParam.php b/test/TestAsset/BasicClassWithParam.php index 3c004752..1b5cf095 100644 --- a/test/TestAsset/BasicClassWithParam.php +++ b/test/TestAsset/BasicClassWithParam.php @@ -5,4 +5,4 @@ class BasicClassWithParam { public function __construct($foo){} -} \ No newline at end of file +} diff --git a/test/TestAsset/CallbackClasses/A.php b/test/TestAsset/CallbackClasses/A.php index d55dcb8a..ddcd160c 100644 --- a/test/TestAsset/CallbackClasses/A.php +++ b/test/TestAsset/CallbackClasses/A.php @@ -11,4 +11,4 @@ public static function factory() } private function __construct() {} -} \ No newline at end of file +} diff --git a/test/TestAsset/CircularClasses/A.php b/test/TestAsset/CircularClasses/A.php index 48f5f1f8..665762c8 100644 --- a/test/TestAsset/CircularClasses/A.php +++ b/test/TestAsset/CircularClasses/A.php @@ -8,4 +8,4 @@ public function __construct(B $b) { } -} \ No newline at end of file +} diff --git a/test/TestAsset/CircularClasses/B.php b/test/TestAsset/CircularClasses/B.php index 6a5a6223..c346a664 100644 --- a/test/TestAsset/CircularClasses/B.php +++ b/test/TestAsset/CircularClasses/B.php @@ -5,4 +5,4 @@ class B { public function __construct(A $a) {} -} \ No newline at end of file +} diff --git a/test/TestAsset/CircularClasses/C.php b/test/TestAsset/CircularClasses/C.php index 0f5fa304..7f34772f 100644 --- a/test/TestAsset/CircularClasses/C.php +++ b/test/TestAsset/CircularClasses/C.php @@ -8,4 +8,4 @@ public function __construct(D $d) { } -} \ No newline at end of file +} diff --git a/test/TestAsset/CircularClasses/D.php b/test/TestAsset/CircularClasses/D.php index fa77c093..aa997fc4 100644 --- a/test/TestAsset/CircularClasses/D.php +++ b/test/TestAsset/CircularClasses/D.php @@ -8,4 +8,4 @@ public function __construct(E $e) { } -} \ No newline at end of file +} diff --git a/test/TestAsset/CircularClasses/E.php b/test/TestAsset/CircularClasses/E.php index 060536b5..fc92bbdc 100644 --- a/test/TestAsset/CircularClasses/E.php +++ b/test/TestAsset/CircularClasses/E.php @@ -8,4 +8,4 @@ public function __construct(C $c) { } -} \ No newline at end of file +} diff --git a/test/TestAsset/CompilerClasses/A.php b/test/TestAsset/CompilerClasses/A.php index 7aa064b3..28d26267 100644 --- a/test/TestAsset/CompilerClasses/A.php +++ b/test/TestAsset/CompilerClasses/A.php @@ -4,4 +4,4 @@ class A { -} \ No newline at end of file +} diff --git a/test/TestAsset/CompilerClasses/B.php b/test/TestAsset/CompilerClasses/B.php index 287ff5be..0a04526c 100644 --- a/test/TestAsset/CompilerClasses/B.php +++ b/test/TestAsset/CompilerClasses/B.php @@ -8,4 +8,4 @@ public function __construct(B $b) { } -} \ No newline at end of file +} diff --git a/test/TestAsset/CompilerClasses/C.php b/test/TestAsset/CompilerClasses/C.php index 7c41074a..d2f73d2f 100644 --- a/test/TestAsset/CompilerClasses/C.php +++ b/test/TestAsset/CompilerClasses/C.php @@ -8,4 +8,4 @@ public function setB(B $b) { } -} \ No newline at end of file +} diff --git a/test/TestAsset/CompilerClasses/D.php b/test/TestAsset/CompilerClasses/D.php index 4e74ecdc..12848c11 100644 --- a/test/TestAsset/CompilerClasses/D.php +++ b/test/TestAsset/CompilerClasses/D.php @@ -5,4 +5,4 @@ class D extends C { -} \ No newline at end of file +} diff --git a/test/TestAsset/CompilerClasses/E.php b/test/TestAsset/CompilerClasses/E.php new file mode 100644 index 00000000..d6259461 --- /dev/null +++ b/test/TestAsset/CompilerClasses/E.php @@ -0,0 +1,8 @@ +a = $a; } -} \ No newline at end of file +} diff --git a/test/TestAsset/ConstructorInjection/X.php b/test/TestAsset/ConstructorInjection/X.php index 53a7e87f..c4da4f44 100644 --- a/test/TestAsset/ConstructorInjection/X.php +++ b/test/TestAsset/ConstructorInjection/X.php @@ -11,4 +11,4 @@ public function __construct($one, $two) $this->one = $one; $this->two = $two; } -} \ No newline at end of file +} diff --git a/test/TestAsset/ConstructorInjection/Y.php b/test/TestAsset/ConstructorInjection/Y.php index 7c2cef45..244f1460 100644 --- a/test/TestAsset/ConstructorInjection/Y.php +++ b/test/TestAsset/ConstructorInjection/Y.php @@ -9,4 +9,4 @@ public function __construct(X $x) { $this->x = $x; } -} \ No newline at end of file +} diff --git a/test/TestAsset/ConstructorInjection/Z.php b/test/TestAsset/ConstructorInjection/Z.php index 2fb9d577..0314aa9f 100644 --- a/test/TestAsset/ConstructorInjection/Z.php +++ b/test/TestAsset/ConstructorInjection/Z.php @@ -9,4 +9,4 @@ public function __construct(Y $y) { $this->y = $y; } -} \ No newline at end of file +} diff --git a/test/TestAsset/InheritanceClasses/A.php b/test/TestAsset/InheritanceClasses/A.php new file mode 100644 index 00000000..00019451 --- /dev/null +++ b/test/TestAsset/InheritanceClasses/A.php @@ -0,0 +1,14 @@ +test = $test; + return $this; + } +} diff --git a/test/TestAsset/InheritanceClasses/B.php b/test/TestAsset/InheritanceClasses/B.php new file mode 100644 index 00000000..017d04d8 --- /dev/null +++ b/test/TestAsset/InheritanceClasses/B.php @@ -0,0 +1,7 @@ +a = $a; } -} \ No newline at end of file +} diff --git a/test/TestAsset/PreferredImplClasses/D.php b/test/TestAsset/PreferredImplClasses/D.php index c5993a27..c10d3013 100644 --- a/test/TestAsset/PreferredImplClasses/D.php +++ b/test/TestAsset/PreferredImplClasses/D.php @@ -5,4 +5,4 @@ class D extends C { -} \ No newline at end of file +} diff --git a/test/TestAsset/SetterInjection/A.php b/test/TestAsset/SetterInjection/A.php index 983ef1a6..8c4c3af9 100644 --- a/test/TestAsset/SetterInjection/A.php +++ b/test/TestAsset/SetterInjection/A.php @@ -4,4 +4,4 @@ class A { -} \ No newline at end of file +} diff --git a/test/TestAsset/SetterInjection/B.php b/test/TestAsset/SetterInjection/B.php index 2eb540d6..0b593602 100644 --- a/test/TestAsset/SetterInjection/B.php +++ b/test/TestAsset/SetterInjection/B.php @@ -9,4 +9,4 @@ public function setA(A $a) { $this->a = $a; } -} \ No newline at end of file +} diff --git a/test/TestAsset/SetterInjection/C.php b/test/TestAsset/SetterInjection/C.php index 9148dc3c..58a24b01 100644 --- a/test/TestAsset/SetterInjection/C.php +++ b/test/TestAsset/SetterInjection/C.php @@ -4,4 +4,4 @@ class C extends B { -} \ No newline at end of file +} diff --git a/test/TestAsset/SetterInjection/X.php b/test/TestAsset/SetterInjection/X.php index 25566ffd..0d0aa816 100644 --- a/test/TestAsset/SetterInjection/X.php +++ b/test/TestAsset/SetterInjection/X.php @@ -14,4 +14,4 @@ public function setTwo($two) { $this->two = $two; } -} \ No newline at end of file +} diff --git a/test/TestAsset/SetterInjection/Z.php b/test/TestAsset/SetterInjection/Z.php index eb35dfe8..87e69358 100644 --- a/test/TestAsset/SetterInjection/Z.php +++ b/test/TestAsset/SetterInjection/Z.php @@ -9,4 +9,4 @@ public function setY(Y $y) { $this->y = $y; } -} \ No newline at end of file +} diff --git a/test/TestAsset/SharedInstance/Lister.php b/test/TestAsset/SharedInstance/Lister.php new file mode 100644 index 00000000..3c61a441 --- /dev/null +++ b/test/TestAsset/SharedInstance/Lister.php @@ -0,0 +1,32 @@ +sharedLister = $lister; + } +} diff --git a/test/TestAsset/SharedInstance/Movie.php b/test/TestAsset/SharedInstance/Movie.php new file mode 100644 index 00000000..0964cf33 --- /dev/null +++ b/test/TestAsset/SharedInstance/Movie.php @@ -0,0 +1,32 @@ +lister = $lister; + } +} diff --git a/test/TestAsset/SharedInstance/SharedLister.php b/test/TestAsset/SharedInstance/SharedLister.php new file mode 100644 index 00000000..bbe6d017 --- /dev/null +++ b/test/TestAsset/SharedInstance/SharedLister.php @@ -0,0 +1,26 @@ +lister = $lister; + } +} diff --git a/test/_files/definition-array.php b/test/_files/definition-array.php index d0e58c08..7f724aed 100644 --- a/test/_files/definition-array.php +++ b/test/_files/definition-array.php @@ -64,4 +64,4 @@ array ( ), ), -); \ No newline at end of file +); diff --git a/test/_files/sample.ini b/test/_files/sample.ini index cb4d23ce..b1f49824 100644 --- a/test/_files/sample.ini +++ b/test/_files/sample.ini @@ -19,4 +19,16 @@ di.definitions.1.class = Zend\Di\Definition\BuilderDefinition di.definitions.1.My\DbAdapter.methods.__construct.username = NULL di.definitions.1.My\DbAdapter.methods.__construct.password = NULL di.definitions.1.My\Mapper.methods.__construct.dbAdapter = My\DbAdapter -di.definitions.1.My\Repository.methods.__construct.mapper = My\Mapper \ No newline at end of file +di.definitions.1.My\Repository.methods.__construct.mapper = My\Mapper + +[section-c] + +di.definition.runtime.xxx = zzz + +[section-d] + +di.definition.runtime.enabled = 0 + +[section-e] + +di.definition.runtime.use_annotations = 1 \ No newline at end of file diff --git a/test/_files/sample.php b/test/_files/sample.php new file mode 100644 index 00000000..5f6e79e6 --- /dev/null +++ b/test/_files/sample.php @@ -0,0 +1,10 @@ + array( + 'definition' => array( + 'compiler' => array( + __DIR__ . '/definition-array.php', + ), + ), + ), +); \ No newline at end of file