<?php /** * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\Mvc\Controller; use Interop\Container\ContainerInterface; use Zend\EventManager\EventManagerAwareInterface; use Zend\EventManager\SharedEventManagerInterface; use Zend\Mvc\Exception; use Zend\ServiceManager\AbstractPluginManager as BasePluginManager; use Zend\ServiceManager\ConfigInterface; use Zend\ServiceManager\Exception\InvalidServiceException; use Zend\ServiceManager\ServiceLocatorAwareInterface; use Zend\Stdlib\DispatchableInterface; /** * Manager for loading controllers * * Does not define any controllers by default, but does add a validator. */ class ControllerManager extends BasePluginManager { /** * We do not want arbitrary classes instantiated as controllers. * * @var bool */ protected $autoAddInvokableClass = false; /** * Controllers must be of this type. * * @var string */ protected $instanceOf = DispatchableInterface::class; /** * Constructor * * Injects an initializer for injecting controllers with an * event manager and plugin manager. * * @param ConfigInterface|ContainerInterface $container * @param array $v3config */ public function __construct($configOrContainerInstance, array $v3config = []) { $this->addInitializer([$this, 'injectEventManager']); $this->addInitializer([$this, 'injectConsole']); $this->addInitializer([$this, 'injectPluginManager']); parent::__construct($configOrContainerInstance, $v3config); // Added after parent construction, as v2 abstract plugin managers add // one during construction. $this->addInitializer([$this, 'injectServiceLocator']); } /** * Validate a plugin (v3) * * {@inheritDoc} */ public function validate($plugin) { if (! $plugin instanceof $this->instanceOf) { throw new InvalidServiceException(sprintf( 'Plugin of type "%s" is invalid; must implement %s', (is_object($plugin) ? get_class($plugin) : gettype($plugin)), $this->instanceOf )); } } /** * Validate a plugin (v2) * * {@inheritDoc} * * @throws Exception\InvalidControllerException */ public function validatePlugin($plugin) { try { $this->validate($plugin); } catch (InvalidServiceException $e) { throw new Exception\InvalidControllerException( $e->getMessage(), $e->getCode(), $e ); } } /** * Initializer: inject EventManager instance * * If we have an event manager composed already, make sure it gets injected * with the shared event manager. * * The AbstractController lazy-instantiates an EM instance, which is why * the shared EM injection needs to happen; the conditional will always * pass. * * @param ContainerInterface|DispatchableInterface $first Container when * using zend-servicemanager v3; controller under v2. * @param DispatchableInterface|ContainerInterface $second Controller when * using zend-servicemanager v3; container under v2. */ public function injectEventManager($first, $second) { if ($first instanceof ContainerInterface) { $container = $first; $controller = $second; } else { $container = $second; $controller = $first; } if (! $controller instanceof EventManagerAwareInterface) { return; } $events = $controller->getEventManager(); if (! $events || ! $events->getSharedManager() instanceof SharedEventManagerInterface) { // For v2, we need to pull the parent service locator if (! method_exists($container, 'configure')) { $container = $container->getServiceLocator() ?: $container; } $controller->setEventManager($container->get('EventManager')); } } /** * Initializer: inject Console adapter instance * * @param ContainerInterface|DispatchableInterface $first Container when * using zend-servicemanager v3; controller under v2. * @param DispatchableInterface|ContainerInterface $second Controller when * using zend-servicemanager v3; container under v2. */ public function injectConsole($first, $second) { if ($first instanceof ContainerInterface) { $container = $first; $controller = $second; } else { $container = $second; $controller = $first; } if (! $controller instanceof AbstractConsoleController) { return; } // For v2, we need to pull the parent service locator if (! method_exists($container, 'configure')) { $container = $container->getServiceLocator() ?: $container; } $controller->setConsole($container->get('Console')); } /** * Initializer: inject plugin manager * * @param ContainerInterface|DispatchableInterface $first Container when * using zend-servicemanager v3; controller under v2. * @param DispatchableInterface|ContainerInterface $second Controller when * using zend-servicemanager v3; container under v2. */ public function injectPluginManager($first, $second) { if ($first instanceof ContainerInterface) { $container = $first; $controller = $second; } else { $container = $second; $controller = $first; } if (! method_exists($controller, 'setPluginManager')) { return; } // For v2, we need to pull the parent service locator if (! method_exists($container, 'configure')) { $container = $container->getServiceLocator() ?: $container; } $controller->setPluginManager($container->get('ControllerPluginManager')); } /** * Initializer: inject service locator * * @param ContainerInterface|DispatchableInterface $first Container when * using zend-servicemanager v3; controller under v2. * @param DispatchableInterface|ContainerInterface $second Controller when * using zend-servicemanager v3; container under v2. */ public function injectServiceLocator($first, $second) { if ($first instanceof ContainerInterface) { $container = $first; $controller = $second; } else { $container = $second; $controller = $first; } // For v2, we need to pull the parent service locator if (! method_exists($container, 'configure')) { $container = $container->getServiceLocator() ?: $container; } // Inject AbstractController extensions that are not ServiceLocatorAware // with the service manager, but do not emit a deprecation notice. We'll // emit it from AbstractController::getServiceLocator() instead. if (! $controller instanceof ServiceLocatorAwareInterface && $controller instanceof AbstractController && method_exists($controller, 'setServiceLocator') ) { // Do not emit deprecation notice in this case $controller->setServiceLocator($container); } // If a controller implements ServiceLocatorAwareInterface explicitly, we // inject, but emit a deprecation notice. Since AbstractController no longer // explicitly does this, this will only affect userland controllers. if ($controller instanceof ServiceLocatorAwareInterface) { trigger_error(sprintf( 'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along ' . 'with the ServiceLocatorAwareInitializer. Please update your class %s to remove ' . 'the implementation, and start injecting your dependencies via factory instead.', get_class($controller) ), E_USER_DEPRECATED); $controller->setServiceLocator($container); } } }