Updated DependencyInjection component's API

Signed-off-by: Gregory PLANCHAT <g.planchat@gmail.com>
This commit is contained in:
Gregory PLANCHAT 2012-07-17 23:27:44 +02:00
commit 2bed707ecd
7 changed files with 438 additions and 63 deletions

View file

@ -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) {

View file

@ -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()

View file

@ -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;
}
/**

View file

@ -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);

View file

@ -0,0 +1,143 @@
<?php
namespace WootookUnit\Core\DependencyInjection\Config;
/**
* Test class for Wootook\Core\BaseObject.
* Generated by PHPUnit on 2011-09-01 at 11:24:52.
* @requires
*/
class ConfigTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \Wootook\Core\App\App
*/
protected $_app;
/**
* @var \Wootook\Core\Config\Node
*/
protected $_config;
/**
* @var \Wootook\Core\DependencyInjection\Registry
*/
protected $_registry;
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
protected function setUp()
{
$this->_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');
}
}

View file

@ -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__));
}

View file

@ -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');
}
}