From 6dbeb693e6b40a8dc262b5bb78d18b3d0fe7e9f2 Mon Sep 17 00:00:00 2001 From: Stefano Torresi Date: Fri, 27 Sep 2013 10:41:44 +0200 Subject: [PATCH 01/10] revert test edits and add new tests --- test/ServiceManagerTest.php | 61 ++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/test/ServiceManagerTest.php b/test/ServiceManagerTest.php index bc67aa99..6f31d09b 100644 --- a/test/ServiceManagerTest.php +++ b/test/ServiceManagerTest.php @@ -753,6 +753,7 @@ public function testRetrieveServiceFromPeeringServiceManagerIfretrieveFromPeerin /** * @covers Zend\ServiceManager\ServiceManager::create + * @covers Zend\ServiceManager\ServiceManager::createDelegatorFromFactory * @covers Zend\ServiceManager\ServiceManager::createDelegatorCallback * @covers Zend\ServiceManager\ServiceManager::addDelegator */ @@ -760,7 +761,8 @@ public function testUsesDelegatorWhenAvailable() { $delegator = $this->getMock('Zend\\ServiceManager\\DelegatorFactoryInterface'); - $this->serviceManager->addDelegator('foo-service', $delegator); + $this->serviceManager->setService('foo-delegator', $delegator); + $this->serviceManager->addDelegator('foo-service', 'foo-delegator'); $this->serviceManager->setInvokableClass('foo-service', 'stdClass'); $delegator @@ -787,6 +789,7 @@ public function testUsesDelegatorWhenAvailable() /** * @covers Zend\ServiceManager\ServiceManager::create + * @covers Zend\ServiceManager\ServiceManager::createDelegatorFromFactory * @covers Zend\ServiceManager\ServiceManager::createDelegatorCallback * @covers Zend\ServiceManager\ServiceManager::addDelegator */ @@ -795,6 +798,62 @@ public function testUsesMultipleDelegates() $fooDelegator = new MockSelfReturningDelegatorFactory(); $barDelegator = new MockSelfReturningDelegatorFactory(); + $this->serviceManager->setService('foo-delegate', $fooDelegator); + $this->serviceManager->setService('bar-delegate', $barDelegator); + $this->serviceManager->addDelegator('foo-service', 'foo-delegate'); + $this->serviceManager->addDelegator('foo-service', 'bar-delegate'); + $this->serviceManager->setInvokableClass('foo-service', 'stdClass'); + + $this->assertSame($barDelegator, $this->serviceManager->create('foo-service')); + $this->assertCount(1, $barDelegator->instances); + $this->assertCount(1, $fooDelegator->instances); + $this->assertInstanceOf('stdClass', array_shift($fooDelegator->instances)); + $this->assertSame($fooDelegator, array_shift($barDelegator->instances)); + } + + /** + * @covers Zend\ServiceManager\ServiceManager::createDelegatorFromFactory + */ + public function testDelegatorFactoryWhenNotRegisteredAsService() + { + $delegator = $this->getMock('Zend\\ServiceManager\\DelegatorFactoryInterface'); + + $this->serviceManager->addDelegator('foo-service', $delegator); + $this->serviceManager->setInvokableClass('foo-service', 'stdClass'); + + $delegator + ->expects($this->once()) + ->method('createDelegatorWithName') + ->with( + $this->serviceManager, + 'fooservice', + 'foo-service', + $this->callback(function ($callback) { + if (!is_callable($callback)) { + return false; + } + + $service = call_user_func($callback); + + return $service instanceof \stdClass; + }) + ) + ->will($this->returnValue($delegator)); + + $this->assertSame($delegator, $this->serviceManager->create('foo-service')); + } + + /** + * @covers Zend\ServiceManager\ServiceManager::create + * @covers Zend\ServiceManager\ServiceManager::createDelegatorFromFactory + * @covers Zend\ServiceManager\ServiceManager::createDelegatorCallback + * @covers Zend\ServiceManager\ServiceManager::addDelegator + */ + public function testMultipleDelegatorFactoriesWhenNotRegisteredAsServices() + { + $fooDelegator = new MockSelfReturningDelegatorFactory(); + $barDelegator = new MockSelfReturningDelegatorFactory(); + $this->serviceManager->addDelegator('foo-service', $fooDelegator); $this->serviceManager->addDelegator('foo-service', $barDelegator); $this->serviceManager->setInvokableClass('foo-service', 'stdClass'); From cc45e0073a7caa18b5f4196b4f63ffd3f7743774 Mon Sep 17 00:00:00 2001 From: Stefano Torresi Date: Fri, 27 Sep 2013 10:47:15 +0200 Subject: [PATCH 02/10] fix BC --- src/ServiceManager.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ServiceManager.php b/src/ServiceManager.php index 2fd5a92c..cb9019dc 100644 --- a/src/ServiceManager.php +++ b/src/ServiceManager.php @@ -1042,8 +1042,10 @@ protected function createDelegatorFromFactory($canonicalName, $requestedName) $delegatorFactory = $this->delegators[$canonicalName][$i]; - if (is_string($delegatorFactory) && class_exists($delegatorFactory, true)) { - $delegatorFactory = new $delegatorFactory; + if (is_string($delegatorFactory)) { + $delegatorFactory = !$this->has($delegatorFactory) && class_exists($delegatorFactory, true) ? + new $delegatorFactory + : $this->get($delegatorFactory); $this->delegators[$canonicalName][$i] = $delegatorFactory; } From c9b63e81ede27b7b6affee61334e45a801b837aa Mon Sep 17 00:00:00 2001 From: Stefano Torresi Date: Fri, 27 Sep 2013 14:24:35 +0200 Subject: [PATCH 03/10] add single delegator tests for abtract plugin manager --- test/AbstractPluginManagerTest.php | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/AbstractPluginManagerTest.php b/test/AbstractPluginManagerTest.php index 1d8f2b31..ffaae8c8 100644 --- a/test/AbstractPluginManagerTest.php +++ b/test/AbstractPluginManagerTest.php @@ -117,4 +117,55 @@ public function testCallableObjectWithMutableCreationOptions() $method->setAccessible(true); $method->invoke($this->pluginManager, $callable, 'foo', 'bar'); } + + public function testValidatePluginGetsCalledOnDelegatorFactoryIfItsAService() + { + $pluginManagerMock = $this->getMockForAbstractClass('Zend\ServiceManager\AbstractPluginManager'); + $delegatorFactoryMock = $this->getMock('Zend\\ServiceManager\\DelegatorFactoryInterface'); + + $pluginManagerMock->setService('delegator-factory', $delegatorFactoryMock); + $pluginManagerMock->addDelegator('foo-service', 'delegator-factory'); + + $pluginManagerMock->expects($this->once()) + ->method('validatePlugin') + ->with($delegatorFactoryMock); + + $pluginManagerMock->create('foo-service'); + } + + public function testSingleDelegatorUsage() + { + $delegatorFactory = $this->getMock('Zend\\ServiceManager\\DelegatorFactoryInterface'); + $pluginManager = $this->getMockForAbstractClass('Zend\ServiceManager\AbstractPluginManager'); + $realService = $this->getMock('stdClass', array(), array(), 'RealService'); + $delegator = $this->getMock('stdClass', array(), array(), 'Delegator'); + + $delegatorFactory + ->expects($this->once()) + ->method('createDelegatorWithName') + ->with( + $pluginManager, + 'fooservice', + 'foo-service', + $this->callback(function ($callback) use ($realService) { + if (!is_callable($callback)) { + return false; + } + + return call_user_func($callback) === $realService; + }) + ) + ->will($this->returnValue($delegator)); + + $pluginManager->setFactory('foo-service', function() use ($realService) { + return $realService; + }); + $pluginManager->addDelegator('foo-service', $delegatorFactory); + + $pluginManager->expects($this->once()) + ->method('validatePlugin') + ->with($delegator); + + $this->assertSame($delegator, $pluginManager->get('foo-service')); + } } From ca07912a14da7f6222442afe5bda405d22568c9d Mon Sep 17 00:00:00 2001 From: Stefano Torresi Date: Fri, 27 Sep 2013 15:57:55 +0200 Subject: [PATCH 04/10] add multiple delegator test for abtract plugin manager --- test/AbstractPluginManagerTest.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/AbstractPluginManagerTest.php b/test/AbstractPluginManagerTest.php index ffaae8c8..d20bbdaa 100644 --- a/test/AbstractPluginManagerTest.php +++ b/test/AbstractPluginManagerTest.php @@ -17,6 +17,7 @@ use ZendTest\ServiceManager\TestAsset\FooCounterAbstractFactory; use ZendTest\ServiceManager\TestAsset\FooPluginManager; +use ZendTest\ServiceManager\TestAsset\MockSelfReturningDelegatorFactory; class AbstractPluginManagerTest extends \PHPUnit_Framework_TestCase { @@ -168,4 +169,27 @@ public function testSingleDelegatorUsage() $this->assertSame($delegator, $pluginManager->get('foo-service')); } + + public function testMultipleDelegatorsUsage() + { + $pluginManager = $this->getMockForAbstractClass('Zend\ServiceManager\AbstractPluginManager'); + + $fooDelegator = new MockSelfReturningDelegatorFactory(); + $barDelegator = new MockSelfReturningDelegatorFactory(); + + $pluginManager->addDelegator('foo-service', $fooDelegator); + $pluginManager->addDelegator('foo-service', $barDelegator); + $pluginManager->setInvokableClass('foo-service', 'stdClass'); + + $pluginManager->expects($this->once()) + ->method('validatePlugin') + ->with($barDelegator); + + $this->assertSame($barDelegator, $pluginManager->get('foo-service')); + $this->assertCount(1, $barDelegator->instances); + $this->assertCount(1, $fooDelegator->instances); + $this->assertInstanceOf('stdClass', array_shift($fooDelegator->instances)); + $this->assertSame($fooDelegator, array_shift($barDelegator->instances)); + + } } From 9df16c2de5b37330c9175d7da1ef91df068fc4f4 Mon Sep 17 00:00:00 2001 From: Stefano Torresi Date: Fri, 27 Sep 2013 15:58:50 +0200 Subject: [PATCH 05/10] test cleanup --- test/AbstractPluginManagerTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/AbstractPluginManagerTest.php b/test/AbstractPluginManagerTest.php index d20bbdaa..2cf31c4a 100644 --- a/test/AbstractPluginManagerTest.php +++ b/test/AbstractPluginManagerTest.php @@ -119,19 +119,19 @@ public function testCallableObjectWithMutableCreationOptions() $method->invoke($this->pluginManager, $callable, 'foo', 'bar'); } - public function testValidatePluginGetsCalledOnDelegatorFactoryIfItsAService() + public function testValidatePluginIsCalledWithDelegatorFactoryIfItsAService() { - $pluginManagerMock = $this->getMockForAbstractClass('Zend\ServiceManager\AbstractPluginManager'); - $delegatorFactoryMock = $this->getMock('Zend\\ServiceManager\\DelegatorFactoryInterface'); + $pluginManager = $this->getMockForAbstractClass('Zend\ServiceManager\AbstractPluginManager'); + $delegatorFactory = $this->getMock('Zend\\ServiceManager\\DelegatorFactoryInterface'); - $pluginManagerMock->setService('delegator-factory', $delegatorFactoryMock); - $pluginManagerMock->addDelegator('foo-service', 'delegator-factory'); + $pluginManager->setService('delegator-factory', $delegatorFactory); + $pluginManager->addDelegator('foo-service', 'delegator-factory'); - $pluginManagerMock->expects($this->once()) + $pluginManager->expects($this->once()) ->method('validatePlugin') - ->with($delegatorFactoryMock); + ->with($delegatorFactory); - $pluginManagerMock->create('foo-service'); + $pluginManager->create('foo-service'); } public function testSingleDelegatorUsage() From 942f443c050a9b31ba705bcba462ebf1e79d07a0 Mon Sep 17 00:00:00 2001 From: Stefano Torresi Date: Fri, 27 Sep 2013 16:16:42 +0200 Subject: [PATCH 06/10] add delegator factory validation testing --- test/ServiceManagerTest.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/ServiceManagerTest.php b/test/ServiceManagerTest.php index 6f31d09b..a3603c69 100644 --- a/test/ServiceManagerTest.php +++ b/test/ServiceManagerTest.php @@ -864,4 +864,33 @@ public function testMultipleDelegatorFactoriesWhenNotRegisteredAsServices() $this->assertInstanceOf('stdClass', array_shift($fooDelegator->instances)); $this->assertSame($fooDelegator, array_shift($barDelegator->instances)); } + + public function testInvalidDelegatorFactoryThrowsException() + { + $delegatorFactory = new \stdClass; + $this->serviceManager->addDelegator('foo-service', $delegatorFactory); + + try { + $this->serviceManager->create('foo-service'); + $this->fail('Expected exception was not raised'); + }catch (Exception\ServiceNotCreatedException $expected) { + $this->assertRegExp('/invalid factory/', $expected->getMessage()); + return; + } + } + + public function testInvalidDelegatorFactoryAmongMultipleOnesThrowsException() + { + $this->serviceManager->addDelegator('foo-service', new MockSelfReturningDelegatorFactory()); + $this->serviceManager->addDelegator('foo-service', new MockSelfReturningDelegatorFactory()); + $this->serviceManager->addDelegator('foo-service', 'stdClass'); + + try { + $this->serviceManager->create('foo-service'); + $this->fail('Expected exception was not raised'); + }catch (Exception\ServiceNotCreatedException $expected) { + $this->assertRegExp('/invalid factory/', $expected->getMessage()); + return; + } + } } From 35f9f655c0ec98fce6d17ef017ec810d4c6991d7 Mon Sep 17 00:00:00 2001 From: Stefano Torresi Date: Fri, 27 Sep 2013 17:42:53 +0200 Subject: [PATCH 07/10] add delegator from callback test --- test/ServiceManagerTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/ServiceManagerTest.php b/test/ServiceManagerTest.php index a3603c69..2e002bec 100644 --- a/test/ServiceManagerTest.php +++ b/test/ServiceManagerTest.php @@ -893,4 +893,21 @@ public function testInvalidDelegatorFactoryAmongMultipleOnesThrowsException() return; } } + + public function testDelegatorFromCallback() + { + $realService = $this->getMock('stdClass', array(), array(), 'RealService'); + $delegator = $this->getMock('stdClass', array(), array(), 'Delegator'); + + $delegator = function($serviceManager, $cName, $rName, $callback) use($delegator) { + $delegator->real = call_user_func($callback); + return $delegator; + }; + + $this->serviceManager->addDelegator('foo-service', $delegator); + $this->serviceManager->setService('foo-service', $realService); + + $this->assertSame($delegator, $this->serviceManager->create('foo-service')); + $this->assertSame($realService, $delegator->real); + } } From b95e474ac9b363c51e2092edf8bade84096dd563 Mon Sep 17 00:00:00 2001 From: Stefano Torresi Date: Mon, 30 Sep 2013 13:04:01 +0200 Subject: [PATCH 08/10] fix callback test --- test/ServiceManagerTest.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/ServiceManagerTest.php b/test/ServiceManagerTest.php index 2e002bec..c4d1638b 100644 --- a/test/ServiceManagerTest.php +++ b/test/ServiceManagerTest.php @@ -899,15 +899,17 @@ public function testDelegatorFromCallback() $realService = $this->getMock('stdClass', array(), array(), 'RealService'); $delegator = $this->getMock('stdClass', array(), array(), 'Delegator'); - $delegator = function($serviceManager, $cName, $rName, $callback) use($delegator) { + $delegatorFactoryCallback = function($serviceManager, $cName, $rName, $callback) use ($delegator) { $delegator->real = call_user_func($callback); return $delegator; }; - $this->serviceManager->addDelegator('foo-service', $delegator); - $this->serviceManager->setService('foo-service', $realService); + $this->serviceManager->setFactory('foo-service', function() use ($realService) { return $realService; } ); + $this->serviceManager->addDelegator('foo-service', $delegatorFactoryCallback); - $this->assertSame($delegator, $this->serviceManager->create('foo-service')); - $this->assertSame($realService, $delegator->real); + $service = $this->serviceManager->create('foo-service'); + + $this->assertSame($delegator, $service); + $this->assertSame($realService, $service->real); } } From b580d44d1d223d9bc6c963426e86a2886b6c4dee Mon Sep 17 00:00:00 2001 From: Stefano Torresi Date: Mon, 30 Sep 2013 13:04:43 +0200 Subject: [PATCH 09/10] add callback support for delegator factories --- src/ServiceManager.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/ServiceManager.php b/src/ServiceManager.php index cb9019dc..a335b1e2 100644 --- a/src/ServiceManager.php +++ b/src/ServiceManager.php @@ -541,10 +541,10 @@ public function create($name) /** * Creates a callback that uses a delegator to create a service * - * @param DelegatorFactoryInterface $delegatorFactory the delegator factory - * @param string $rName requested service name - * @param string $cName canonical service name - * @param callable $creationCallback callback that is responsible for instantiating the service + * @param DelegatorFactoryInterface|callable $delegatorFactory the delegator factory + * @param string $rName requested service name + * @param string $cName canonical service name + * @param callable $creationCallback callback for instantiating the real service * * @return callable */ @@ -553,7 +553,9 @@ private function createDelegatorCallback($delegatorFactory, $rName, $cName, $cre $serviceManager = $this; return function () use ($serviceManager, $delegatorFactory, $rName, $cName, $creationCallback) { - return $delegatorFactory->createDelegatorWithName($serviceManager, $cName, $rName, $creationCallback); + return $delegatorFactory instanceof DelegatorFactoryInterface + ? $delegatorFactory->createDelegatorWithName($serviceManager, $cName, $rName, $creationCallback) + : $delegatorFactory($serviceManager, $cName, $rName, $creationCallback); }; } @@ -1049,7 +1051,7 @@ protected function createDelegatorFromFactory($canonicalName, $requestedName) $this->delegators[$canonicalName][$i] = $delegatorFactory; } - if (!$delegatorFactory instanceof DelegatorFactoryInterface) { + if (!$delegatorFactory instanceof DelegatorFactoryInterface && !is_callable($delegatorFactory)) { throw new Exception\ServiceNotCreatedException(sprintf( 'While attempting to create %s%s an invalid factory was registered for this instance type.', $canonicalName, @@ -1068,7 +1070,9 @@ protected function createDelegatorFromFactory($canonicalName, $requestedName) } } - $delegator = $delegatorFactory->createDelegatorWithName($this, $canonicalName, $requestedName, $creationCallback); + $delegator = $delegatorFactory instanceof DelegatorFactoryInterface + ? $delegatorFactory->createDelegatorWithName($serviceManager, $canonicalName, $requestedName, $creationCallback) + : $delegatorFactory($serviceManager, $canonicalName, $requestedName, $creationCallback); return $delegator; } From d22ed524727543ad1e5f4a44eab8f61487d05daf Mon Sep 17 00:00:00 2001 From: Stefano Torresi Date: Mon, 30 Sep 2013 13:25:35 +0200 Subject: [PATCH 10/10] code cleaning --- src/ServiceManager.php | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/ServiceManager.php b/src/ServiceManager.php index a335b1e2..d908fe19 100644 --- a/src/ServiceManager.php +++ b/src/ServiceManager.php @@ -1059,22 +1059,15 @@ protected function createDelegatorFromFactory($canonicalName, $requestedName) )); } - // add additional callbacks for every delegatorFactory but the last - if ($delegatorsCount > 1 && $i != $delegatorsCount - 1) { - $creationCallback = $this->createDelegatorCallback( - $delegatorFactory, - $requestedName, - $canonicalName, - $creationCallback - ); - } + $creationCallback = $this->createDelegatorCallback( + $delegatorFactory, + $requestedName, + $canonicalName, + $creationCallback + ); } - $delegator = $delegatorFactory instanceof DelegatorFactoryInterface - ? $delegatorFactory->createDelegatorWithName($serviceManager, $canonicalName, $requestedName, $creationCallback) - : $delegatorFactory($serviceManager, $canonicalName, $requestedName, $creationCallback); - - return $delegator; + return $creationCallback($serviceManager, $canonicalName, $requestedName, $creationCallback); } /**