From bdf03f32299dcaea7c7a4836724fa27e60e3205e Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Tue, 7 May 2013 20:57:20 +0900 Subject: [PATCH 01/15] remove @package --- test/DiCompatibilityTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/test/DiCompatibilityTest.php b/test/DiCompatibilityTest.php index b11dd7e6..6431246c 100644 --- a/test/DiCompatibilityTest.php +++ b/test/DiCompatibilityTest.php @@ -5,7 +5,6 @@ * @link http://github.com/zendframework/zf2 for the canonical source repository * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License - * @package Zend_Di */ namespace ZendTest\Di; From 24c0a5cc30283a7cc4a95d643ffa21120b2fa666 Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Tue, 7 May 2013 22:16:21 +0900 Subject: [PATCH 02/15] update docblock --- test/DiCompatibilityTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/DiCompatibilityTest.php b/test/DiCompatibilityTest.php index 6431246c..e94fec96 100644 --- a/test/DiCompatibilityTest.php +++ b/test/DiCompatibilityTest.php @@ -22,7 +22,7 @@ class DiCompatibilityTest extends \PHPUnit_Framework_TestCase /** * * @dataProvider providesSimpleClasses - * @param type $class + * @param string $class */ public function testDiSimple($class) { @@ -39,7 +39,7 @@ public function testDiSimple($class) /** * provides known classes invokable without parameters * - * @return string + * @return array */ public function providesSimpleClasses() { From 3e95a909dc18aa0ad8de0dcc394e3358a1ff4c90 Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 07:12:20 +0900 Subject: [PATCH 03/15] Add test constructor's parameter is required --- test/DiCompatibilityTest.php | 66 ++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/test/DiCompatibilityTest.php b/test/DiCompatibilityTest.php index e94fec96..bc5634a7 100644 --- a/test/DiCompatibilityTest.php +++ b/test/DiCompatibilityTest.php @@ -15,8 +15,6 @@ use Zend\Di\Config; use Zend\Di\Definition; -use Zend\Form\Form; - class DiCompatibilityTest extends \PHPUnit_Framework_TestCase { /** @@ -48,8 +46,72 @@ public function providesSimpleClasses() array('Zend\EventManager\EventManager'), array('Zend\Filter\Null'), array('Zend\Form\Form'), + array('Zend\Log\Logger'), array('Zend\Stdlib\SplStack'), array('Zend\View\Model\ViewModel'), ); } + + /** + * + * error: Missing argument 1 for $class::__construct() + * @dataProvider providesClassWithConstructionParameters + * @expectedException PHPUnit_Framework_Error + * @param string $class + */ + public function testRaiseErrorMissingConstructorRequiredParameter($class) + { + $bareObject = new $class; + $this->assertInstanceOf($class, $bareObject, 'Test instantiate simple'); + } + + /** + * + * @dataProvider providesClassWithConstructionParameters + * @expectedException \Zend\Di\Exception\MissingPropertyException + * @param string $class + */ + public function testWillThrowExceptionMissingConstructorRequiredParameterWithDi($class) + { + $di = new Di(); + $diObject = $di->get($class); + $this->assertInstanceOf($class, $diObject, 'Test $di->get'); + } + + /** + * + * @dataProvider providesClassWithConstructionParameters + * @param string $class + */ + public function testCanCreateInstanceWithConstructorRequiredParameter($class, $args) + { + $reflection = new \ReflectionClass($class); + $bareObject = $reflection->newInstanceArgs($args); + $this->assertInstanceOf($class, $bareObject, 'Test instantiate with constructor required parameters'); + } + + /** + * @dataProvider providesClassWithConstructionParameters + * @param string $class + */ + public function testCanCreateInstanceWithConstructorRequiredParameterWithDi($class, $args) + { + $di = new Di(); + $diObject = $di->get($class, $args); + $this->assertInstanceOf($class, $diObject, 'Test $di->get with constructor required paramters'); + } + + public function providesClassWithConstructionParameters() + { + $serviceManager = new \Zend\ServiceManager\ServiceManager; + $serviceManager->setService('EventManager', new \Zend\EventManager\EventManager); + $serviceManager->setService('Request', new \StdClass); + $serviceManager->setService('Response', new \StdClass); + + return array( + array('Zend\Config\Config', array('array' => array())), + array('Zend\Db\Adapter\Adapter', array('driver' => array('driver' => 'Pdo_Sqlite'))), + array('Zend\Mvc\Application', array('configuration' => array(), 'serviceManager' => $serviceManager)), + ); + } } From 2065899bd5678093137dcb3d00128d737bc286e7 Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 10:13:55 +0900 Subject: [PATCH 04/15] Change Di::resolveMethodParameter, add resolve type EAGER --- src/Definition/Builder/InjectionMethod.php | 36 ++++++- src/Definition/ClassDefinition.php | 46 ++++++++- src/Definition/RuntimeDefinition.php | 11 ++- src/Di.php | 107 +++++++++++++++++---- 4 files changed, 171 insertions(+), 29 deletions(-) diff --git a/src/Definition/Builder/InjectionMethod.php b/src/Definition/Builder/InjectionMethod.php index a19cb617..d785ad01 100644 --- a/src/Definition/Builder/InjectionMethod.php +++ b/src/Definition/Builder/InjectionMethod.php @@ -9,6 +9,8 @@ namespace Zend\Di\Definition\Builder; +use Zend\Di\Di; + /** * Definitions for an injection endpoint method */ @@ -52,10 +54,42 @@ public function getName() */ public function addParameter($name, $class = null, $isRequired = null, $default = null) { + if (is_bool($isRequired)) { + $methodRequirementType = $isRequired ? Di::METHOD_IS_REQUIRED : Di::METHOD_IS_OPTIONAL; + } + + if (null === $isRequired) { + $methodRequirementType = Di::METHOD_IS_REQUIRED; + } + + if (is_int($isRequired)) { + $methodRequirementType = $isRequired; + } + + if (is_string($isRequired)) { + switch (strtolower($isRequired)) { + case "require": + case "required": + $methodRequirementType = Di::METHOD_IS_REQUIRED; + break; + case "aware": + $methodRequirementType = Di::METHOD_IS_AWARE; + break; + case "optional": + $methodRequirementType = Di::METHOD_IS_OPTIONAL; + break; + case "constructor": + $methodRequirementType = Di::MEHTOD_IS_CONSTRUCTOR; + break; + case "instantiator": + $methodRequirementType = Di::METHOD_IS_INSTANTIATOR; + break; + } + } $this->parameters[] = array( $name, $class, - ($isRequired == null) ? true : false, + $methodRequirementType, $default, ); diff --git a/src/Definition/ClassDefinition.php b/src/Definition/ClassDefinition.php index e9e929ed..4e435d53 100644 --- a/src/Definition/ClassDefinition.php +++ b/src/Definition/ClassDefinition.php @@ -9,6 +9,7 @@ namespace Zend\Di\Definition; +use Zend\Di\Di; /** * Class definitions for a single class */ @@ -71,15 +72,48 @@ public function setSupertypes(array $supertypes) /** * @param string $method - * @param bool|null $isRequired + * @param mixed|bool|null $isRequired * @return self */ public function addMethod($method, $isRequired = null) { if ($isRequired === null) { - $isRequired = ($method === '__construct') ? true : false; + if ($method === '__construct') { + $methodRequirementType = Di::METHOD_IS_CONSTRUCTOR; + } + $methodRequirementType = Di::METHOD_IS_OPTIONAL; } - $this->methods[$method] = (bool) $isRequired; + + if (is_bool($isRequired)) { + $methodRequirementType = $isRequired ? Di::METHOD_IS_REQUIRED : Di::METHOD_IS_OPTIONAL; + } + + if (is_int($isRequired)) { + $methodRequirementType = $isRequired; + } + + if (is_string($isRequired)) { + switch (strtolower($isRequired)) { + case "require": + case "required": + $methodRequirementType = Di::METHOD_IS_REQUIRED; + break; + case "aware": + $methodRequirementType = Di::METHOD_IS_AWARE; + break; + case "optional": + $methodRequirementType = Di::METHOD_IS_OPTIONAL; + break; + case "constructor": + $methodRequirementType = Di::MEHTOD_IS_CONSTRUCTOR; + break; + case "instantiator": + $methodRequirementType = Di::METHOD_IS_INSTANTIATOR; + break; + } + } + + $this->methods[$method] = $methodRequirementType; return $this; } @@ -93,7 +127,11 @@ public function addMethod($method, $isRequired = null) public function addMethodParameter($method, $parameterName, array $parameterInfo) { if (!array_key_exists($method, $this->methods)) { - $this->methods[$method] = ($method === '__construct') ? true : false; + if ($method === '__construct') { + $this->methods[$method] = Di::METHOD_IS_CONSTRUCTOR; + } else { + $this->methods[$method] = Di::METHOD_IS_OPTIONAL; + } } if (!array_key_exists($method, $this->methodParameters)) { diff --git a/src/Definition/RuntimeDefinition.php b/src/Definition/RuntimeDefinition.php index 011313ed..122eaa5e 100644 --- a/src/Definition/RuntimeDefinition.php +++ b/src/Definition/RuntimeDefinition.php @@ -12,7 +12,7 @@ use Zend\Code\Annotation\AnnotationCollection; use Zend\Code\Reflection; use Zend\Di\Definition\Annotation; - +use Zend\Di\Di; /** * Class definitions based on runtime reflection */ @@ -248,7 +248,7 @@ protected function processClass($class) } if ($rClass->hasMethod('__construct')) { - $def['methods']['__construct'] = true; // required + $def['methods']['__construct'] = Di::METHOD_IS_CONSTRUCTOR; // required $this->processParams($def, $rClass, $rClass->getMethod('__construct')); } @@ -266,7 +266,8 @@ protected function processClass($class) if (($annotations instanceof AnnotationCollection) && $annotations->hasAnnotation('Zend\Di\Definition\Annotation\Inject')) { - $def['methods'][$methodName] = true; + // use '@inject' and search for parameters + $def['methods'][$methodName] = Di::METHOD_IS_EAGER; $this->processParams($def, $rClass, $rMethod); continue; } @@ -278,7 +279,7 @@ protected function processClass($class) foreach ($methodPatterns as $methodInjectorPattern) { preg_match($methodInjectorPattern, $methodName, $matches); if ($matches) { - $def['methods'][$methodName] = false; // check ot see if this is required? + $def['methods'][$methodName] = Di::METHOD_IS_OPTIONAL; // check ot see if this is required? $this->processParams($def, $rClass, $rMethod); continue 2; } @@ -304,7 +305,7 @@ protected function processClass($class) // constructor not allowed in interfaces continue; } - $def['methods'][$rMethod->getName()] = true; + $def['methods'][$rMethod->getName()] = Di::METHOD_IS_AWARE; $this->processParams($def, $rClass, $rMethod); } continue 2; diff --git a/src/Di.php b/src/Di.php index b2404b27..d8025160 100644 --- a/src/Di.php +++ b/src/Di.php @@ -11,6 +11,7 @@ use Closure; use ReflectionClass; +use Zend\Di\Exception; /** * Dependency injector that can generate instances using class definitions and configured instance parameters @@ -46,6 +47,50 @@ class Di implements DependencyInjectionInterface */ protected $references = array(); + /** + * Resolve method policy + * + * EAGER: explore type preference or go through + */ + const RESOLVE_EAGER = 1; + + /** + * Resolve method policy + * + * STRICT: explore type preference or throw exception + */ + const RESOLVE_STRICT = 2; + + /** + * + * use only specified parameters + */ + const METHOD_IS_OPTIONAL = 0; + + /** + * + * resolve mode RESOLVE_EAGER + */ + const METHOD_IS_AWARE = 1; + + /** + * + * resolve mode RESOLVE_EAGER | RESOLVE_STRICT + */ + const METHOD_IS_CONSTRUCTOR = 3; + + /** + * + * resolve mode RESOLVE_EAGER | RESOLVE_STRICT + */ + const METHOD_IS_INSTANTIATOR = 3; + + /** + * + * resolve mode RESOLVE_EAGER | RESOLVE_STRICT + */ + const METHOD_IS_REQUIRED = 3; + /** * Constructor * @@ -308,9 +353,9 @@ protected function handleInjectDependencies($instance, $injectionMethods, $param if ($injectionMethods) { foreach ($injectionMethods as $type => $typeInjectionMethods) { - foreach ($typeInjectionMethods as $typeInjectionMethod => $methodIsRequired) { + foreach ($typeInjectionMethods as $typeInjectionMethod => $methodRequirementType) { if (!isset($calledMethods[$typeInjectionMethod])) { - if ($this->resolveAndCallInjectionMethodForInstance($instance, $typeInjectionMethod, $params, $instanceAlias, $methodIsRequired, $type)) { + if ($this->resolveAndCallInjectionMethodForInstance($instance, $typeInjectionMethod, $params, $instanceAlias, $methodRequirementType, $type)) { $calledMethods[$typeInjectionMethod] = true; } } @@ -346,14 +391,14 @@ protected function handleInjectDependencies($instance, $injectionMethods, $param foreach ($objectsToInject as $objectToInject) { $calledMethods = array('__construct' => true); foreach ($injectionMethods as $type => $typeInjectionMethods) { - foreach ($typeInjectionMethods as $typeInjectionMethod => $methodIsRequired) { + foreach ($typeInjectionMethods as $typeInjectionMethod => $methodRequirementType) { if (!isset($calledMethods[$typeInjectionMethod])) { $methodParams = $definitions->getMethodParameters($type, $typeInjectionMethod); if ($methodParams) { foreach ($methodParams as $methodParam) { $objectToInjectClass = $this->getClass($objectToInject); if ($objectToInjectClass == $methodParam[1] || self::isSubclassOf($objectToInjectClass, $methodParam[1])) { - if ($this->resolveAndCallInjectionMethodForInstance($instance, $typeInjectionMethod, array($methodParam[0] => $objectToInject), $instanceAlias, true, $type)) { + if ($this->resolveAndCallInjectionMethodForInstance($instance, $typeInjectionMethod, array($methodParam[0] => $objectToInject), $instanceAlias, self::METHOD_IS_REQUIRED, $type)) { $calledMethods[$typeInjectionMethod] = true; } continue 3; @@ -367,7 +412,7 @@ protected function handleInjectDependencies($instance, $injectionMethods, $param } if ($methodsToCall) { foreach ($methodsToCall as $methodInfo) { - $this->resolveAndCallInjectionMethodForInstance($instance, $methodInfo['method'], $methodInfo['args'], $instanceAlias, true, $instanceClass); + $this->resolveAndCallInjectionMethodForInstance($instance, $methodInfo['method'], $methodInfo['args'], $instanceAlias, self::METHOD_IS_REQUIRED, $instanceClass); } } } @@ -391,7 +436,7 @@ protected function createInstanceViaConstructor($class, $params, $alias = null) { $callParameters = array(); if ($this->definitions->hasMethod($class, '__construct')) { - $callParameters = $this->resolveMethodParameters($class, '__construct', $params, $alias, true, true); + $callParameters = $this->resolveMethodParameters($class, '__construct', $params, $alias, self::METHOD_IS_CONSTRUCTOR, true); } // Hack to avoid Reflection in most common use cases @@ -438,7 +483,7 @@ protected function createInstanceViaCallback($callback, $params, $alias) $callParameters = array(); if ($this->definitions->hasMethod($class, $method)) { - $callParameters = $this->resolveMethodParameters($class, $method, $params, $alias, true, true); + $callParameters = $this->resolveMethodParameters($class, $method, $params, $alias, self::METHOD_IS_INSTANTIATOR, true); } return call_user_func_array($callback, $callParameters); @@ -452,14 +497,14 @@ protected function createInstanceViaCallback($callback, $params, $alias) * @param string $method * @param array $params * @param string $alias - * @param bool $methodIsRequired + * @param bool $methodRequirementType * @param string|null $methodClass * @return bool */ - protected function resolveAndCallInjectionMethodForInstance($instance, $method, $params, $alias, $methodIsRequired, $methodClass = null) + protected function resolveAndCallInjectionMethodForInstance($instance, $method, $params, $alias, $methodRequirementType, $methodClass = null) { $methodClass = ($methodClass) ?: $this->getClass($instance); - $callParameters = $this->resolveMethodParameters($methodClass, $method, $params, $alias, $methodIsRequired); + $callParameters = $this->resolveMethodParameters($methodClass, $method, $params, $alias, $methodRequirementType); if ($callParameters == false) { return false; } @@ -479,14 +524,24 @@ protected function resolveAndCallInjectionMethodForInstance($instance, $method, * @param string $method * @param array $callTimeUserParams * @param string $alias - * @param bool $methodIsRequired + * @param int|bolean $methodRequirementType * @param bool $isInstantiator * @throws Exception\MissingPropertyException * @throws Exception\CircularDependencyException * @return array */ - protected function resolveMethodParameters($class, $method, array $callTimeUserParams, $alias, $methodIsRequired, $isInstantiator = false) + protected function resolveMethodParameters($class, $method, array $callTimeUserParams, $alias, $methodRequirementType, $isInstantiator = false) { + //BC compatibility + if (is_bool($methodRequirementType)) { + if ($isInstantiator) { + $methodRequirementType = Di::METHOD_IS_INSTANTIATOR; + } elseif ($methodRequirementType) { + $methodRequirementType = Di::METHOD_IS_REQUIRED; + } else { + $methodRequirementType = Di::METHOD_IS_OPTIONAL; + } + } // parameters for this method, in proper order, to be returned $resolvedParams = array(); @@ -662,7 +717,7 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP $computedParams['optional'][$fqParamPos] = true; } - if ($type && $isRequired && $methodIsRequired) { + if ($type && $isRequired && ($methodRequirementType & self::RESOLVE_EAGER)) { $computedParams['required'][$fqParamPos] = array($type, $type); } @@ -686,15 +741,29 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP array_push($this->currentDependencies, $class); $dConfig = $this->instanceManager->getConfig($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); + try { + if ($dConfig['shared'] === false) { + $resolvedParams[$index] = $this->newInstance($computedParams['required'][$fqParamPos][0], $callTimeUserParams, false); + } else { + $resolvedParams[$index] = $this->get($computedParams['required'][$fqParamPos][0], $callTimeUserParams); + } + } catch (Exception\RuntimeException $e) { + if ($methodRequirementType & self::RESOLVE_STRICT) { + // if this item was marked strict, + // plus it cannot be resolve, and no value exist, bail out + throw new Exception\MissingPropertyException(sprintf( + 'Missing %s for parameter ' . $name . ' for ' . $class . '::' . $method, + (($value[0] === null) ? 'value' : 'instance/object' ) + ), + $e->getCode(), + $e); + } else { + return false; + } } - array_pop($this->currentDependencies); } elseif (!array_key_exists($fqParamPos, $computedParams['optional'])) { - if ($methodIsRequired) { + if ($methodRequirementType & self::RESOLVE_STRICT) { // if this item was not marked as optional, // plus it cannot be resolve, and no value exist, bail out throw new Exception\MissingPropertyException(sprintf( From bb37b6926c4498bd6b0d72446a85e690b57eb6c0 Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 11:52:47 +0900 Subject: [PATCH 05/15] Add Builder\InjectionMethod::detectMethodRequirement --- src/Definition/Builder/InjectionMethod.php | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/Definition/Builder/InjectionMethod.php b/src/Definition/Builder/InjectionMethod.php index d785ad01..deba8821 100644 --- a/src/Definition/Builder/InjectionMethod.php +++ b/src/Definition/Builder/InjectionMethod.php @@ -103,4 +103,48 @@ public function getParameters() { return $this->parameters; } + + /** + * + * @param mixed $requirement + * @return int + */ + public static function detectMethodRequirement($requirement) + { + if (is_bool($requirement)) { + return $requirement ? Di::METHOD_IS_REQUIRED : Di::METHOD_IS_OPTIONAL; + } + + if (null === $requirement) { + //This is mismatch to ClassDefinition::addMethod is it ok ? is optional? + return Di::METHOD_IS_REQUIRED; + } + + if (is_int($requirement)) { + return $requirement; + } + + if (is_string($requirement)) { + switch (strtolower($requirement)) { + default: + case "require": + case "required": + return Di::METHOD_IS_REQUIRED; + break; + case "aware": + return Di::METHOD_IS_AWARE; + break; + case "optional": + return Di::METHOD_IS_OPTIONAL; + break; + case "constructor": + return Di::MEHTOD_IS_CONSTRUCTOR; + break; + case "instantiator": + return Di::METHOD_IS_INSTANTIATOR; + break; + } + } + return 0; + } } From d876372ebcfe0a64adb38443de981a91d65b03ac Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 11:54:35 +0900 Subject: [PATCH 06/15] Update using InjectionMethod::detectMethodRequirement --- src/Definition/ArrayDefinition.php | 10 +++++++ src/Definition/Builder/InjectionMethod.php | 34 +-------------------- src/Definition/ClassDefinition.php | 35 ++++------------------ 3 files changed, 16 insertions(+), 63 deletions(-) diff --git a/src/Definition/ArrayDefinition.php b/src/Definition/ArrayDefinition.php index b1cd14b8..908554fb 100644 --- a/src/Definition/ArrayDefinition.php +++ b/src/Definition/ArrayDefinition.php @@ -9,6 +9,7 @@ namespace Zend\Di\Definition; +use Zend\Di\Definition\Builder\InjectionMethod; /** * Class definitions based on a given array */ @@ -28,6 +29,15 @@ public function __construct(array $dataArray) // force lower names $dataArray[$class] = array_change_key_case($dataArray[$class], CASE_LOWER); } + foreach ($dataArray as $class => $definition) { + if (isset($definition['methods']) && is_array($definition['methods'])) { + foreach ($definition['methods'] as $type => $requirement) { + if (!is_int($requirement)) { + $dataArray[$class]['methods'][$type] = InjectionMethod::detectMethodRequirement($requirement); + } + } + } + } $this->dataArray = $dataArray; } diff --git a/src/Definition/Builder/InjectionMethod.php b/src/Definition/Builder/InjectionMethod.php index deba8821..ff2b3444 100644 --- a/src/Definition/Builder/InjectionMethod.php +++ b/src/Definition/Builder/InjectionMethod.php @@ -54,42 +54,10 @@ public function getName() */ public function addParameter($name, $class = null, $isRequired = null, $default = null) { - if (is_bool($isRequired)) { - $methodRequirementType = $isRequired ? Di::METHOD_IS_REQUIRED : Di::METHOD_IS_OPTIONAL; - } - - if (null === $isRequired) { - $methodRequirementType = Di::METHOD_IS_REQUIRED; - } - - if (is_int($isRequired)) { - $methodRequirementType = $isRequired; - } - - if (is_string($isRequired)) { - switch (strtolower($isRequired)) { - case "require": - case "required": - $methodRequirementType = Di::METHOD_IS_REQUIRED; - break; - case "aware": - $methodRequirementType = Di::METHOD_IS_AWARE; - break; - case "optional": - $methodRequirementType = Di::METHOD_IS_OPTIONAL; - break; - case "constructor": - $methodRequirementType = Di::MEHTOD_IS_CONSTRUCTOR; - break; - case "instantiator": - $methodRequirementType = Di::METHOD_IS_INSTANTIATOR; - break; - } - } $this->parameters[] = array( $name, $class, - $methodRequirementType, + self::detectMethodRequirement($isRequired), $default, ); diff --git a/src/Definition/ClassDefinition.php b/src/Definition/ClassDefinition.php index 4e435d53..9d2d37a1 100644 --- a/src/Definition/ClassDefinition.php +++ b/src/Definition/ClassDefinition.php @@ -10,6 +10,8 @@ namespace Zend\Di\Definition; use Zend\Di\Di; +use Zend\Di\Definition\Builder\InjectionMethod; + /** * Class definitions for a single class */ @@ -77,40 +79,13 @@ public function setSupertypes(array $supertypes) */ public function addMethod($method, $isRequired = null) { - if ($isRequired === null) { + if ($isRequired === null) { if ($method === '__construct') { $methodRequirementType = Di::METHOD_IS_CONSTRUCTOR; } $methodRequirementType = Di::METHOD_IS_OPTIONAL; - } - - if (is_bool($isRequired)) { - $methodRequirementType = $isRequired ? Di::METHOD_IS_REQUIRED : Di::METHOD_IS_OPTIONAL; - } - - if (is_int($isRequired)) { - $methodRequirementType = $isRequired; - } - - if (is_string($isRequired)) { - switch (strtolower($isRequired)) { - case "require": - case "required": - $methodRequirementType = Di::METHOD_IS_REQUIRED; - break; - case "aware": - $methodRequirementType = Di::METHOD_IS_AWARE; - break; - case "optional": - $methodRequirementType = Di::METHOD_IS_OPTIONAL; - break; - case "constructor": - $methodRequirementType = Di::MEHTOD_IS_CONSTRUCTOR; - break; - case "instantiator": - $methodRequirementType = Di::METHOD_IS_INSTANTIATOR; - break; - } + } else { + $methodRequirementType = InjectionMethod::detectMethodRequirement($isRequired); } $this->methods[$method] = $methodRequirementType; From 1ee40f6897f99652a6ce239598f63637b90b776b Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 12:15:29 +0900 Subject: [PATCH 07/15] Add Di::METHOD_IS_EAGER --- src/Di.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Di.php b/src/Di.php index d8025160..67186551 100644 --- a/src/Di.php +++ b/src/Di.php @@ -91,6 +91,12 @@ class Di implements DependencyInjectionInterface */ const METHOD_IS_REQUIRED = 3; + /** + * + * resolve mode RESOLVE_EAGER + */ + const METHOD_IS_EAGER = 1; + /** * Constructor * From ddc0154be31e972f1c673181278ec1ba0f49c258 Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 12:17:33 +0900 Subject: [PATCH 08/15] Add METHOD_IS_EAGER to Builder\InjectionMethod::detectMethodRequirement --- src/Definition/Builder/InjectionMethod.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Definition/Builder/InjectionMethod.php b/src/Definition/Builder/InjectionMethod.php index ff2b3444..41e6f242 100644 --- a/src/Definition/Builder/InjectionMethod.php +++ b/src/Definition/Builder/InjectionMethod.php @@ -111,6 +111,9 @@ public static function detectMethodRequirement($requirement) case "instantiator": return Di::METHOD_IS_INSTANTIATOR; break; + case "eager": + return Di::METHOD_IS_EAGER; + break; } } return 0; From a8580855d01386274deaaef6b8be427dbb4d0a2d Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 12:46:31 +0900 Subject: [PATCH 09/15] Rename $computedParams['required'] to retrieval --- src/Di.php | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Di.php b/src/Di.php index 67186551..79472ddc 100644 --- a/src/Di.php +++ b/src/Di.php @@ -538,7 +538,7 @@ protected function resolveAndCallInjectionMethodForInstance($instance, $method, */ protected function resolveMethodParameters($class, $method, array $callTimeUserParams, $alias, $methodRequirementType, $isInstantiator = false) { - //BC compatibility + //for BC if (is_bool($methodRequirementType)) { if ($isInstantiator) { $methodRequirementType = Di::METHOD_IS_INSTANTIATOR; @@ -556,9 +556,9 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP // computed parameters array $computedParams = array( - 'value' => array(), - 'required' => array(), - 'optional' => array() + 'value' => array(), + 'retrieval' => array(), + 'optional' => array() ); // retrieve instance configurations for all contexts @@ -614,13 +614,13 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP if ($type !== false && is_string($callTimeCurValue)) { if ($this->instanceManager->hasAlias($callTimeCurValue)) { // was an alias provided? - $computedParams['required'][$fqParamPos] = array( + $computedParams['retrieval'][$fqParamPos] = array( $callTimeUserParams[$name], $this->instanceManager->getClassFromAlias($callTimeCurValue) ); } elseif ($this->definitions->hasClass($callTimeUserParams[$name])) { // was a known class provided? - $computedParams['required'][$fqParamPos] = array( + $computedParams['retrieval'][$fqParamPos] = array( $callTimeCurValue, $callTimeCurValue ); @@ -659,13 +659,13 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP $computedParams['value'][$fqParamPos] = $iConfigCurValue; } elseif (is_string($iConfigCurValue) && isset($aliases[$iConfigCurValue])) { - $computedParams['required'][$fqParamPos] = array( + $computedParams['retrieval'][$fqParamPos] = array( $iConfig[$thisIndex]['parameters'][$name], $this->instanceManager->getClassFromAlias($iConfigCurValue) ); } elseif (is_string($iConfigCurValue) && $this->definitions->hasClass($iConfigCurValue)) { - $computedParams['required'][$fqParamPos] = array( + $computedParams['retrieval'][$fqParamPos] = array( $iConfigCurValue, $iConfigCurValue ); @@ -696,7 +696,7 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; if ($pInstanceClass === $type || self::isSubclassOf($pInstanceClass, $type)) { - $computedParams['required'][$fqParamPos] = array($pInstance, $pInstanceClass); + $computedParams['retrieval'][$fqParamPos] = array($pInstance, $pInstanceClass); continue 2; } } @@ -713,7 +713,7 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; if ($pInstanceClass === $type || self::isSubclassOf($pInstanceClass, $type)) { - $computedParams['required'][$fqParamPos] = array($pInstance, $pInstanceClass); + $computedParams['retrieval'][$fqParamPos] = array($pInstance, $pInstanceClass); continue 2; } } @@ -724,7 +724,7 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP } if ($type && $isRequired && ($methodRequirementType & self::RESOLVE_EAGER)) { - $computedParams['required'][$fqParamPos] = array($type, $type); + $computedParams['retrieval'][$fqParamPos] = array($type, $type); } } @@ -736,22 +736,22 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP if (isset($computedParams['value'][$fqParamPos])) { // if there is a value supplied, use it $resolvedParams[$index] = $computedParams['value'][$fqParamPos]; - } elseif (isset($computedParams['required'][$fqParamPos])) { + } elseif (isset($computedParams['retrieval'][$fqParamPos])) { // detect circular dependencies! (they can only happen in instantiators) - if ($isInstantiator && in_array($computedParams['required'][$fqParamPos][1], $this->currentDependencies)) { + if ($isInstantiator && in_array($computedParams['retrieval'][$fqParamPos][1], $this->currentDependencies)) { throw new Exception\CircularDependencyException( "Circular dependency detected: $class depends on {$value[1]} and viceversa" ); } array_push($this->currentDependencies, $class); - $dConfig = $this->instanceManager->getConfig($computedParams['required'][$fqParamPos][0]); + $dConfig = $this->instanceManager->getConfig($computedParams['retrieval'][$fqParamPos][0]); try { if ($dConfig['shared'] === false) { - $resolvedParams[$index] = $this->newInstance($computedParams['required'][$fqParamPos][0], $callTimeUserParams, false); + $resolvedParams[$index] = $this->newInstance($computedParams['retrieval'][$fqParamPos][0], $callTimeUserParams, false); } else { - $resolvedParams[$index] = $this->get($computedParams['required'][$fqParamPos][0], $callTimeUserParams); + $resolvedParams[$index] = $this->get($computedParams['retrieval'][$fqParamPos][0], $callTimeUserParams); } } catch (Exception\RuntimeException $e) { if ($methodRequirementType & self::RESOLVE_STRICT) { From c8c08064f4a598477fc1594343ee0a1f3a8069cb Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 12:54:15 +0900 Subject: [PATCH 10/15] Add finalize before bailout --- src/Di.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Di.php b/src/Di.php index 79472ddc..10403ad4 100644 --- a/src/Di.php +++ b/src/Di.php @@ -755,6 +755,8 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP } } catch (Exception\RuntimeException $e) { if ($methodRequirementType & self::RESOLVE_STRICT) { + //finally ( be aware to do at the end of flow) + array_pop($this->currentDependencies); // if this item was marked strict, // plus it cannot be resolve, and no value exist, bail out throw new Exception\MissingPropertyException(sprintf( @@ -764,6 +766,8 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP $e->getCode(), $e); } else { + //finally ( be aware to do at the end of flow) + array_pop($this->currentDependencies); return false; } } From 9b49280d4c4b68c918dd7b247f7f60d2515e217d Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 15:09:47 +0900 Subject: [PATCH 11/15] Add test no injection to a bare setter with TypePreference Be aware of BC break for an enhancement of di capability --- test/DiTest.php | 37 ++++++++++++++++++- .../PreferredImplClasses/AAwareInterface.php | 15 ++++++++ test/TestAsset/PreferredImplClasses/E.php | 19 ++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 test/TestAsset/PreferredImplClasses/AAwareInterface.php create mode 100644 test/TestAsset/PreferredImplClasses/E.php diff --git a/test/DiTest.php b/test/DiTest.php index cf019f5a..127142f6 100644 --- a/test/DiTest.php +++ b/test/DiTest.php @@ -456,7 +456,13 @@ public function testNewInstanceThrowsExceptionWhenEnteringInMiddleOfCircularDepe */ public function testNewInstanceWillUsePreferredClassForInterfaceHints() { - $di = new Di(); + $definitionList = new DefinitionList(array( + $classdef = new Definition\ClassDefinition('ZendTest\Di\TestAsset\PreferredImplClasses\C'), + new Definition\RuntimeDefinition() + )); + $classdef->addMethod('setA', Di::METHOD_IS_EAGER); + $di = new Di($definitionList); + $di->instanceManager()->addTypePreference( 'ZendTest\Di\TestAsset\PreferredImplClasses\A', 'ZendTest\Di\TestAsset\PreferredImplClasses\BofA' @@ -469,6 +475,35 @@ public function testNewInstanceWillUsePreferredClassForInterfaceHints() $this->assertSame($a, $d->a); } + public function testMatchPreferredClassWithAwareInterface() + { + $di = new Di(); + + $di->instanceManager()->addTypePreference( + 'ZendTest\Di\TestAsset\PreferredImplClasses\A', + 'ZendTest\Di\TestAsset\PreferredImplClasses\BofA' + ); + + $e = $di->get('ZendTest\Di\TestAsset\PreferredImplClasses\E'); + $this->assertInstanceOf('ZendTest\Di\TestAsset\PreferredImplClasses\BofA', $e->a); + } + + public function testWillNotUsePreferredClassForInterfaceHints() + { + $di = new Di(); + + $di->instanceManager()->addTypePreference( + 'ZendTest\Di\TestAsset\PreferredImplClasses\A', + 'ZendTest\Di\TestAsset\PreferredImplClasses\BofA' + ); + + $c = $di->get('ZendTest\Di\TestAsset\PreferredImplClasses\C'); + $a = $c->a; + $this->assertNull($a); + $d = $di->get('ZendTest\Di\TestAsset\PreferredImplClasses\D'); + $this->assertNull($d->a); + } + public function testInjectionInstancesCanBeInjectedMultipleTimes() { $definitionList = new DefinitionList(array( diff --git a/test/TestAsset/PreferredImplClasses/AAwareInterface.php b/test/TestAsset/PreferredImplClasses/AAwareInterface.php new file mode 100644 index 00000000..5afed28a --- /dev/null +++ b/test/TestAsset/PreferredImplClasses/AAwareInterface.php @@ -0,0 +1,15 @@ +a = $a; + } +} From 55ce256813270ad805c33d4d7b7af54ed56b0cf4 Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 15:15:40 +0900 Subject: [PATCH 12/15] Compose EAGER load spec & TypePreferences --- src/Di.php | 58 +++++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/Di.php b/src/Di.php index 10403ad4..64eb8623 100644 --- a/src/Di.php +++ b/src/Di.php @@ -686,39 +686,43 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP // PRIORITY 6 - globally preferred implementations // next consult alias level preferred instances - if ($alias && $this->instanceManager->hasTypePreferences($alias)) { - $pInstances = $this->instanceManager->getTypePreferences($alias); - foreach ($pInstances as $pInstance) { - if (is_object($pInstance)) { - $computedParams['value'][$fqParamPos] = $pInstance; - continue 2; - } - $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? - $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; - if ($pInstanceClass === $type || self::isSubclassOf($pInstanceClass, $type)) { - $computedParams['retrieval'][$fqParamPos] = array($pInstance, $pInstanceClass); - continue 2; + // RESOLVE_EAGER wants to inject the cross-cutting concerns. + // If you want to retrieve an instance from TypePreferences, + // use AwareInterface or specify the method requirement option METHOD_IS_EAGER at ClassDefinition + if ($methodRequirementType & self::RESOLVE_EAGER) { + if ($alias && $this->instanceManager->hasTypePreferences($alias)) { + $pInstances = $this->instanceManager->getTypePreferences($alias); + foreach ($pInstances as $pInstance) { + if (is_object($pInstance)) { + $computedParams['value'][$fqParamPos] = $pInstance; + continue 2; + } + $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? + $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; + if ($pInstanceClass === $type || self::isSubclassOf($pInstanceClass, $type)) { + $computedParams['retrieval'][$fqParamPos] = array($pInstance, $pInstanceClass); + continue 2; + } } } - } - // next consult class level preferred instances - if ($type && $this->instanceManager->hasTypePreferences($type)) { - $pInstances = $this->instanceManager->getTypePreferences($type); - foreach ($pInstances as $pInstance) { - if (is_object($pInstance)) { - $computedParams['value'][$fqParamPos] = $pInstance; - continue 2; - } - $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? - $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; - if ($pInstanceClass === $type || self::isSubclassOf($pInstanceClass, $type)) { - $computedParams['retrieval'][$fqParamPos] = array($pInstance, $pInstanceClass); - continue 2; + // next consult class level preferred instances + if ($type && $this->instanceManager->hasTypePreferences($type)) { + $pInstances = $this->instanceManager->getTypePreferences($type); + foreach ($pInstances as $pInstance) { + if (is_object($pInstance)) { + $computedParams['value'][$fqParamPos] = $pInstance; + continue 2; + } + $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? + $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; + if ($pInstanceClass === $type || self::isSubclassOf($pInstanceClass, $type)) { + $computedParams['retrieval'][$fqParamPos] = array($pInstance, $pInstanceClass); + continue 2; + } } } } - if (!$isRequired) { $computedParams['optional'][$fqParamPos] = true; } From 4a93d96cb8fe8a0fb04d2fac7a8bf7f5197174c4 Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 23:35:01 +0900 Subject: [PATCH 13/15] Update catch Exceptions --- src/Di.php | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/Di.php b/src/Di.php index 64eb8623..a2e36f1a 100644 --- a/src/Di.php +++ b/src/Di.php @@ -11,8 +11,8 @@ use Closure; use ReflectionClass; -use Zend\Di\Exception; - +use Zend\Di\Exception\RuntimeException as DiRuntimeException; +use Zend\ServiceManager\Exception\ServiceNotCreatedException; /** * Dependency injector that can generate instances using class definitions and configured instance parameters */ @@ -757,7 +757,28 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP } else { $resolvedParams[$index] = $this->get($computedParams['retrieval'][$fqParamPos][0], $callTimeUserParams); } - } catch (Exception\RuntimeException $e) { + } catch (ServiceNotCreatedException $e) { + //Zend\ServiceManager\Exception\ServiceNotCreatedException + //Zend\Di\Exception\RuntimeException + if ($methodRequirementType & self::RESOLVE_STRICT) { + //finally ( be aware to do at the end of flow) + array_pop($this->currentDependencies); + // if this item was marked strict, + // plus it cannot be resolve, and no value exist, bail out + throw new Exception\MissingPropertyException(sprintf( + 'Missing %s for parameter ' . $name . ' for ' . $class . '::' . $method, + (($value[0] === null) ? 'value' : 'instance/object' ) + ), + $e->getCode(), + $e); + } else { + //finally ( be aware to do at the end of flow) + array_pop($this->currentDependencies); + return false; + } + } catch (DiRuntimeException $e) { + //Zend\ServiceManager\Exception\ServiceNotCreatedException + //Zend\Di\Exception\RuntimeException if ($methodRequirementType & self::RESOLVE_STRICT) { //finally ( be aware to do at the end of flow) array_pop($this->currentDependencies); From 80a796f58a02e54071cd3cbee13927489dc1c518 Mon Sep 17 00:00:00 2001 From: Tomoaki Kosugi Date: Thu, 9 May 2013 23:35:01 +0900 Subject: [PATCH 14/15] Update catch Exceptions --- src/Di.php | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Di.php b/src/Di.php index 64eb8623..eb8358a4 100644 --- a/src/Di.php +++ b/src/Di.php @@ -11,8 +11,8 @@ use Closure; use ReflectionClass; -use Zend\Di\Exception; - +use Zend\Di\Exception\RuntimeException as DiRuntimeException; +use Zend\ServiceManager\Exception\ExceptionInterface as ServiceManagerException; /** * Dependency injector that can generate instances using class definitions and configured instance parameters */ @@ -757,7 +757,25 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP } else { $resolvedParams[$index] = $this->get($computedParams['retrieval'][$fqParamPos][0], $callTimeUserParams); } - } catch (Exception\RuntimeException $e) { + } catch (DiRuntimeException $e) { + if ($methodRequirementType & self::RESOLVE_STRICT) { + //finally ( be aware to do at the end of flow) + array_pop($this->currentDependencies); + // if this item was marked strict, + // plus it cannot be resolve, and no value exist, bail out + throw new Exception\MissingPropertyException(sprintf( + 'Missing %s for parameter ' . $name . ' for ' . $class . '::' . $method, + (($value[0] === null) ? 'value' : 'instance/object' ) + ), + $e->getCode(), + $e); + } else { + //finally ( be aware to do at the end of flow) + array_pop($this->currentDependencies); + return false; + } + } catch (ServiceManagerException $e) { + //Zend\ServiceManager\Exception\ServiceNotCreatedException if ($methodRequirementType & self::RESOLVE_STRICT) { //finally ( be aware to do at the end of flow) array_pop($this->currentDependencies); From 810dcd2dc8bf0dc8caf7aa664780dbe0c8842c3b Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 9 May 2013 09:57:44 -0500 Subject: [PATCH 15/15] [zendframework/zf2#4435] CS fixes - order of use statements - ensure line between use statements and class docblock --- src/Definition/ArrayDefinition.php | 1 + src/Definition/ClassDefinition.php | 2 +- src/Definition/RuntimeDefinition.php | 1 + src/Di.php | 1 + test/DiCompatibilityTest.php | 6 +++--- test/DiTest.php | 7 +++---- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Definition/ArrayDefinition.php b/src/Definition/ArrayDefinition.php index 908554fb..65113b7f 100644 --- a/src/Definition/ArrayDefinition.php +++ b/src/Definition/ArrayDefinition.php @@ -10,6 +10,7 @@ namespace Zend\Di\Definition; use Zend\Di\Definition\Builder\InjectionMethod; + /** * Class definitions based on a given array */ diff --git a/src/Definition/ClassDefinition.php b/src/Definition/ClassDefinition.php index 9d2d37a1..0d3fd52d 100644 --- a/src/Definition/ClassDefinition.php +++ b/src/Definition/ClassDefinition.php @@ -9,8 +9,8 @@ namespace Zend\Di\Definition; -use Zend\Di\Di; use Zend\Di\Definition\Builder\InjectionMethod; +use Zend\Di\Di; /** * Class definitions for a single class diff --git a/src/Definition/RuntimeDefinition.php b/src/Definition/RuntimeDefinition.php index 122eaa5e..9df696ed 100644 --- a/src/Definition/RuntimeDefinition.php +++ b/src/Definition/RuntimeDefinition.php @@ -13,6 +13,7 @@ use Zend\Code\Reflection; use Zend\Di\Definition\Annotation; use Zend\Di\Di; + /** * Class definitions based on runtime reflection */ diff --git a/src/Di.php b/src/Di.php index a2e36f1a..49cbeef6 100644 --- a/src/Di.php +++ b/src/Di.php @@ -13,6 +13,7 @@ use ReflectionClass; use Zend\Di\Exception\RuntimeException as DiRuntimeException; use Zend\ServiceManager\Exception\ServiceNotCreatedException; + /** * Dependency injector that can generate instances using class definitions and configured instance parameters */ diff --git a/test/DiCompatibilityTest.php b/test/DiCompatibilityTest.php index bc5634a7..89b0ec23 100644 --- a/test/DiCompatibilityTest.php +++ b/test/DiCompatibilityTest.php @@ -9,11 +9,11 @@ namespace ZendTest\Di; -use Zend\Di\Di; -use Zend\Di\DefinitionList; -use Zend\Di\InstanceManager; use Zend\Di\Config; use Zend\Di\Definition; +use Zend\Di\DefinitionList; +use Zend\Di\Di; +use Zend\Di\InstanceManager; class DiCompatibilityTest extends \PHPUnit_Framework_TestCase { diff --git a/test/DiTest.php b/test/DiTest.php index 127142f6..01fae76a 100644 --- a/test/DiTest.php +++ b/test/DiTest.php @@ -10,12 +10,11 @@ namespace ZendTest\Di; -use Zend\Di\Di; -use Zend\Di\DefinitionList; -use Zend\Di\InstanceManager; use Zend\Di\Config; use Zend\Di\Definition; - +use Zend\Di\DefinitionList; +use Zend\Di\Di; +use Zend\Di\InstanceManager; class DiTest extends \PHPUnit_Framework_TestCase {