Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Allowing multiple wrapped delegates

  • Loading branch information...
commit 59fd2ae23fd714aba548f3c2540871afc33711d2 1 parent 93b585d
@Ocramius authored
View
6 library/Zend/ServiceManager/Config.php
@@ -156,8 +156,10 @@ public function configureServiceManager(ServiceManager $serviceManager)
$serviceManager->setShared($name, $isShared);
}
- foreach ($this->getDelegates() as $name => $isShared) {
- $serviceManager->setDelegate($name, $isShared);
+ foreach ($this->getDelegates() as $name => $delegates) {
+ foreach ($delegates as $delegate) {
+ $serviceManager->addDelegate($name, $delegate);
+ }
}
}
}
View
61 library/Zend/ServiceManager/ServiceManager.php
@@ -49,7 +49,7 @@ class ServiceManager implements ServiceLocatorInterface
protected $abstractFactories = array();
/**
- * @var string[]
+ * @var array[]
*/
protected $delegates = array();
@@ -324,9 +324,13 @@ public function addAbstractFactory($factory, $topOfStack = true)
*
* @return ServiceManager
*/
- public function setDelegate($serviceName, $delegateFactoryName)
+ public function addDelegate($serviceName, $delegateFactoryName)
{
- $this->delegates[$this->canonicalizeName($serviceName)] = $delegateFactoryName;
+ if (!isset($this->delegates[$this->canonicalizeName($serviceName)])) {
+ $this->delegates[$this->canonicalizeName($serviceName)] = array();
+ }
+
+ $this->delegates[$this->canonicalizeName($serviceName)][] = $delegateFactoryName;
return $this;
}
@@ -495,7 +499,7 @@ public function get($name, $usePeeringServiceManagers = true)
}
/**
- * Create an instance
+ * Create an instance of the requested service
*
* @param string|array $name
*
@@ -517,24 +521,53 @@ public function create($name)
}
if (isset($this->delegates[$cName])) {
+ $serviceManager = $this;
+ $additionalDelegates = count($this->delegates[$cName]) - 1;
+ $creationCallback = function () use ($serviceManager, $rName, $cName) {
+ return $serviceManager->doCreate($rName, $cName);
+ };
+
+ for ($i = 0; $i < $additionalDelegates; $i += 1) {
+ $creationCallback = $this->createDelegateCallback(
+ $this->delegates[$cName][$i],
+ $rName,
+ $cName,
+ $creationCallback
+ );
+ }
+
/* @var $delegateFactory DelegateFactoryInterface */
- $delegateFactory = $this->get($this->delegates[$cName]);
- $serviceManager = $this;
+ $delegateFactory = $this->get($this->delegates[$cName][$i]);
- return $delegateFactory->createDelegateWithName(
- $this,
- $cName,
- $rName,
- function () use ($serviceManager, $rName, $cName) {
- return $serviceManager->doCreate($rName, $cName);
- }
- );
+ return $delegateFactory->createDelegateWithName($this, $cName, $rName, $creationCallback);
}
return $this->doCreate($rName, $cName);
}
/**
+ * Creates a callback that uses a delegate to create a service
+ *
+ * @param string $delegateFactoryName name of the delegate factory
+ * @param string $rName requested service name
+ * @param string $cName canonical service name
+ * @param callable $creationCallback callback that is responsible for instantiating the service
+ *
+ * @return callable
+ */
+ private function createDelegateCallback($delegateFactoryName, $rName, $cName, $creationCallback)
+ {
+ $serviceManager = $this;
+
+ return function () use ($serviceManager, $delegateFactoryName, $rName, $cName, $creationCallback) {
+ /* @var $delegateFactory DelegateFactoryInterface */
+ $delegateFactory = $this->get($delegateFactoryName);
+
+ return $delegateFactory->createDelegateWithName($this, $cName, $rName, $creationCallback);
+ };
+ }
+
+ /**
* Actually creates the service
*
* @param string $rName real service name
View
31 tests/ZendTest/ServiceManager/ServiceManagerTest.php
@@ -18,6 +18,7 @@
use Zend\ServiceManager\Config;
use ZendTest\ServiceManager\TestAsset\FooCounterAbstractFactory;
+use ZendTest\ServiceManager\TestAsset\MockSelfReturningDelegateFactory;
class ServiceManagerTest extends \PHPUnit_Framework_TestCase
{
@@ -731,14 +732,15 @@ public function testRetrieveServiceFromPeeringServiceManagerIfretrieveFromPeerin
/**
* @covers Zend\ServiceManager\ServiceManager::create
- * @covers Zend\ServiceManager\ServiceManager::setDelegate
+ * @covers Zend\ServiceManager\ServiceManager::createDelegateCallback
+ * @covers Zend\ServiceManager\ServiceManager::addDelegate
*/
public function testUsesDelegateWhenAvailable()
{
$delegate = $this->getMock('Zend\\ServiceManager\\DelegateFactoryInterface');
$this->serviceManager->setService('foo-delegate', $delegate);
- $this->serviceManager->setDelegate('foo-service', 'foo-delegate');
+ $this->serviceManager->addDelegate('foo-service', 'foo-delegate');
$this->serviceManager->setInvokableClass('foo-service', 'stdClass');
$delegate
@@ -762,4 +764,27 @@ public function testUsesDelegateWhenAvailable()
$this->assertSame($delegate, $this->serviceManager->create('foo-service'));
}
-}
+
+ /**
+ * @covers Zend\ServiceManager\ServiceManager::create
+ * @covers Zend\ServiceManager\ServiceManager::createDelegateCallback
+ * @covers Zend\ServiceManager\ServiceManager::addDelegate
+ */
+ public function testUsesMultipleDelegates()
+ {
+ $fooDelegate = new MockSelfReturningDelegateFactory();
+ $barDelegate = new MockSelfReturningDelegateFactory();
+
+ $this->serviceManager->setService('foo-delegate', $fooDelegate);
+ $this->serviceManager->setService('bar-delegate', $barDelegate);
+ $this->serviceManager->addDelegate('foo-service', 'foo-delegate');
+ $this->serviceManager->addDelegate('foo-service', 'bar-delegate');
+ $this->serviceManager->setInvokableClass('foo-service', 'stdClass');
+
+ $this->assertSame($barDelegate, $this->serviceManager->create('foo-service'));
+ $this->assertCount(1, $barDelegate->instances);
+ $this->assertCount(1, $fooDelegate->instances);
+ $this->assertInstanceOf('stdClass', array_shift($fooDelegate->instances));
+ $this->assertSame($fooDelegate, array_shift($barDelegate->instances));
+ }
+}
View
35 tests/ZendTest/ServiceManager/TestAsset/MockSelfReturningDelegateFactory.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @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_ServiceManager
+ */
+
+namespace ZendTest\ServiceManager\TestAsset;
+
+use Zend\ServiceManager\DelegateFactoryInterface;
+use Zend\ServiceManager\ServiceLocatorInterface;
+
+/**
+ * Mock factory that logs delegated instances and returns itself
+ */
+class MockSelfReturningDelegateFactory implements DelegateFactoryInterface
+{
+ /**
+ * @var mixed[]
+ */
+ public $instances = array();
+
+ /**
+ * {@inheritDoc}
+ */
+ public function createDelegateWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback)
+ {
+ $this->instances[] = call_user_func($callback);
+
+ return $this;
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.