3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Mvc\Service
;
12 use Interop\Container\ContainerInterface
;
14 use Zend\Di\Exception\ClassNotFoundException
;
15 use Zend\ServiceManager\AbstractFactoryInterface
;
16 use Zend\ServiceManager\AbstractPluginManager
;
17 use Zend\ServiceManager\Exception
;
18 use Zend\ServiceManager\ServiceLocatorInterface
;
21 * Create and return instances from a DI container and/or the parent container.
23 * This abstract factory can be mapped to arbitrary class names, and used to
24 * pull them from the composed Di instance, using the following behaviors:
26 * - If USE_SL_BEFORE_DI is passed as the second argument to the constructor,
27 * the factory will attempt to fetch the service from the passed container
28 * first, and fall back to the composed DI container only on failure.
29 * - If USE_SL_AFTER_DI is passed as the second argument to the constructor,
30 * the factory will attempt to fetch the service from the composed DI
31 * container first, and fall back to the passed container only on failure.
32 * - If USE_SL_NONE is passed as the second argument to the constructor (or no
33 * argument is passed), then the factory will only fetch from the composed
36 * Unlike DiAbstractServiceFactory and DiServiceFactory, this abstract factory
37 * requires that classes requested are in a provided whitelist; if the requested
38 * service is not, an exception is raised. This is useful to provide a scoped
39 * container, e.g., to limit to known controller classes, etc.
41 * @deprecated Since 2.7.9. The factory is now defined in zend-servicemanager-di,
42 * and removed in 3.0.0. Use Zend\ServiceManager\Di\DiStrictAbstractServiceFactory
43 * from zend-servicemanager-di if you are using zend-servicemanager v3, and/or when
44 * ready to migrate to zend-mvc 3.0.
46 class DiStrictAbstractServiceFactory
extends Di
implements AbstractFactoryInterface
51 const USE_SL_BEFORE_DI
= 'before';
52 const USE_SL_AFTER_DI
= 'after';
53 const USE_SL_NONE
= 'none';
64 protected $useContainer = self
::USE_SL_AFTER_DI
;
67 * @var ContainerInterface
69 protected $container = null;
72 * @var array an array of whitelisted service names (keys are the service names)
74 protected $allowedServiceNames = [];
78 * @param string $useContainer
80 public function __construct(Di
$di, $useContainer = self
::USE_SL_NONE
)
82 $this->useContainer
= $useContainer;
84 // Since we are using this in a proxy-fashion, localize state
86 $this->definitions
= $this->di
->definitions
;
87 $this->instanceManager
= $this->di
->instanceManager
;
91 * @param array $allowedServiceNames
93 public function setAllowedServiceNames(array $allowedServiceNames)
95 $this->allowedServiceNames
= array_flip(array_values($allowedServiceNames));
101 public function getAllowedServiceNames()
103 return array_keys($this->allowedServiceNames
);
109 * Allows creation of services only when in a whitelist
111 public function __invoke(ContainerInterface
$container, $name, array $options = null)
113 if (! isset($this->allowedServiceNames
[$name])) {
114 throw new Exception\
InvalidServiceException(sprintf(
115 'Service "%s" is not whitelisted',
120 $this->container
= ($container instanceof AbstractPluginManager
)
121 ?
$container->getServiceLocator()
124 return parent
::get($name);
130 * For use with zend-servicemanager v2; proxies to __invoke().
132 public function createServiceWithName(ServiceLocatorInterface
$container, $serviceName, $requestedName)
134 return $this($container, $requestedName);
138 * Overrides Zend\Di to allow the given container's services to be reused by Di itself
142 * @throws Exception\InvalidServiceNameException
144 public function get($name, array $params = [])
146 if (null === $this->container
) {
147 throw new Exception\
DomainException(
148 'No ServiceLocator defined, use `createServiceWithName` instead of `get`'
152 if (self
::USE_SL_BEFORE_DI
=== $this->useContainer
&& $this->container
->has($name)) {
153 return $this->container
->get($name);
157 return parent
::get($name, $params);
158 } catch (ClassNotFoundException
$e) {
159 if (self
::USE_SL_AFTER_DI
=== $this->useContainer
&& $this->container
->has($name)) {
160 return $this->container
->get($name);
163 throw new Exception\
ServiceNotFoundException(
164 sprintf('Service %s was not found in this DI instance', $name),
174 * Allows creation of services only when in a whitelist.
176 public function canCreate(ContainerInterface
$container, $requestedName)
178 // won't check if the service exists, we are trusting the user's whitelist
179 return isset($this->allowedServiceNames
[$requestedName]);
185 * For use with zend-servicemanager v2; proxies to canCreate().
187 public function canCreateServiceWithName(ServiceLocatorInterface
$container, $name, $requestedName)
189 return $this->canCreate($container, $requestedName);