3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\ServiceManager
;
13 * ServiceManager implementation for managing plugins
15 * Automatically registers an initializer which should be used to verify that
16 * a plugin instance is of a valid type. Additionally, allows plugins to accept
17 * an array of options for the constructor, which can be used to configure
18 * the plugin when retrieved. Finally, enables the allowOverride property by
19 * default to allow registering factories, aliases, and invokables to take
20 * the place of those provided by the implementing class.
22 abstract class AbstractPluginManager
extends ServiceManager
implements ServiceLocatorAwareInterface
25 * Allow overriding by default
29 protected $allowOverride = true;
32 * Whether or not to auto-add a class as an invokable class if it exists
36 protected $autoAddInvokableClass = true;
39 * Options to use when creating an instance
43 protected $creationOptions = null;
46 * The main service locator
48 * @var ServiceLocatorInterface
50 protected $serviceLocator;
55 * Add a default initializer to ensure the plugin is valid after instance
58 * @param null|ConfigInterface $configuration
60 public function __construct(ConfigInterface
$configuration = null)
62 parent
::__construct($configuration);
64 $this->addInitializer(function ($instance) use ($self) {
65 if ($instance instanceof ServiceLocatorAwareInterface
) {
66 $instance->setServiceLocator($self);
74 * Checks that the filter loaded is either a valid callback or an instance
77 * @param mixed $plugin
79 * @throws Exception\RuntimeException if invalid
81 abstract public function validatePlugin($plugin);
84 * Retrieve a service from the manager by name
86 * Allows passing an array of options to use when creating the instance.
87 * createFromInvokable() will use these and pass them to the instance
88 * constructor if not null and a non-empty array.
91 * @param array $options
92 * @param bool $usePeeringServiceManagers
95 public function get($name, $options = array(), $usePeeringServiceManagers = true)
97 // Allow specifying a class name directly; registers as an invokable class
98 if (!$this->has($name) && $this->autoAddInvokableClass
&& class_exists($name)) {
99 $this->setInvokableClass($name, $name);
102 $this->creationOptions
= $options;
103 $instance = parent
::get($name, $usePeeringServiceManagers);
104 $this->creationOptions
= null;
105 $this->validatePlugin($instance);
110 * Register a service with the locator.
112 * Validates that the service object via validatePlugin() prior to
113 * attempting to register it.
115 * @param string $name
116 * @param mixed $service
117 * @param bool $shared
118 * @return AbstractPluginManager
119 * @throws Exception\InvalidServiceNameException
121 public function setService($name, $service, $shared = true)
124 $this->validatePlugin($service);
126 parent
::setService($name, $service, $shared);
131 * Set the main service locator so factories can have access to it to pull deps
133 * @param ServiceLocatorInterface $serviceLocator
134 * @return AbstractPluginManager
136 public function setServiceLocator(ServiceLocatorInterface
$serviceLocator)
138 $this->serviceLocator
= $serviceLocator;
143 * Get the main plugin manager. Useful for fetching dependencies from within factories.
147 public function getServiceLocator()
149 return $this->serviceLocator
;
153 * Attempt to create an instance via an invokable class
155 * Overrides parent implementation by passing $creationOptions to the
156 * constructor, if non-null.
158 * @param string $canonicalName
159 * @param string $requestedName
160 * @return null|\stdClass
161 * @throws Exception\ServiceNotCreatedException If resolved class does not exist
163 protected function createFromInvokable($canonicalName, $requestedName)
165 $invokable = $this->invokableClasses
[$canonicalName];
167 if (null === $this->creationOptions
168 ||
(is_array($this->creationOptions
) && empty($this->creationOptions
))
170 $instance = new $invokable();
172 $instance = new $invokable($this->creationOptions
);
179 * Attempt to create an instance via a factory class
181 * Overrides parent implementation by passing $creationOptions to the
182 * constructor, if non-null.
184 * @param string $canonicalName
185 * @param string $requestedName
187 * @throws Exception\ServiceNotCreatedException If factory is not callable
189 protected function createFromFactory($canonicalName, $requestedName)
191 $factory = $this->factories
[$canonicalName];
192 $hasCreationOptions = !(null === $this->creationOptions ||
(is_array($this->creationOptions
) && empty($this->creationOptions
)));
194 if (is_string($factory) && class_exists($factory, true)) {
195 if (!$hasCreationOptions) {
196 $factory = new $factory();
198 $factory = new $factory($this->creationOptions
);
201 $this->factories
[$canonicalName] = $factory;
204 if ($factory instanceof FactoryInterface
) {
205 $instance = $this->createServiceViaCallback(array($factory, 'createService'), $canonicalName, $requestedName);
206 } elseif (is_callable($factory)) {
207 $instance = $this->createServiceViaCallback($factory, $canonicalName, $requestedName);
209 throw new Exception\
ServiceNotCreatedException(sprintf(
210 'While attempting to create %s%s an invalid factory was registered for this instance type.', $canonicalName, ($requestedName ?
'(alias: ' . $requestedName . ')' : '')
218 * Create service via callback
220 * @param callable $callable
221 * @param string $cName
222 * @param string $rName
223 * @throws Exception\ServiceNotCreatedException
224 * @throws Exception\ServiceNotFoundException
225 * @throws Exception\CircularDependencyFoundException
228 protected function createServiceViaCallback($callable, $cName, $rName)
230 if (is_object($callable)) {
231 $factory = $callable;
232 } elseif (is_array($callable)) {
233 // reset both rewinds and returns the value of the first array element
234 $factory = reset($callable);
238 && ($factory instanceof MutableCreationOptionsInterface
)
239 && is_array($this->creationOptions
)
240 && !empty($this->creationOptions
)
242 $factory->setCreationOptions($this->creationOptions
);
245 return parent
::createServiceViaCallback($callable, $cName, $rName);