Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Implementing first version of delegate factories for services

  • Loading branch information...
commit 93b585d6197a151b9133f1d56de2f4355e3b7f6e 1 parent 18d522d
@Ocramius authored
View
14 library/Zend/ServiceManager/Config.php
@@ -107,6 +107,16 @@ public function getShared()
}
/**
+ * Get delegate services map, with keys being the services, and values being the delegate factories names
+ *
+ * @return array
+ */
+ public function getDelegates()
+ {
+ return (isset($this->config['delegates'])) ? $this->config['delegates'] : array();
+ }
+
+ /**
* Configure service manager
*
* @param ServiceManager $serviceManager
@@ -145,5 +155,9 @@ public function configureServiceManager(ServiceManager $serviceManager)
foreach ($this->getShared() as $name => $isShared) {
$serviceManager->setShared($name, $isShared);
}
+
+ foreach ($this->getDelegates() as $name => $isShared) {
+ $serviceManager->setDelegate($name, $isShared);
+ }
}
}
View
28 library/Zend/ServiceManager/DelegateFactoryInterface.php
@@ -0,0 +1,28 @@
+<?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
+ */
+
+namespace Zend\ServiceManager;
+
+/**
+ * Interface for factories that can create delegates for services
+ */
+interface DelegateFactoryInterface
+{
+ /**
+ * A factory that creates delegates of a given service
+ *
+ * @param ServiceLocatorInterface $serviceLocator the service locator which requested the service
+ * @param string $name the normalized service name
+ * @param string $requestedName the requested service name
+ * @param callable $callback the callback that is responsible for creating the service
+ *
+ * @return mixed
+ */
+ public function createDelegateWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback);
+}
View
57 library/Zend/ServiceManager/ServiceManager.php
@@ -49,6 +49,11 @@ class ServiceManager implements ServiceLocatorInterface
protected $abstractFactories = array();
/**
+ * @var string[]
+ */
+ protected $delegates = array();
+
+ /**
* @var array
*/
protected $pendingAbstractFactoryRequests = array();
@@ -312,6 +317,21 @@ public function addAbstractFactory($factory, $topOfStack = true)
}
/**
+ * Sets the given service name as to be handled by a delegate factory
+ *
+ * @param string $serviceName
+ * @param string $delegateFactoryName
+ *
+ * @return ServiceManager
+ */
+ public function setDelegate($serviceName, $delegateFactoryName)
+ {
+ $this->delegates[$this->canonicalizeName($serviceName)] = $delegateFactoryName;
+
+ return $this;
+ }
+
+ /**
* Add initializer
*
* @param callable|InitializerInterface $initializer
@@ -478,14 +498,11 @@ public function get($name, $usePeeringServiceManagers = true)
* Create an instance
*
* @param string|array $name
+ *
* @return bool|object
- * @throws Exception\ServiceNotFoundException
- * @throws Exception\ServiceNotCreatedException
*/
public function create($name)
{
- $instance = false;
-
if (is_array($name)) {
list($cName, $rName) = $name;
} else {
@@ -499,6 +516,38 @@ public function create($name)
}
}
+ if (isset($this->delegates[$cName])) {
+ /* @var $delegateFactory DelegateFactoryInterface */
+ $delegateFactory = $this->get($this->delegates[$cName]);
+ $serviceManager = $this;
+
+ return $delegateFactory->createDelegateWithName(
+ $this,
+ $cName,
+ $rName,
+ function () use ($serviceManager, $rName, $cName) {
+ return $serviceManager->doCreate($rName, $cName);
+ }
+ );
+ }
+
+ return $this->doCreate($rName, $cName);
+ }
+
+ /**
+ * Actually creates the service
+ *
+ * @param string $rName real service name
+ * @param string $cName canonicalized service name
+ *
+ * @return bool|mixed|null|object
+ * @throws Exception\ServiceNotFoundException
+ *
+ * @internal this method is internal because of PHP 5.3 compatibility - do not explicitly use it
+ */
+ public function doCreate($rName, $cName)
+ {
+ $instance = false;
if (isset($this->factories[$cName])) {
$instance = $this->createFromFactory($cName, $rName);
View
34 tests/ZendTest/ServiceManager/ServiceManagerTest.php
@@ -728,4 +728,38 @@ public function testRetrieveServiceFromPeeringServiceManagerIfretrieveFromPeerin
$this->assertEquals($serviceManagerChild->get($foo1), $boo2);
$this->assertEquals($this->serviceManager->get($foo1), $boo2);
}
+
+ /**
+ * @covers Zend\ServiceManager\ServiceManager::create
+ * @covers Zend\ServiceManager\ServiceManager::setDelegate
+ */
+ public function testUsesDelegateWhenAvailable()
+ {
+ $delegate = $this->getMock('Zend\\ServiceManager\\DelegateFactoryInterface');
+
+ $this->serviceManager->setService('foo-delegate', $delegate);
+ $this->serviceManager->setDelegate('foo-service', 'foo-delegate');
+ $this->serviceManager->setInvokableClass('foo-service', 'stdClass');
+
+ $delegate
+ ->expects($this->once())
+ ->method('createDelegateWithName')
+ ->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($delegate));
+
+ $this->assertSame($delegate, $this->serviceManager->create('foo-service'));
+ }
}
Please sign in to comment.
Something went wrong with that request. Please try again.