diff --git a/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Config/Config.php b/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Config/Config.php index 10be5d5..198e1f2 100644 --- a/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Config/Config.php +++ b/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Config/Config.php @@ -10,8 +10,7 @@ class Config public function __invoke(DependencyInjection\Factory $factory, Node $config) { foreach ($config as $className => $classConfig) { - $classDefinition = $factory->initClassDefinition($className); - $factory->registerClassDefinition($className, $classDefinition); + $factory->addClassDefinition($className); if ($classConfig->methods instanceof Node) { foreach ($classConfig->methods as $methodName => $methodConfig) { diff --git a/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Definition/ClassDefinition.php b/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Definition/ClassDefinition.php index 8adc5ce..df3fdc4 100644 --- a/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Definition/ClassDefinition.php +++ b/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Definition/ClassDefinition.php @@ -11,15 +11,17 @@ class ClassDefinition { protected $_className = null; protected $_reflector = null; - protected $_methods = array(); + protected $_methodDefinitions = array(); - protected $_methodDefinitionHandlerClass = null; + protected $_registry = null; + + protected $_methodDefinitionClassName = 'Wootook\\Core\\DependencyInjection\\Definition\\MethodDefinition'; /** * @param string $className * @param null|string $methodDefinitionHandlerClass */ - public function __construct($className, $methodDefinitionHandlerClass = null) + public function __construct($className, DependencyInjection\Registry $registry = null, $methodDefinitionHandlerClass = null) { $this->_className = $className; try { @@ -35,13 +37,16 @@ class ClassDefinition } } - /** - * @param string $methodName - * @return \Wootook\Core\DependencyInjection\Definition\MethodDefinition - */ - protected function _getMethodDefinitionInstance($methodName) + public function setRegistry(DependencyInjection\Registry $registry) { - return new $this->_methodDefinitionHandlerClass($this, $methodName); + $this->_registry = $registry; + + return $this; + } + + public function getRegistry() + { + return $this->_registry; } /** @@ -49,17 +54,50 @@ class ClassDefinition * @return \Wootook\Core\DependencyInjection\Definition\MethodDefinition * @throws \Wootook\Core\Exception\DependencyInjection\InvalidArgumentException */ - public function getMethodDefinition($methodName) + public function getMethodDefinition($methodName, $registerInstanceIfNew = false) { if (!is_string($methodName)) { throw new CoreException\DependencyInjection\InvalidArgumentException('Method names only accept string.'); } - if (!isset($this->_methods[$methodName])) { - $this->_methods[$methodName] = $this->_getMethodDefinitionInstance($methodName); + if (isset($this->_methodDefinitions[$methodName])) { + return $this->_methodDefinitions[$methodName]; } - return $this->_methods[$methodName]; + $definition = $this->initMethodDefinition($methodName); + if ($registerInstanceIfNew === true) { + $this->registerMethodDefinition($methodName, $definition); + } + return $definition; + } + + /** + * @param string $methodName + * @return \Wootook\Core\DependencyInjection\Definition\MethodDefinition + */ + public function initMethodDefinition($methodName) + { + $class = $this->getMethodDefinitionClassName(); + + return new $class($this, $methodName, $this->getRegistry()); + } + + public function registerMethodDefinition($methodName, MethodDefinition $methodDefinition) + { + if (!is_string($methodName)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Method names only accept string.'); + } + + $this->_methodDefinitions[$methodName] = $methodDefinition; + + return $this; + } + + public function addMethodDefinition($methodName) + { + $this->registerMethodDefinition($methodName, $this->initMethodDefinition($methodName)); + + return $this; } public function setMethodDefinition($methodName, MethodDefinition $definition) @@ -68,17 +106,31 @@ class ClassDefinition throw new CoreException\DependencyInjection\InvalidArgumentException('Method names only accept string.'); } - $this->_methods[$methodName] = $definition; + $this->_methodDefinitions[$methodName] = $definition; return $this; } - public function getAllMethodDefinitions() + public function setMethodDefinitionClassName($methodDefinitionClassName) { - return $this->_methods; + if (!is_string($methodDefinitionClassName)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Class names only accept string.'); + } + + return $this->_methodDefinitionClassName; } - public function newInstance(Array $args = array(), $withoutConstructorCall = false) + public function getMethodDefinitionClassName() + { + return $this->_methodDefinitionClassName; + } + + public function getAllMethodDefinitions() + { + return $this->_methodDefinitions; + } + + public function newInstance(Array $args = array()) { try { if ($this->getReflector()->hasMethod('__construct')) { @@ -104,7 +156,7 @@ class ClassDefinition public function reset() { - return $this->_methods = array(); + return $this->_methodDefinitions = array(); } public function getReflector() diff --git a/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Definition/MethodDefinition.php b/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Definition/MethodDefinition.php index 5d73f4f..3bf86fd 100644 --- a/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Definition/MethodDefinition.php +++ b/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Definition/MethodDefinition.php @@ -27,7 +27,7 @@ class MethodDefinition /** * @var array */ - protected $_arguments = array(); + protected $_argumentDefinitions = array(); /** * @var array @@ -44,7 +44,7 @@ class MethodDefinition */ protected $_registry = null; - protected $_argumentDefinitionHandlerClass = null; + protected $_argumentDefinitionClassName = 'Wootook\\Core\\DependencyInjection\\Definition\\ArgumentDefinition'; /** * @param ClassDefinition $classDefinition @@ -64,23 +64,12 @@ class MethodDefinition } if (is_string($argumentDefinitionHandlerClass)) { - $this->_argumentDefinitionHandlerClass = $argumentDefinitionHandlerClass; - } else { - $this->_argumentDefinitionHandlerClass = __NAMESPACE__ . '\\ArgumentDefinition'; + $this->setArgumentDefinitionClassName($argumentDefinitionHandlerClass); } $this->_registry = $registry; } - /** - * @param $argumentPosition - * @return \Wootook\Core\DependencyInjection\Definition\ArgumentDefinition - */ - protected function _getArgumentDefinitionInstance($argumentPosition) - { - return new $this->_argumentDefinitionHandlerClass($this, $argumentPosition); - } - /** * @param \Wootook\Core\DependencyInjection\Registry $registry * @return MethodDefinition @@ -100,6 +89,98 @@ class MethodDefinition return $this->_registry; } + /** + * @param int|string $argumentPosition + * @return \Wootook\Core\DependencyInjection\Definition\ArgumentDefinition + * @throws \Wootook\Core\Exception\DependencyInjection\InvalidArgumentException + */ + public function getArgumentDefinition($argumentPosition, $registerInstanceIfNew = false) + { + if (is_string($argumentPosition) && isset($this->_argumentIndex[$argumentPosition])) { + $argumentPosition = $this->_argumentIndex[$argumentPosition]; + } + + if (!is_int($argumentPosition)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Argument could only be found by position or by name.'); + } + + if (isset($this->_argumentDefinitions[$argumentPosition])) { + return $this->_argumentDefinitions[$argumentPosition]; + } + + $definition = $this->initArgumentDefinition($argumentPosition); + if ($registerInstanceIfNew === true) { + $this->registerArgumentDefinition($argumentPosition, $definition); + } + return $definition; + } + + public function initArgumentDefinition($argumentPosition) + { + if (is_string($argumentPosition) && isset($this->_argumentIndex[$argumentPosition])) { + $argumentPosition = $this->_argumentIndex[$argumentPosition]; + } + + if (!is_int($argumentPosition)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Argument could only be found by position or by name.'); + } + + $class = $this->getArgumentDefinitionClassName(); + + return new $class($this, $argumentPosition, $this->getRegistry()); + } + + public function registerArgumentDefinition($argumentPosition, ArgumentDefinition $argumentDefinition) + { + if (is_string($argumentPosition) && isset($this->_argumentIndex[$argumentPosition])) { + $argumentPosition = $this->_argumentIndex[$argumentPosition]; + } + + if (!is_int($argumentPosition)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Argument could only be found by position or by name.'); + } + + $this->_argumentDefinitions[$argumentPosition] = $argumentDefinition; + + return $this; + } + + public function addArgumentDefinition($argumentPosition) + { + $this->registerArgumentDefinition($argumentPosition, $this->initArgumentDefinition($argumentPosition)); + + return $this; + } + + public function setArgumentDefinition($argumentPosition, ArgumentDefinition $definition) + { + if (is_string($argumentPosition) && isset($this->_argumentIndex[$argumentPosition])) { + $argumentPosition = $this->_argumentIndex[$argumentPosition]; + } + + if (!is_int($argumentPosition)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Argument could only be found by position or by name.'); + } + + $this->_argumentDefinitions[$argumentPosition] = $definition; + + return $this; + } + + public function setArgumentDefinitionClassName($argumentDefinitionClassName) + { + if (!is_string($argumentDefinitionClassName)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Class names only accept string.'); + } + + return $this->_argumentDefinitionClassName; + } + + public function getArgumentDefinitionClassName() + { + return $this->_argumentDefinitionClassName; + } + /** * @param string|int $argumentPosition * @param mixed $argumentValue @@ -108,7 +189,7 @@ class MethodDefinition */ public function bindArgumentValue($argumentPosition, $argumentValue) { - $this->getArgumentDefinition($argumentPosition)->bindValue($argumentValue); + $this->getArgumentDefinition($argumentPosition, true)->bindValue($argumentValue); return $this; } @@ -121,7 +202,7 @@ class MethodDefinition */ public function bindArgumentVariable($argumentPosition, &$argumentVariable) { - $this->getArgumentDefinition($argumentPosition)->bindVariable($argumentVariable); + $this->getArgumentDefinition($argumentPosition, true)->bindVariable($argumentVariable); return $this; } @@ -139,39 +220,17 @@ class MethodDefinition throw new CoreException\DependencyInjection\RuntimeException('No registry available'); } - $this->getArgumentDefinition($argumentPosition)->bindRegistryEntry($registryKey); + $this->getArgumentDefinition($argumentPosition, true)->bindRegistryEntry($registryKey); return $this; } - /** - * @param int|string $argumentPosition - * @return \Wootook\Core\DependencyInjection\Definition\ArgumentDefinition - * @throws \Wootook\Core\Exception\DependencyInjection\InvalidArgumentException - */ - public function getArgumentDefinition($argumentPosition) - { - if (is_string($argumentPosition) && isset($this->_argumentIndex[$argumentPosition])) { - $argumentPosition = $this->_argumentIndex[$argumentPosition]; - } - - if (!is_int($argumentPosition)) { - throw new CoreException\DependencyInjection\InvalidArgumentException('Argument not found.'); - } - - if (!isset($this->_arguments[$argumentPosition])) { - $this->_arguments[$argumentPosition] = $this->_getArgumentDefinitionInstance($argumentPosition); - } - - return $this->_arguments[$argumentPosition]; - } - /** * @return array */ public function getAllArgumentDefinitions() { - return $this->_arguments; + return $this->_argumentDefinitions; } /** diff --git a/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Factory.php b/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Factory.php index 018e3d7..bbff31f 100644 --- a/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Factory.php +++ b/src/application/modules/WootookCore/src/Wootook/Core/DependencyInjection/Factory.php @@ -16,11 +16,15 @@ class Factory protected $_classDefinitionClassName = 'Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition'; - protected function _construct(Registry $registry = null) + protected function _construct(Registry $registry = null, $classDefinitionClassName = null) { if ($registry !== null) { $this->setRegistry($registry); } + + if ($classDefinitionClassName !== null) { + $this->setClassDefinitionClassName($classDefinitionClassName); + } } public function setRegistry(Registry $registry) @@ -39,23 +43,38 @@ class Factory return $this->_registry; } - public function getClassDefinition($className) + public function getClassDefinition($className, $registerInstanceIfNew = false) { + if (!is_string($className)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Class names only accept string.'); + } + if (isset($this->_classDefinitions[$className])) { return $this->_classDefinitions[$className]; } + $definition = $this->initClassDefinition($className); + if ($registerInstanceIfNew === true) { + $this->registerClassDefinition($className, $definition); + } + return $definition; + return $this->initClassDefinition($className); } public function initClassDefinition($className) { $class = $this->getClassDefinitionClassName(); + return new $class($className); } public function registerClassDefinition($className, Definition\ClassDefinition $classDefinition) { + if (!is_string($className)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Class names only accept string.'); + } + $this->_classDefinitions[$className] = $classDefinition; return $this; @@ -68,9 +87,29 @@ class Factory return $this; } - public function setClassDefinitionClassName($className) + public function setClassDefinition($className, Definition\ClassDefinition $definition) { - $this->_classDefinitionClassName = $className; + if (!is_string($className)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Class names only accept string.'); + } + + $this->_classDefinitions[$className] = $definition; + + return $this; + } + + public function getAllClassDefinitions() + { + return $this->_classDefinitions; + } + + public function setClassDefinitionClassName($classDefinitionClassName) + { + if (!is_string($classDefinitionClassName)) { + throw new CoreException\DependencyInjection\InvalidArgumentException('Class names only accept string.'); + } + + $this->_classDefinitionClassName = $classDefinitionClassName; return $this; } @@ -80,6 +119,11 @@ class Factory return $this->_classDefinitionClassName; } + public function reset() + { + return $this->_classDefinitions = array(); + } + public function __invoke($className, Array $additionalArguments = array()) { $definition = $this->getClassDefinition($className); diff --git a/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/Config/ConfigTest.php b/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/Config/ConfigTest.php new file mode 100644 index 0000000..de0327e --- /dev/null +++ b/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/Config/ConfigTest.php @@ -0,0 +1,143 @@ +_app = $this->getMock('Wootook\\Core\\App\\App', array('__construct'), array('')); + $this->_registry = new \Wootook\Core\DependencyInjection\Registry($this->_app); + } + + public function testGetRegistryWhilePassedToConstructor() + { + $object = new \Wootook\Core\DependencyInjection\Factory($this->_app, $this->_registry); + + $this->assertAttributeSame($this->_registry, '_registry', $object); + $this->assertSame($object->getRegistry(), $this->_registry); + } + + public function testGetClassDefinition_usingSpecialClassName() + { + $object = new \Wootook\Core\DependencyInjection\Factory($this->_app, $this->_registry, 'stdClass'); + + $this->assertInstanceOf('stdClass', $object->getClassDefinition('stdClass')); + } + + public function testGetRegistryWhileNonePassedToConstructor() + { + $object = new \Wootook\Core\DependencyInjection\Factory($this->_app); + + $this->assertInstanceOf('Wootook\\Core\\DependencyInjection\\Registry', $object->getRegistry()); + $this->assertAttributeNotEmpty('_registry', $object); + $this->assertAttributeNotSame($this->_registry, '_registry', $object); + + $object->setRegistry($this->_registry); + + $this->assertAttributeSame($this->_registry, '_registry', $object); + $this->assertSame($object->getRegistry(), $this->_registry); + } + + public function testGetUndeclaredClassDefinition() + { + $object = new \Wootook\Core\DependencyInjection\Factory($this->_app, $this->_registry); + + $this->assertInstanceOf('Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition', $object->getClassDefinition('stdClass')); + } + + public function testGetDeclaredClassDefinition() + { + $object = new \Wootook\Core\DependencyInjection\Factory($this->_app, $this->_registry); + + $classDefinition = $this->getMockBuilder('Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition') + ->disableOriginalConstructor() + ->getMock() + ; + + $object->registerClassDefinition('stdClass', $classDefinition); + + $this->assertInstanceOf('Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition', $object->getClassDefinition('stdClass')); + } + + public function testAddClassDefinition() + { + $classDefinition = $this->getMockBuilder('Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition') + ->disableOriginalConstructor() + ->getMock() + ; + + $object = $this->getMockBuilder('Wootook\\Core\\DependencyInjection\\Factory') + ->disableOriginalConstructor() + ->setMethods(array('initClassDefinition', 'registerClassDefinition')) + ->getMock() + ; + + $object->expects($this->once()) + ->method('initClassDefinition') + ->with('stdClass') + ->will($this->returnValue($classDefinition)) + ; + + $object->expects($this->once()) + ->method('registerClassDefinition') + ->with('stdClass', $classDefinition) + ->will($this->returnSelf()) + ; + + $object->addClassDefinition('stdClass'); + } + + public function testInstanceInvocation() + { + $classDefinition = $this->getMockBuilder('Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition') + ->disableOriginalConstructor() + ->setMethods(array('newInstance')) + ->getMock() + ; + + $classDefinition->expects($this->once()) + ->method('newInstance') + ->with(array()) + ->will($this->returnValue(new \stdClass)) + ; + + $object = $this->getMockBuilder('Wootook\\Core\\DependencyInjection\\Factory') + ->disableOriginalConstructor() + ->setMethods(array('getClassDefinition')) + ->getMock() + ; + + $object->expects($this->once()) + ->method('getClassDefinition') + ->with('stdClass') + ->will($this->returnValue($classDefinition)) + ; + + $object('stdClass'); + } +} diff --git a/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/Definition/ClassDefinitionTest.php b/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/Definition/ClassDefinitionTest.php index 12b54b8..2d07a4b 100644 --- a/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/Definition/ClassDefinitionTest.php +++ b/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/Definition/ClassDefinitionTest.php @@ -18,7 +18,7 @@ class ClassDefinitionTest extends \PHPUnit_Framework_TestCase $methodDefinitionClassName = \uniqid('WootookUnit_Core_DependencyInjection_Mock_MethodDefinition_TestNewInstance_'); $this->getMock('Wootook\\Core\\DependencyInjection\\Definition\\MethodDefinition', array(), array(), $methodDefinitionClassName, false); - $definition = new Definition\ClassDefinition(__CLASS__, $methodDefinitionClassName); + $definition = new Definition\ClassDefinition(__CLASS__, null, $methodDefinitionClassName); $this->assertInstanceOf($methodDefinitionClassName, $definition->getMethodDefinition(__FUNCTION__)); } diff --git a/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/FactoryTest.php b/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/FactoryTest.php index 185ceb1..01d3349 100644 --- a/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/FactoryTest.php +++ b/src/application/modules/WootookCore/test/php/WootookUnit/Core/DependencyInjection/FactoryTest.php @@ -42,6 +42,13 @@ class FactoryTest extends \PHPUnit_Framework_TestCase $this->assertSame($object->getRegistry(), $this->_registry); } + public function testGetClassDefinition_usingSpecialClassName() + { + $object = new \Wootook\Core\DependencyInjection\Factory($this->_app, $this->_registry, 'stdClass'); + + $this->assertInstanceOf('stdClass', $object->getClassDefinition('stdClass')); + } + public function testGetRegistryWhileNonePassedToConstructor() { $object = new \Wootook\Core\DependencyInjection\Factory($this->_app); @@ -56,10 +63,81 @@ class FactoryTest extends \PHPUnit_Framework_TestCase $this->assertSame($object->getRegistry(), $this->_registry); } - public function testGetDefinition() + public function testGetUndeclaredClassDefinition() { $object = new \Wootook\Core\DependencyInjection\Factory($this->_app, $this->_registry); $this->assertInstanceOf('Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition', $object->getClassDefinition('stdClass')); } + + public function testGetDeclaredClassDefinition() + { + $object = new \Wootook\Core\DependencyInjection\Factory($this->_app, $this->_registry); + + $classDefinition = $this->getMockBuilder('Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition') + ->disableOriginalConstructor() + ->getMock() + ; + + $object->registerClassDefinition('stdClass', $classDefinition); + + $this->assertInstanceOf('Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition', $object->getClassDefinition('stdClass')); + } + + public function testAddClassDefinition() + { + $classDefinition = $this->getMockBuilder('Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition') + ->disableOriginalConstructor() + ->getMock() + ; + + $object = $this->getMockBuilder('Wootook\\Core\\DependencyInjection\\Factory') + ->disableOriginalConstructor() + ->setMethods(array('initClassDefinition', 'registerClassDefinition')) + ->getMock() + ; + + $object->expects($this->once()) + ->method('initClassDefinition') + ->with('stdClass') + ->will($this->returnValue($classDefinition)) + ; + + $object->expects($this->once()) + ->method('registerClassDefinition') + ->with('stdClass', $classDefinition) + ->will($this->returnSelf()) + ; + + $object->addClassDefinition('stdClass'); + } + + public function testInstanceInvocation() + { + $classDefinition = $this->getMockBuilder('Wootook\\Core\\DependencyInjection\\Definition\\ClassDefinition') + ->disableOriginalConstructor() + ->setMethods(array('newInstance')) + ->getMock() + ; + + $classDefinition->expects($this->once()) + ->method('newInstance') + ->with(array()) + ->will($this->returnValue(new \stdClass)) + ; + + $object = $this->getMockBuilder('Wootook\\Core\\DependencyInjection\\Factory') + ->disableOriginalConstructor() + ->setMethods(array('getClassDefinition')) + ->getMock() + ; + + $object->expects($this->once()) + ->method('getClassDefinition') + ->with('stdClass') + ->will($this->returnValue($classDefinition)) + ; + + $object('stdClass'); + } }