diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dc6ef691..e4d0e5c6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ All notable changes to this project will be documented in this file, in reverse - [#31](https://github.com/zendframework/zend-mvc/pull/31) adds three required arguments to the `Zend\Mvc\Application` constructor: an EventManager instance, a Request instance, and a Response instance. +- [#36](https://github.com/zendframework/zend-mvc/pull/36) adds more than a + dozen service factories, primarily to separate conditional factories into + discrete factories. ### Deprecated @@ -16,12 +19,47 @@ All notable changes to this project will be documented in this file, in reverse ### Removed -- Nothing. +- [#36](https://github.com/zendframework/zend-mvc/pull/36) removes + `Zend\Mvc\Service\ConfigFactory`, as the functionality is now incorporated + into `Zend\ModuleManager\Listener\ServiceListener`. +- [#36](https://github.com/zendframework/zend-mvc/pull/36) removes + the `ServiceLocatorAware` intializer, as zend-servicemanager v3 no longer + defines the interface. +- [#36](https://github.com/zendframework/zend-mvc/pull/36) removes + `Zend\Mvc\Service\ControllerLoaderFactory` and replaces it with + `Zend\Mvc\Service\ControllerManagerFactory`. +- [#36](https://github.com/zendframework/zend-mvc/pull/36) removes + `Zend\Mvc\Service\DiFactory`, `Zend\Mvc\Service\DiAbstractServiceFactory`, + `Zend\Mvc\Service\DiStrictAbstractServiceFactory`, + `Zend\Mvc\Service\DiStrictAbstractServiceFactoryFactory`, + and `Zend\Mvc\Service\DiServiceInitializerFactory`, as zend-servicemanager v3 + removes `Zend\Di` integration. ### Fixed - [#31](https://github.com/zendframework/zend-mvc/pull/31) updates the component to use zend-eventmanager v3. +- [#36](https://github.com/zendframework/zend-mvc/pull/36) updates the component + to use zend-servicemanager v3, and zend-modulemanager v3. This involves: + - Updating all factories implementing either `FactoryInterface` or + `AbstractFactoryInterface` to the new signatures of those interfaces. + - Updating all plugin managers to the updates to `AbstractPluginManager`. + - Updating how plugin manager factories work (they're now passed the container + instance in their constructor arguments, as well as any build options). + - Added a `RouteInvokableFactory`, which can act as either a + `FactoryInterface` or `AbstractFactoryInterface` for loading invokable route + classes, including by fully qualified class name. This is registered as an + abstract factory by default with the `RoutePluginManager`. + - The `DispatchListener` now receives the controller manager instance at + instantiation. + - The `ViewManager` implementations were updated, and most functionality + within separated into discrete factories. (Previously these instances + injected services and aliases into the service manager instance, which is no + longer possible or desirable with the zend-servicemanager v3 changes.) + - `Application::init()` now pulls the configured service manager from the + `Zend\ModuleManager\Listener\ServiceListener` instance before retrieving and + bootstrapping the `Application` instance; this ensure it is fully + configured at that time. ## 2.6.1 - TBD diff --git a/composer.json b/composer.json index d00404ebc..5a85e94d4 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "require": { "php": ">=5.5", "zendframework/zend-eventmanager": "dev-develop as 2.7.0", - "zendframework/zend-servicemanager": "~2.5", + "zendframework/zend-servicemanager": "dev-develop as 2.6.0", "zendframework/zend-hydrator": "~1.0", "zendframework/zend-form": "~2.6", "zendframework/zend-stdlib": "~2.7", diff --git a/src/Application.php b/src/Application.php index 2b9068449..360a71aff 100644 --- a/src/Application.php +++ b/src/Application.php @@ -125,7 +125,7 @@ public function __construct( */ public function getConfig() { - return $this->serviceManager->get('Config'); + return $this->serviceManager->get('config'); } /** @@ -140,9 +140,10 @@ public function getConfig() */ public function bootstrap(array $listeners = []) { - $serviceManager = $this->serviceManager; $events = $this->events; + $serviceManager = $this->serviceManager; + // Setup default listeners $listeners = array_unique(array_merge($this->defaultListeners, $listeners)); foreach ($listeners as $listener) { @@ -160,6 +161,7 @@ public function bootstrap(array $listeners = []) // Trigger bootstrap events $events->triggerEvent($event); + return $this; } @@ -252,13 +254,27 @@ public function getEventManager() */ public static function init($configuration = []) { + // Prepare the service manager $smConfig = isset($configuration['service_manager']) ? $configuration['service_manager'] : []; - $serviceManager = new ServiceManager(new Service\ServiceManagerConfig($smConfig)); - $serviceManager->setService('ApplicationConfig', $configuration); + $smConfig = new Service\ServiceManagerConfig($smConfig); + + $serviceManager = new ServiceManager($smConfig->toArray()); + $serviceManager = $serviceManager->withConfig(['services' => [ + 'ApplicationConfig' => $configuration, + ]]); + + // Load modules $serviceManager->get('ModuleManager')->loadModules(); + // Get the configured SM if necessary. + if ($serviceManager->has('ServiceListener')) { + $serviceListener = $serviceManager->get('ServiceListener'); + $serviceManager = $serviceListener->getConfiguredServiceManager(); + } + + // Prepare list of listeners to bootstrap $listenersFromAppConfig = isset($configuration['listeners']) ? $configuration['listeners'] : []; - $config = $serviceManager->get('Config'); + $config = $serviceManager->get('config'); $listenersFromConfigService = isset($config['listeners']) ? $config['listeners'] : []; $listeners = array_unique(array_merge($listenersFromConfigService, $listenersFromAppConfig)); diff --git a/src/Controller/AbstractController.php b/src/Controller/AbstractController.php index 1d5f0d3cc..92e633d92 100644 --- a/src/Controller/AbstractController.php +++ b/src/Controller/AbstractController.php @@ -17,8 +17,7 @@ use Zend\Http\Request as HttpRequest; use Zend\Mvc\InjectApplicationEventInterface; use Zend\Mvc\MvcEvent; -use Zend\ServiceManager\ServiceLocatorAwareInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\ServiceManager; use Zend\Stdlib\DispatchableInterface as Dispatchable; use Zend\Stdlib\RequestInterface as Request; use Zend\Stdlib\ResponseInterface as Response; @@ -46,8 +45,7 @@ abstract class AbstractController implements Dispatchable, EventManagerAwareInterface, - InjectApplicationEventInterface, - ServiceLocatorAwareInterface + InjectApplicationEventInterface { /** * @var PluginManager @@ -74,11 +72,6 @@ abstract class AbstractController implements */ protected $events; - /** - * @var ServiceLocatorInterface - */ - protected $serviceLocator; - /** * @var null|string|string[] */ @@ -231,27 +224,6 @@ public function getEvent() return $this->event; } - /** - * Set serviceManager instance - * - * @param ServiceLocatorInterface $serviceLocator - * @return void - */ - public function setServiceLocator(ServiceLocatorInterface $serviceLocator) - { - $this->serviceLocator = $serviceLocator; - } - - /** - * Retrieve serviceManager instance - * - * @return ServiceLocatorInterface - */ - public function getServiceLocator() - { - return $this->serviceLocator; - } - /** * Get plugin manager * @@ -260,7 +232,7 @@ public function getServiceLocator() public function getPluginManager() { if (!$this->plugins) { - $this->setPluginManager(new PluginManager()); + $this->setPluginManager(new PluginManager(new ServiceManager())); } $this->plugins->setController($this); diff --git a/src/Controller/ControllerManager.php b/src/Controller/ControllerManager.php index 9749f93af..57cd64184 100644 --- a/src/Controller/ControllerManager.php +++ b/src/Controller/ControllerManager.php @@ -9,13 +9,10 @@ namespace Zend\Mvc\Controller; +use Interop\Container\ContainerInterface; use Zend\EventManager\EventManagerAwareInterface; use Zend\EventManager\SharedEventManagerInterface; -use Zend\Mvc\Exception; use Zend\ServiceManager\AbstractPluginManager; -use Zend\ServiceManager\ConfigInterface; -use Zend\ServiceManager\ServiceLocatorAwareInterface; -use Zend\ServiceManager\ServiceLocatorInterface; use Zend\Stdlib\DispatchableInterface; /** @@ -25,113 +22,77 @@ */ class ControllerManager extends AbstractPluginManager { - /** - * We do not want arbitrary classes instantiated as controllers. - * - * @var bool - */ - protected $autoAddInvokableClass = false; + protected $instanceOf = DispatchableInterface::class; /** * Constructor * - * After invoking parent constructor, add an initializer to inject the - * service manager, event manager, and plugin manager + * Injects an initializer for injecting controllers with an + * event manager and plugin manager. * - * @param null|ConfigInterface $configuration + * @param ContainerInterface $container + * @param array $configuration */ - public function __construct(ConfigInterface $configuration = null) + public function __construct(ContainerInterface $container, array $configuration = []) { - parent::__construct($configuration); - // Pushing to bottom of stack to ensure this is done last - $this->addInitializer([$this, 'injectControllerDependencies'], false); + $this->initializers[] = [$this, 'injectEventManager']; + $this->initializers[] = [$this, 'injectConsole']; + $this->initializers[] = [$this, 'injectPluginManager']; + parent::__construct($container, $configuration); } /** - * Inject required dependencies into the controller. + * 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 DispatchableInterface $controller - * @param ServiceLocatorInterface $serviceLocator - * @return void + * @param ContainerInterface $container + * @param DispatchableInterface $controller */ - public function injectControllerDependencies($controller, ServiceLocatorInterface $serviceLocator) + public function injectEventManager(ContainerInterface $container, $controller) { - if (!$controller instanceof DispatchableInterface) { + if (! $controller instanceof EventManagerAwareInterface) { return; } - $parentLocator = $serviceLocator->getServiceLocator(); - - if ($controller instanceof ServiceLocatorAwareInterface) { - $controller->setServiceLocator($parentLocator->get('Zend\ServiceManager\ServiceLocatorInterface')); - } - - if ($controller instanceof EventManagerAwareInterface) { - // 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. - $events = $controller->getEventManager(); - if (! $events || ! $events->getSharedManager() instanceof SharedEventManagerInterface) { - $controller->setEventManager($parentLocator->get('EventManager')); - } - } - - if ($controller instanceof AbstractConsoleController) { - $controller->setConsole($parentLocator->get('Console')); - } - - if (method_exists($controller, 'setPluginManager')) { - $controller->setPluginManager($parentLocator->get('ControllerPluginManager')); + $events = $controller->getEventManager(); + if (! $events || ! $events->getSharedManager() instanceof SharedEventManagerInterface) { + $controller->setEventManager($container->get('EventManager')); } } /** - * Validate the plugin - * - * Ensure we have a dispatchable. + * Initializer: inject Console adapter instance * - * @param mixed $plugin - * @return true - * @throws Exception\InvalidControllerException + * @param ContainerInterface $container + * @param DispatchableInterface $controller */ - public function validatePlugin($plugin) + public function injectConsole(ContainerInterface $container, $controller) { - if ($plugin instanceof DispatchableInterface) { - // we're okay + if (! $controller instanceof AbstractConsoleController) { return; } - throw new Exception\InvalidControllerException(sprintf( - 'Controller of type %s is invalid; must implement Zend\Stdlib\DispatchableInterface', - (is_object($plugin) ? get_class($plugin) : gettype($plugin)) - )); + $controller->setConsole($container->get('Console')); } /** - * Override: do not use peering service managers + * Initializer: inject plugin manager * - * @param string|array $name - * @param bool $checkAbstractFactories - * @param bool $usePeeringServiceManagers - * @return bool + * @param ContainerInterface $container + * @param DispatchableInterface $controller */ - public function has($name, $checkAbstractFactories = true, $usePeeringServiceManagers = false) + public function injectPluginManager(ContainerInterface $container, $controller) { - return parent::has($name, $checkAbstractFactories, $usePeeringServiceManagers); - } + if (! method_exists($controller, 'setPluginManager')) { + return; + } - /** - * Override: do not use peering service managers - * - * @param string $name - * @param array $options - * @param bool $usePeeringServiceManagers - * @return mixed - */ - public function get($name, $options = [], $usePeeringServiceManagers = false) - { - return parent::get($name, $options, $usePeeringServiceManagers); + $controller->setPluginManager($container->get('ControllerPluginManager')); } } diff --git a/src/Controller/Plugin/Forward.php b/src/Controller/Plugin/Forward.php index e0824fbf8..d26065ec4 100644 --- a/src/Controller/Plugin/Forward.php +++ b/src/Controller/Plugin/Forward.php @@ -236,7 +236,10 @@ protected function getEvent() $controller = $this->getController(); if (!$controller instanceof InjectApplicationEventInterface) { - throw new Exception\DomainException('Forward plugin requires a controller that implements InjectApplicationEventInterface'); + throw new Exception\DomainException(sprintf( + 'Forward plugin requires a controller that implements InjectApplicationEventInterface; received %s', + (is_object($controller) ? get_class($controller) : var_export($controller, 1)) + )); } $event = $controller->getEvent(); diff --git a/src/Controller/Plugin/Service/ForwardFactory.php b/src/Controller/Plugin/Service/ForwardFactory.php index 1f114ac57..89076fe5c 100644 --- a/src/Controller/Plugin/Service/ForwardFactory.php +++ b/src/Controller/Plugin/Service/ForwardFactory.php @@ -9,9 +9,9 @@ namespace Zend\Mvc\Controller\Plugin\Service; +use Interop\Container\ContainerInterface; use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; use Zend\Mvc\Controller\Plugin\Forward; class ForwardFactory implements FactoryInterface @@ -22,24 +22,16 @@ class ForwardFactory implements FactoryInterface * @return Forward * @throws ServiceNotCreatedException if Controllermanager service is not found in application service locator */ - public function createService(ServiceLocatorInterface $plugins) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $services = $plugins->getServiceLocator(); - if (!$services instanceof ServiceLocatorInterface) { - throw new ServiceNotCreatedException(sprintf( - '%s requires that the application service manager has been injected; none found', - __CLASS__ - )); - } - - if (!$services->has('ControllerManager')) { + if (! $container->has('ControllerManager')) { throw new ServiceNotCreatedException(sprintf( '%s requires that the application service manager contains a "%s" service; none found', __CLASS__, 'ControllerManager' )); } - $controllers = $services->get('ControllerManager'); + $controllers = $container->get('ControllerManager'); return new Forward($controllers); } diff --git a/src/Controller/Plugin/Service/IdentityFactory.php b/src/Controller/Plugin/Service/IdentityFactory.php index 701b3ddd7..dc3b7acfb 100644 --- a/src/Controller/Plugin/Service/IdentityFactory.php +++ b/src/Controller/Plugin/Service/IdentityFactory.php @@ -9,9 +9,10 @@ namespace Zend\Mvc\Controller\Plugin\Service; +use Interop\Container\ContainerInterface; +use Zend\Authentication\AuthenticationService; use Zend\Mvc\Controller\Plugin\Identity; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class IdentityFactory implements FactoryInterface { @@ -20,12 +21,11 @@ class IdentityFactory implements FactoryInterface * * @return \Zend\Mvc\Controller\Plugin\Identity */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $services = $serviceLocator->getServiceLocator(); $helper = new Identity(); - if ($services->has('Zend\Authentication\AuthenticationService')) { - $helper->setAuthenticationService($services->get('Zend\Authentication\AuthenticationService')); + if ($container->has(AuthenticationService::class)) { + $helper->setAuthenticationService($container->get(AuthenticationService::class)); } return $helper; } diff --git a/src/Controller/PluginManager.php b/src/Controller/PluginManager.php index cd7653695..bca5687a8 100644 --- a/src/Controller/PluginManager.php +++ b/src/Controller/PluginManager.php @@ -9,8 +9,8 @@ namespace Zend\Mvc\Controller; -use Zend\Mvc\Exception; use Zend\ServiceManager\AbstractPluginManager; +use Zend\ServiceManager\Factory\InvokableFactory; use Zend\Stdlib\DispatchableInterface; /** @@ -21,42 +21,62 @@ */ class PluginManager extends AbstractPluginManager { - /** - * Default set of plugins factories - * - * @var array - */ - protected $factories = [ - 'forward' => 'Zend\Mvc\Controller\Plugin\Service\ForwardFactory', - 'identity' => 'Zend\Mvc\Controller\Plugin\Service\IdentityFactory', - ]; + protected $instanceOf = Plugin\PluginInterface::class; /** - * Default set of plugins - * - * @var array + * @var string[] Default aliases */ - protected $invokableClasses = [ - 'acceptableviewmodelselector' => 'Zend\Mvc\Controller\Plugin\AcceptableViewModelSelector', - 'filepostredirectget' => 'Zend\Mvc\Controller\Plugin\FilePostRedirectGet', - 'flashmessenger' => 'Zend\Mvc\Controller\Plugin\FlashMessenger', - 'layout' => 'Zend\Mvc\Controller\Plugin\Layout', - 'params' => 'Zend\Mvc\Controller\Plugin\Params', - 'postredirectget' => 'Zend\Mvc\Controller\Plugin\PostRedirectGet', - 'redirect' => 'Zend\Mvc\Controller\Plugin\Redirect', - 'url' => 'Zend\Mvc\Controller\Plugin\Url', - 'createhttpnotfoundmodel' => 'Zend\Mvc\Controller\Plugin\CreateHttpNotFoundModel', - 'createconsolenotfoundmodel' => 'Zend\Mvc\Controller\Plugin\CreateConsoleNotFoundModel', + protected $aliases = [ + 'AcceptableViewModelSelector' => Plugin\AcceptableViewModelSelector::class, + 'acceptableViewModelSelector' => Plugin\AcceptableViewModelSelector::class, + 'acceptableviewmodelselector' => Plugin\AcceptableViewModelSelector::class, + 'FilePostRedirectGet' => Plugin\FilePostRedirectGet::class, + 'filePostRedirectGet' => Plugin\FilePostRedirectGet::class, + 'filepostredirectget' => Plugin\FilePostRedirectGet::class, + 'fileprg' => Plugin\FilePostRedirectGet::class, + 'FlashMessenger' => Plugin\FlashMessenger::class, + 'flashMessenger' => Plugin\FlashMessenger::class, + 'flashmessenger' => Plugin\FlashMessenger::class, + 'Forward' => Plugin\Forward::class, + 'forward' => Plugin\Forward::class, + 'Identity' => Plugin\Identity::class, + 'identity' => Plugin\Identity::class, + 'Layout' => Plugin\Layout::class, + 'layout' => Plugin\Layout::class, + 'Params' => Plugin\Params::class, + 'params' => Plugin\Params::class, + 'PostRedirectGet' => Plugin\PostRedirectGet::class, + 'postRedirectGet' => Plugin\PostRedirectGet::class, + 'postredirectget' => Plugin\PostRedirectGet::class, + 'prg' => Plugin\PostRedirectGet::class, + 'Redirect' => Plugin\Redirect::class, + 'redirect' => Plugin\Redirect::class, + 'Url' => Plugin\Url::class, + 'url' => Plugin\Url::class, + 'CreateHttpNotFoundModel' => Plugin\CreateHttpNotFoundModel::class, + 'createHttpNotFoundModel' => Plugin\CreateHttpNotFoundModel::class, + 'createhttpnotfoundmodel' => Plugin\CreateHttpNotFoundModel::class, + 'CreateConsoleNotFoundModel' => Plugin\CreateConsoleNotFoundModel::class, + 'createConsoleNotFoundModel' => Plugin\CreateConsoleNotFoundModel::class, + 'createconsolenotfoundmodel' => Plugin\CreateConsoleNotFoundModel::class, ]; /** - * Default set of plugin aliases - * - * @var array + * @var string[]|callable[] Default factories */ - protected $aliases = [ - 'prg' => 'postredirectget', - 'fileprg' => 'filepostredirectget', + protected $factories = [ + Plugin\Forward::class => Plugin\Service\ForwardFactory::class, + Plugin\Identity::class => Plugin\Service\IdentityFactory::class, + Plugin\AcceptableViewModelSelector::class => InvokableFactory::class, + Plugin\FilePostRedirectGet::class => InvokableFactory::class, + Plugin\FlashMessenger::class => InvokableFactory::class, + Plugin\Layout::class => InvokableFactory::class, + Plugin\Params::class => InvokableFactory::class, + Plugin\PostRedirectGet::class => InvokableFactory::class, + Plugin\Redirect::class => InvokableFactory::class, + Plugin\Url::class => InvokableFactory::class, + Plugin\CreateHttpNotFoundModel::class => InvokableFactory::class, + Plugin\CreateConsoleNotFoundModel::class => InvokableFactory::class, ]; /** @@ -75,13 +95,11 @@ class PluginManager extends AbstractPluginManager * plugin is lost. * * @param string $name - * @param mixed $options - * @param bool $usePeeringServiceManagers - * @return mixed + * @return DispatchableInterface */ - public function get($name, $options = [], $usePeeringServiceManagers = true) + public function get($name, array $options = null) { - $plugin = parent::get($name, $options, $usePeeringServiceManagers); + $plugin = parent::get($name, $options); $this->injectController($plugin); return $plugin; @@ -132,27 +150,4 @@ public function injectController($plugin) $plugin->setController($controller); } - - /** - * Validate the plugin - * - * Any plugin is considered valid in this context. - * - * @param mixed $plugin - * @return void - * @throws Exception\InvalidPluginException - */ - public function validatePlugin($plugin) - { - if ($plugin instanceof Plugin\PluginInterface) { - // we're okay - return; - } - - throw new Exception\InvalidPluginException(sprintf( - 'Plugin of type %s is invalid; must implement %s\Plugin\PluginInterface', - (is_object($plugin) ? get_class($plugin) : gettype($plugin)), - __NAMESPACE__ - )); - } } diff --git a/src/DispatchListener.php b/src/DispatchListener.php index 4b8671110..e8932400e 100644 --- a/src/DispatchListener.php +++ b/src/DispatchListener.php @@ -12,7 +12,7 @@ use ArrayObject; use Zend\EventManager\AbstractListenerAggregate; use Zend\EventManager\EventManagerInterface; -use Zend\Mvc\Exception\InvalidControllerException; +use Zend\ServiceManager\Exception\InvalidServiceException; use Zend\Stdlib\ArrayUtils; /** @@ -39,6 +39,19 @@ */ class DispatchListener extends AbstractListenerAggregate { + /** + * @var Controller\ControllerManager + */ + private $controllerManager; + + /** + * @param Controller\ControllerManager $controllerManager + */ + public function __construct(Controller\ControllerManager $controllerManager) + { + $this->controllerManager = $controllerManager; + } + /** * Attach listeners to an event manager * @@ -62,20 +75,24 @@ public function attach(EventManagerInterface $events, $priority = 1) */ public function onDispatch(MvcEvent $e) { - $routeMatch = $e->getRouteMatch(); - $controllerName = $routeMatch->getParam('controller', 'not-found'); - $application = $e->getApplication(); - $events = $application->getEventManager(); - $controllerLoader = $application->getServiceManager()->get('ControllerManager'); + $routeMatch = $e->getRouteMatch(); + $controllerName = $routeMatch instanceof Router\RouteMatch + ? $routeMatch->getParam('controller', 'not-found') + : 'not-found'; + $application = $e->getApplication(); + $events = $application->getEventManager(); + $controllerManager = $this->controllerManager; + - if (!$controllerLoader->has($controllerName)) { + // Query abstract controllers, too! + if (! $controllerManager->has($controllerName, true)) { $return = $this->marshalControllerNotFoundEvent($application::ERROR_CONTROLLER_NOT_FOUND, $controllerName, $e, $application); return $this->complete($return, $e); } try { - $controller = $controllerLoader->get($controllerName); - } catch (InvalidControllerException $exception) { + $controller = $controllerManager->get($controllerName); + } catch (InvalidServiceException $exception) { $return = $this->marshalControllerNotFoundEvent($application::ERROR_CONTROLLER_INVALID, $controllerName, $e, $application, $exception); return $this->complete($return, $e); } catch (\Exception $exception) { diff --git a/src/Exception/InvalidControllerException.php b/src/Exception/InvalidControllerException.php deleted file mode 100644 index 166f1fcdb..000000000 --- a/src/Exception/InvalidControllerException.php +++ /dev/null @@ -1,14 +0,0 @@ -routePluginManager; - foreach ([ - 'catchall' => __NAMESPACE__ . '\Catchall', - 'simple' => __NAMESPACE__ . '\Simple', - ] as $name => $class - ) { - $routes->setInvokableClass($name, $class); - }; + $this->routePluginManager = $routes->withConfig(['invokables' => [ + 'catchall' => __NAMESPACE__ . '\Catchall', + 'simple' => __NAMESPACE__ . '\Simple', + ]]); } /** diff --git a/src/Router/Http/TreeRouteStack.php b/src/Router/Http/TreeRouteStack.php index 481f9892f..7581d40d6 100644 --- a/src/Router/Http/TreeRouteStack.php +++ b/src/Router/Http/TreeRouteStack.php @@ -81,7 +81,20 @@ protected function init() $this->prototypes = new ArrayObject; $routes = $this->routePluginManager; - foreach ([ + $this->routePluginManager = $routes->withConfig([ + 'aliases' => [ + 'Chain' => 'chain', + 'Hostname' => 'hostname', + 'Literal' => 'literal', + 'Method' => 'method', + 'Part' => 'part', + 'Query' => 'query', + 'Regex' => 'regex', + 'Scheme' => 'scheme', + 'Segment' => 'segment', + 'Wildcard' => 'wildcard', + ], + 'invokables' => [ 'chain' => __NAMESPACE__ . '\Chain', 'hostname' => __NAMESPACE__ . '\Hostname', 'literal' => __NAMESPACE__ . '\Literal', @@ -92,10 +105,8 @@ protected function init() 'scheme' => __NAMESPACE__ . '\Scheme', 'segment' => __NAMESPACE__ . '\Segment', 'wildcard' => __NAMESPACE__ . '\Wildcard', - ] as $name => $class - ) { - $routes->setInvokableClass($name, $class); - }; + ], + ]); } /** @@ -275,8 +286,7 @@ public function match(Request $request, $pathOffset = null, array $options = []) } foreach ($this->routes as $name => $route) { - if ( - ($match = $route->match($request, $baseUrlLength, $options)) instanceof RouteMatch + if (($match = $route->match($request, $baseUrlLength, $options)) instanceof RouteMatch && ($pathLength === null || $match->getLength() === $pathLength) ) { $match->setMatchedRouteName($name); diff --git a/src/Router/RouteInvokableFactory.php b/src/Router/RouteInvokableFactory.php new file mode 100644 index 000000000..11c477882 --- /dev/null +++ b/src/Router/RouteInvokableFactory.php @@ -0,0 +1,83 @@ +setAlias($invokableClass, $name); - } - return $this; + $config = ArrayUtils::merge(['abstract_factories' => [ + RouteInvokableFactory::class, + ]], $config); + + parent::__construct($container, $config); } /** - * Validate the plugin. + * Pre-process configuration. * - * Checks that the filter loaded is either a valid callback or an instance - * of FilterInterface. + * Checks for invokables, and, if found, maps them to the + * component-specific RouteInvokableFactory; removes the invokables entry + * before passing to the parent. * - * @param mixed $plugin + * @param array $config * @return void - * @throws Exception\RuntimeException if invalid */ - public function validatePlugin($plugin) + protected function configure(array $config) { - if ($plugin instanceof RouteInterface) { - // we're okay - return; + if (isset($config['invokables']) && ! empty($config['invokables'])) { + $aliases = $this->createAliasesForInvokables($config['invokables']); + $factories = $this->createFactoriesForInvokables($config['invokables']); + + if (! empty($aliases)) { + $config['aliases'] = isset($config['aliases']) + ? array_merge($config['aliases'], $aliases) + : $aliases; + } + + $config['factories'] = isset($config['factories']) + ? array_merge($config['factories'], $factories) + : $factories; + + unset($config['invokables']); } - throw new Exception\RuntimeException(sprintf( - 'Plugin of type %s is invalid; must implement %s\RouteInterface', - (is_object($plugin) ? get_class($plugin) : gettype($plugin)), - __NAMESPACE__ - )); + parent::configure($config); } - /** - * Attempt to create an instance via an invokable class. + /** + * Create aliases for invokable classes. * - * Overrides parent implementation by invoking the route factory, - * passing $creationOptions as the argument. + * If an invokable service name does not match the class it maps to, this + * creates an alias to the class (which will later be mapped as an + * invokable factory). * - * @param string $canonicalName - * @param string $requestedName - * @return null|\stdClass - * @throws Exception\RuntimeException If resolved class does not exist, or does not implement RouteInterface + * @param array $invokables + * @return array */ - protected function createFromInvokable($canonicalName, $requestedName) + protected function createAliasesForInvokables(array $invokables) { - $invokable = $this->invokableClasses[$canonicalName]; - if (!class_exists($invokable)) { - throw new Exception\RuntimeException(sprintf( - '%s: failed retrieving "%s%s" via invokable class "%s"; class does not exist', - __METHOD__, - $canonicalName, - ($requestedName ? '(alias: ' . $requestedName . ')' : ''), - $invokable - )); + $aliases = []; + foreach ($invokables as $name => $class) { + if ($name === $class) { + continue; + } + $aliases[$name] = $class; } + return $aliases; + } - if (!static::isSubclassOf($invokable, __NAMESPACE__ . '\RouteInterface')) { - throw new Exception\RuntimeException(sprintf( - '%s: failed retrieving "%s%s" via invokable class "%s"; class does not implement %s\RouteInterface', - __METHOD__, - $canonicalName, - ($requestedName ? '(alias: ' . $requestedName . ')' : ''), - $invokable, - __NAMESPACE__ - )); - } + /** + * Create invokable factories for invokable classes. + * + * If an invokable service name does not match the class it maps to, this + * creates an invokable factory entry for the class name; otherwise, it + * creates an invokable factory for the entry name. + * + * @param array $invokables + * @return array + */ + protected function createFactoriesForInvokables(array $invokables) + { + $factories = []; + foreach ($invokables as $name => $class) { + if ($name === $class) { + $factories[$name] = RouteInvokableFactory::class; + continue; + } - return $invokable::factory($this->creationOptions); + $factories[$class] = RouteInvokableFactory::class; + } + return $factories; } } diff --git a/src/Router/SimpleRouteStack.php b/src/Router/SimpleRouteStack.php index 0bee25b81..a89dbde33 100644 --- a/src/Router/SimpleRouteStack.php +++ b/src/Router/SimpleRouteStack.php @@ -10,6 +10,7 @@ namespace Zend\Mvc\Router; use Traversable; +use Zend\ServiceManager\ServiceManager; use Zend\Stdlib\ArrayUtils; use Zend\Stdlib\RequestInterface as Request; @@ -49,7 +50,7 @@ public function __construct(RoutePluginManager $routePluginManager = null) $this->routes = new PriorityList(); if (null === $routePluginManager) { - $routePluginManager = new RoutePluginManager(); + $routePluginManager = new RoutePluginManager(new ServiceManager()); } $this->routePluginManager = $routePluginManager; diff --git a/src/Service/AbstractPluginManagerFactory.php b/src/Service/AbstractPluginManagerFactory.php index 1463fd5d3..11995a97b 100644 --- a/src/Service/AbstractPluginManagerFactory.php +++ b/src/Service/AbstractPluginManagerFactory.php @@ -9,9 +9,9 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\ServiceManager\AbstractPluginManager; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; abstract class AbstractPluginManagerFactory implements FactoryInterface { @@ -19,24 +19,19 @@ abstract class AbstractPluginManagerFactory implements FactoryInterface /** * Create and return a plugin manager. + * * Classes that extend this should provide a valid class for * the PLUGIN_MANGER_CLASS constant. * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return AbstractPluginManager */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { + $options = $options ?: []; $pluginManagerClass = static::PLUGIN_MANAGER_CLASS; - /* @var $plugins AbstractPluginManager */ - $plugins = new $pluginManagerClass; - $plugins->setServiceLocator($serviceLocator); - $configuration = $serviceLocator->get('Config'); - - if (isset($configuration['di']) && $serviceLocator->has('Di')) { - $plugins->addAbstractFactory($serviceLocator->get('DiAbstractServiceFactory')); - } - - return $plugins; + return new $pluginManagerClass($container, $options); } } diff --git a/src/Service/ApplicationFactory.php b/src/Service/ApplicationFactory.php index 5897aba42..a87edb4c8 100644 --- a/src/Service/ApplicationFactory.php +++ b/src/Service/ApplicationFactory.php @@ -9,9 +9,9 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\Mvc\Application; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class ApplicationFactory implements FactoryInterface { @@ -21,17 +21,19 @@ class ApplicationFactory implements FactoryInterface * Creates a Zend\Mvc\Application service, passing it the configuration * service and the service manager instance. * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return Application */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { return new Application( - $serviceLocator->get('Config'), - $serviceLocator, - $serviceLocator->get('EventManager'), - $serviceLocator->get('Request'), - $serviceLocator->get('Response') + $container->get('config'), + $container, + $container->get('EventManager'), + $container->get('Request'), + $container->get('Response') ); } } diff --git a/src/Service/ConfigFactory.php b/src/Service/ConfigFactory.php deleted file mode 100644 index a3683994c..000000000 --- a/src/Service/ConfigFactory.php +++ /dev/null @@ -1,37 +0,0 @@ -get('ModuleManager'); - $mm->loadModules(); - $moduleParams = $mm->getEvent()->getParams(); - $config = $moduleParams['configListener']->getMergedConfig(false); - return $config; - } -} diff --git a/src/Service/ConsoleAdapterFactory.php b/src/Service/ConsoleAdapterFactory.php index 0258653d4..bd4ea3ee8 100644 --- a/src/Service/ConsoleAdapterFactory.php +++ b/src/Service/ConsoleAdapterFactory.php @@ -9,11 +9,11 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use stdClass; use Zend\Console\Adapter\AdapterInterface; use Zend\Console\Console; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class ConsoleAdapterFactory implements FactoryInterface { @@ -35,22 +35,24 @@ class ConsoleAdapterFactory implements FactoryInterface * ) * ) * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return AdapterInterface|stdClass */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { // First, check if we're actually in a Console environment - if (!Console::isConsole()) { + if (! Console::isConsole()) { // SM factory cannot currently return null, so we return dummy object return new stdClass(); } // Read app config and determine Console adapter to use - $config = $serviceLocator->get('Config'); - if (!empty($config['console']) && !empty($config['console']['adapter'])) { + $config = $container->get('config'); + if (! empty($config['console']) && ! empty($config['console']['adapter'])) { // use the adapter supplied in application config - $adapter = $serviceLocator->get($config['console']['adapter']); + $adapter = $container->get($config['console']['adapter']); } else { // try to detect best console adapter $adapter = Console::detectBestAdapter(); @@ -58,15 +60,15 @@ public function createService(ServiceLocatorInterface $serviceLocator) } // check if we have a valid console adapter - if (!$adapter instanceof AdapterInterface) { + if (! $adapter instanceof AdapterInterface) { // SM factory cannot currently return null, so we convert it to dummy object return new stdClass(); } // Optionally, change Console charset - if (!empty($config['console']) && !empty($config['console']['charset'])) { + if (! empty($config['console']) && ! empty($config['console']['charset'])) { // use the charset supplied in application config - $charset = $serviceLocator->get($config['console']['charset']); + $charset = $container->get($config['console']['charset']); $adapter->setCharset($charset); } diff --git a/src/Service/ConsoleExceptionStrategyFactory.php b/src/Service/ConsoleExceptionStrategyFactory.php new file mode 100644 index 000000000..e56ab73dc --- /dev/null +++ b/src/Service/ConsoleExceptionStrategyFactory.php @@ -0,0 +1,60 @@ +getConfig($container); + + $this->injectDisplayExceptions($strategy, $config); + $this->injectExceptionMessage($strategy, $config); + + return $strategy; + } + + /** + * Inject strategy with configured display_exceptions flag. + * + * @param ExceptionStrategy $strategy + * @param array $config + */ + private function injectDisplayExceptions(ExceptionStrategy $strategy, array $config) + { + $flag = array_key_exists('display_exceptions', $config) ? $config['display_exceptions'] : true; + $strategy->setDisplayExceptions($flag); + } + + /** + * Inject strategy with configured exception_message + * + * @param ExceptionStrategy $strategy + * @param array $config + */ + private function injectExceptionMessage(ExceptionStrategy $strategy, array $config) + { + $message = isset($config['exception_message']) ? $config['exception_message'] : ''; + $strategy->setMessage($message); + } +} diff --git a/src/Service/ConsoleRouteNotFoundStrategyFactory.php b/src/Service/ConsoleRouteNotFoundStrategyFactory.php new file mode 100644 index 000000000..43bc723e4 --- /dev/null +++ b/src/Service/ConsoleRouteNotFoundStrategyFactory.php @@ -0,0 +1,47 @@ +getConfig($container); + + $this->injectDisplayNotFoundReason($strategy, $config); + + return $strategy; + } + + /** + * Inject strategy with configured display_not_found_reason flag. + * + * @param RouteNotFoundStrategy $strategy + * @param array $config + */ + private function injectDisplayNotFoundReason(RouteNotFoundStrategy $strategy, array $config) + { + $flag = array_key_exists('display_not_found_reason', $config) ? $config['display_not_found_reason'] : true; + $strategy->setDisplayNotFoundReason($flag); + } +} diff --git a/src/Service/ConsoleRouterFactory.php b/src/Service/ConsoleRouterFactory.php new file mode 100644 index 000000000..2d75e8cc0 --- /dev/null +++ b/src/Service/ConsoleRouterFactory.php @@ -0,0 +1,38 @@ +has('config') ? $container->get('config') : []; + + // Defaults + $class = 'Zend\Mvc\Router\Console\SimpleRouteStack'; + $config = isset($config['console']['router']) ? $config['console']['router'] : []; + + return $this->createRouter($class, $config, $container); + } +} diff --git a/src/Service/ConsoleViewManagerConfigTrait.php b/src/Service/ConsoleViewManagerConfigTrait.php new file mode 100644 index 000000000..21f49dfd2 --- /dev/null +++ b/src/Service/ConsoleViewManagerConfigTrait.php @@ -0,0 +1,39 @@ +has('config') ? $container->get('config') : []; + + if (isset($config['console']['view_manager'])) { + $config = $config['console']['view_manager']; + } elseif (isset($config['view_manager'])) { + $config = $config['view_manager']; + } else { + $config = []; + } + + return (is_array($config) || $config instanceof ArrayAccess) + ? $config + : []; + } +} diff --git a/src/Service/ConsoleViewManagerFactory.php b/src/Service/ConsoleViewManagerFactory.php index e3dfc6653..79cf6f21f 100644 --- a/src/Service/ConsoleViewManagerFactory.php +++ b/src/Service/ConsoleViewManagerFactory.php @@ -9,10 +9,10 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\Console\Console; use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; use Zend\Mvc\View\Console\ViewManager as ConsoleViewManager; class ConsoleViewManagerFactory implements FactoryInterface @@ -20,12 +20,14 @@ class ConsoleViewManagerFactory implements FactoryInterface /** * Create and return the view manager for the console environment * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return ConsoleViewManager */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - if (!Console::isConsole()) { + if (! Console::isConsole()) { throw new ServiceNotCreatedException( 'ConsoleViewManager requires a Console environment; console environment not detected' ); diff --git a/src/Service/ControllerLoaderFactory.php b/src/Service/ControllerLoaderFactory.php deleted file mode 100644 index cf5cda2d0..000000000 --- a/src/Service/ControllerLoaderFactory.php +++ /dev/null @@ -1,48 +0,0 @@ -setServiceLocator($serviceLocator); - $controllerLoader->addPeeringServiceManager($serviceLocator); - - $config = $serviceLocator->get('Config'); - - if (isset($config['di']) && isset($config['di']['allowed_controllers']) && $serviceLocator->has('Di')) { - $controllerLoader->addAbstractFactory($serviceLocator->get('DiStrictAbstractServiceFactory')); - } - - return $controllerLoader; - } -} diff --git a/src/Service/ControllerManagerFactory.php b/src/Service/ControllerManagerFactory.php new file mode 100644 index 000000000..69ad463ac --- /dev/null +++ b/src/Service/ControllerManagerFactory.php @@ -0,0 +1,40 @@ +get('Di'), DiAbstractServiceFactory::USE_SL_BEFORE_DI); - - if ($serviceLocator instanceof ServiceManager) { - /* @var $serviceLocator ServiceManager */ - $serviceLocator->addAbstractFactory($factory, false); - } - - return $factory; - } -} diff --git a/src/Service/DiFactory.php b/src/Service/DiFactory.php deleted file mode 100644 index 9ea5ceaba..000000000 --- a/src/Service/DiFactory.php +++ /dev/null @@ -1,44 +0,0 @@ -get('Config'); - - if (isset($config['di'])) { - $config = new Config($config['di']); - $config->configure($di); - } - - return $di; - } -} diff --git a/src/Service/DiServiceInitializerFactory.php b/src/Service/DiServiceInitializerFactory.php deleted file mode 100644 index 2a2fb1904..000000000 --- a/src/Service/DiServiceInitializerFactory.php +++ /dev/null @@ -1,28 +0,0 @@ -get('Di'), $serviceLocator); - } -} diff --git a/src/Service/DiStrictAbstractServiceFactory.php b/src/Service/DiStrictAbstractServiceFactory.php deleted file mode 100644 index fb367876e..000000000 --- a/src/Service/DiStrictAbstractServiceFactory.php +++ /dev/null @@ -1,142 +0,0 @@ -useServiceLocator = $useServiceLocator; - // since we are using this in a proxy-fashion, localize state - $this->di = $di; - $this->definitions = $this->di->definitions; - $this->instanceManager = $this->di->instanceManager; - } - - /** - * @param array $allowedServiceNames - */ - public function setAllowedServiceNames(array $allowedServiceNames) - { - $this->allowedServiceNames = array_flip(array_values($allowedServiceNames)); - } - - /** - * @return array - */ - public function getAllowedServiceNames() - { - return array_keys($this->allowedServiceNames); - } - - /** - * {@inheritDoc} - * - * Allows creation of services only when in a whitelist - */ - public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $serviceName, $requestedName) - { - if (!isset($this->allowedServiceNames[$requestedName])) { - throw new Exception\InvalidServiceNameException('Service "' . $requestedName . '" is not whitelisted'); - } - - if ($serviceLocator instanceof AbstractPluginManager) { - /* @var $serviceLocator AbstractPluginManager */ - $this->serviceLocator = $serviceLocator->getServiceLocator(); - } else { - $this->serviceLocator = $serviceLocator; - } - - return parent::get($requestedName); - } - - /** - * Overrides Zend\Di to allow the given serviceLocator's services to be reused by Di itself - * - * {@inheritDoc} - * - * @throws Exception\InvalidServiceNameException - */ - public function get($name, array $params = []) - { - if (null === $this->serviceLocator) { - throw new DomainException('No ServiceLocator defined, use `createServiceWithName` instead of `get`'); - } - - if (self::USE_SL_BEFORE_DI === $this->useServiceLocator && $this->serviceLocator->has($name)) { - return $this->serviceLocator->get($name); - } - - try { - return parent::get($name, $params); - } catch (ClassNotFoundException $e) { - if (self::USE_SL_AFTER_DI === $this->useServiceLocator && $this->serviceLocator->has($name)) { - return $this->serviceLocator->get($name); - } - - throw new Exception\ServiceNotFoundException( - sprintf('Service %s was not found in this DI instance', $name), - null, - $e - ); - } - } - - /** - * {@inheritDoc} - * - * Allows creation of services only when in a whitelist - */ - public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName) - { - // won't check if the service exists, we are trusting the user's whitelist - return isset($this->allowedServiceNames[$requestedName]); - } -} diff --git a/src/Service/DiStrictAbstractServiceFactoryFactory.php b/src/Service/DiStrictAbstractServiceFactoryFactory.php deleted file mode 100644 index 54dd3335a..000000000 --- a/src/Service/DiStrictAbstractServiceFactoryFactory.php +++ /dev/null @@ -1,37 +0,0 @@ -get('Di'), - DiStrictAbstractServiceFactory::USE_SL_BEFORE_DI - ); - $config = $serviceLocator->get('Config'); - - if (isset($config['di']['allowed_controllers'])) { - $diAbstractFactory->setAllowedServiceNames($config['di']['allowed_controllers']); - } - - return $diAbstractFactory; - } -} diff --git a/src/Service/DispatchListenerFactory.php b/src/Service/DispatchListenerFactory.php new file mode 100644 index 000000000..75c375f7e --- /dev/null +++ b/src/Service/DispatchListenerFactory.php @@ -0,0 +1,30 @@ +get('ControllerManager')); + } +} diff --git a/src/Service/EventManagerFactory.php b/src/Service/EventManagerFactory.php index e23238ddb..0f4352afe 100644 --- a/src/Service/EventManagerFactory.php +++ b/src/Service/EventManagerFactory.php @@ -9,9 +9,9 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\EventManager\EventManager; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class EventManagerFactory implements FactoryInterface { @@ -21,13 +21,15 @@ class EventManagerFactory implements FactoryInterface * Creates a new EventManager instance, seeding it with a shared instance * of SharedEventManager. * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return EventManager */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - if ($serviceLocator->has('SharedEventManager')) { - return new EventManager($serviceLocator->get('SharedEventManager')); + if ($container->has('SharedEventManager')) { + return new EventManager($container->get('SharedEventManager')); } return new EventManager(); } diff --git a/src/Service/FilterManagerFactory.php b/src/Service/FilterManagerFactory.php index d9a9e1722..b95fabd68 100644 --- a/src/Service/FilterManagerFactory.php +++ b/src/Service/FilterManagerFactory.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Service; +use Zend\Filter\FilterPluginManager; + class FilterManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\Filter\FilterPluginManager'; + const PLUGIN_MANAGER_CLASS = FilterPluginManager::class; } diff --git a/src/Service/FormAnnotationBuilderFactory.php b/src/Service/FormAnnotationBuilderFactory.php index 873b68a39..60f33bc87 100644 --- a/src/Service/FormAnnotationBuilderFactory.php +++ b/src/Service/FormAnnotationBuilderFactory.php @@ -9,29 +9,34 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\EventManager\ListenerAggregateInterface; use Zend\Form\Annotation\AnnotationBuilder; -use Zend\ServiceManager\Exception\RuntimeException; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Exception\ServiceNotCreatedException; +use Zend\ServiceManager\Factory\FactoryInterface; class FormAnnotationBuilderFactory implements FactoryInterface { /** * Create service * - * @param ServiceLocatorInterface $serviceLocator - * @throws \Zend\ServiceManager\Exception\RuntimeException + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return mixed + * @throws ServiceNotCreatedException for invalid listener configuration. */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { //setup a form factory which can use custom form elements $annotationBuilder = new AnnotationBuilder(); - $formElementManager = $serviceLocator->get('FormElementManager'); + $eventManager = $container->build('EventManager'); + $annotationBuilder->setEventManager($ventManager); + + $formElementManager = $container->get('FormElementManager'); $formElementManager->injectFactory($annotationBuilder); - $config = $serviceLocator->get('Config'); + $config = $container->get('config'); if (isset($config['form_annotation_builder'])) { $config = $config['form_annotation_builder']; @@ -43,11 +48,11 @@ public function createService(ServiceLocatorInterface $serviceLocator) if (isset($config['listeners'])) { foreach ((array) $config['listeners'] as $listenerName) { - $listener = $serviceLocator->get($listenerName); + $listener = $container->get($listenerName); if (!($listener instanceof ListenerAggregateInterface)) { - throw new RuntimeException(sprintf('Invalid event listener (%s) provided', $listenerName)); + throw new ServiceNotCreatedException(sprintf('Invalid event listener (%s) provided', $listenerName)); } - $listener->attach($annotationBuilder->getEventManager()); + $listener->attach($eventManager); } } diff --git a/src/Service/FormElementManagerFactory.php b/src/Service/FormElementManagerFactory.php index e33dd87eb..4f5f33bc2 100644 --- a/src/Service/FormElementManagerFactory.php +++ b/src/Service/FormElementManagerFactory.php @@ -10,23 +10,8 @@ namespace Zend\Mvc\Service; use Zend\Form\FormElementManager; -use Zend\ServiceManager\ServiceLocatorInterface; class FormElementManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\Form\FormElementManager'; - - /** - * Create and return the MVC controller plugin manager - * - * @param ServiceLocatorInterface $serviceLocator - * @return FormElementManager - */ - public function createService(ServiceLocatorInterface $serviceLocator) - { - $plugins = parent::createService($serviceLocator); - $plugins->addPeeringServiceManager($serviceLocator); - $plugins->setRetrieveFromPeeringManagerFirst(true); - return $plugins; - } + const PLUGIN_MANAGER_CLASS = FormElementManager::class; } diff --git a/src/Service/HttpDefaultRenderingStrategyFactory.php b/src/Service/HttpDefaultRenderingStrategyFactory.php new file mode 100644 index 000000000..19a7f5a6d --- /dev/null +++ b/src/Service/HttpDefaultRenderingStrategyFactory.php @@ -0,0 +1,42 @@ +get(View::class)); + $config = $this->getConfig($container); + + $this->injectLayoutTemplate($strategy, $config); + + return $strategy; + } + + private function injectLayoutTemplate(DefaultRenderingStrategy $strategy, array $config) + { + $layout = isset($config['layout']) ? $config['layout'] : 'layout/layout'; + $strategy->setLayoutTemplate($layout); + } +} diff --git a/src/Service/HttpExceptionStrategyFactory.php b/src/Service/HttpExceptionStrategyFactory.php new file mode 100644 index 000000000..51555f436 --- /dev/null +++ b/src/Service/HttpExceptionStrategyFactory.php @@ -0,0 +1,60 @@ +getConfig($container); + + $this->injectDisplayExceptions($strategy, $config); + $this->injectExceptionTemplate($strategy, $config); + + return $strategy; + } + + /** + * Inject strategy with configured display_exceptions flag. + * + * @param ExceptionStrategy $strategy + * @param array $config + */ + private function injectDisplayExceptions(ExceptionStrategy $strategy, array $config) + { + $flag = isset($config['display_exceptions']) ? $config['display_exceptions'] : false; + $strategy->setDisplayExceptions($flag); + } + + /** + * Inject strategy with configured exception_template + * + * @param ExceptionStrategy $strategy + * @param array $config + */ + private function injectExceptionTemplate(ExceptionStrategy $strategy, array $config) + { + $template = isset($config['exception_template']) ? $config['exception_template'] : 'error'; + $strategy->setExceptionTemplate($template); + } +} diff --git a/src/Service/HttpMethodListenerFactory.php b/src/Service/HttpMethodListenerFactory.php index 46ea25eeb..d4c83f3dc 100644 --- a/src/Service/HttpMethodListenerFactory.php +++ b/src/Service/HttpMethodListenerFactory.php @@ -9,9 +9,9 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\Mvc\HttpMethodListener; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class HttpMethodListenerFactory implements FactoryInterface { @@ -19,9 +19,9 @@ class HttpMethodListenerFactory implements FactoryInterface * {@inheritdoc} * @return HttpMethodListener */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $config = $serviceLocator->get('config'); + $config = $container->get('config'); if (! isset($config['http_methods_listener'])) { return new HttpMethodListener(); diff --git a/src/Service/HttpRouteNotFoundStrategyFactory.php b/src/Service/HttpRouteNotFoundStrategyFactory.php new file mode 100644 index 000000000..afb5b9d8a --- /dev/null +++ b/src/Service/HttpRouteNotFoundStrategyFactory.php @@ -0,0 +1,73 @@ +getConfig($container); + + $this->injectDisplayExceptions($strategy, $config); + $this->injectDisplayNotFoundReason($strategy, $config); + $this->injectNotFoundTemplate($strategy, $config); + + return $strategy; + } + + /** + * Inject strategy with configured display_exceptions flag. + * + * @param RouteNotFoundStrategy $strategy + * @param array $config + */ + private function injectDisplayExceptions(RouteNotFoundStrategy $strategy, array $config) + { + $flag = isset($config['display_exceptions']) ? $config['display_exceptions'] : false; + $strategy->setDisplayExceptions($flag); + } + + /** + * Inject strategy with configured display_not_found_reason flag. + * + * @param RouteNotFoundStrategy $strategy + * @param array $config + */ + private function injectDisplayNotFoundReason(RouteNotFoundStrategy $strategy, array $config) + { + $flag = isset($config['display_not_found_reason']) ? $config['display_not_found_reason'] : false; + $strategy->setDisplayNotFoundReason($flag); + } + + /** + * Inject strategy with configured not_found_template. + * + * @param RouteNotFoundStrategy $strategy + * @param array $config + */ + private function injectNotFoundTemplate(RouteNotFoundStrategy $strategy, array $config) + { + $template = isset($config['not_found_template']) ? $config['not_found_template'] : '404'; + $strategy->setNotFoundTemplate($template); + } +} diff --git a/src/Service/HttpRouterFactory.php b/src/Service/HttpRouterFactory.php new file mode 100644 index 000000000..c2f288794 --- /dev/null +++ b/src/Service/HttpRouterFactory.php @@ -0,0 +1,41 @@ +has('config') ? $container->get('config') : []; + + // Defaults + $class = 'Zend\Mvc\Router\Http\TreeRouteStack'; + $config = isset($config['router']) ? $config['router'] : []; + + return $this->createRouter($class, $config, $container); + } +} diff --git a/src/Service/HttpViewManagerConfigTrait.php b/src/Service/HttpViewManagerConfigTrait.php new file mode 100644 index 000000000..24239f507 --- /dev/null +++ b/src/Service/HttpViewManagerConfigTrait.php @@ -0,0 +1,37 @@ +has('config') ? $container->get('config') : []; + + if (isset($config['view_manager']) + && (is_array($config['view_manager']) + || $config['view_manager'] instanceof ArrayAccess + ) + ) { + return $config['view_manager']; + } + + return []; + } +} diff --git a/src/Service/HttpViewManagerFactory.php b/src/Service/HttpViewManagerFactory.php index 5c61bad97..8c68e726b 100644 --- a/src/Service/HttpViewManagerFactory.php +++ b/src/Service/HttpViewManagerFactory.php @@ -9,19 +9,21 @@ namespace Zend\Mvc\Service; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; use Zend\Mvc\View\Http\ViewManager as HttpViewManager; +use Zend\ServiceManager\Factory\FactoryInterface; class HttpViewManagerFactory implements FactoryInterface { /** * Create and return a view manager for the HTTP environment * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return HttpViewManager */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { return new HttpViewManager(); } diff --git a/src/Service/HydratorManagerFactory.php b/src/Service/HydratorManagerFactory.php index 436a01223..7d889a9e8 100644 --- a/src/Service/HydratorManagerFactory.php +++ b/src/Service/HydratorManagerFactory.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Service; +use Zend\Hydrator\HydratorPluginManager; + class HydratorManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\Hydrator\HydratorPluginManager'; + const PLUGIN_MANAGER_CLASS = HydratorPluginManager::class; } diff --git a/src/Service/InjectTemplateListenerFactory.php b/src/Service/InjectTemplateListenerFactory.php index e0bac2e1f..ef9ab8bd0 100644 --- a/src/Service/InjectTemplateListenerFactory.php +++ b/src/Service/InjectTemplateListenerFactory.php @@ -9,9 +9,9 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\Mvc\View\Http\InjectTemplateListener; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class InjectTemplateListenerFactory implements FactoryInterface { @@ -22,10 +22,10 @@ class InjectTemplateListenerFactory implements FactoryInterface * * @return InjectTemplateListener */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { $listener = new InjectTemplateListener(); - $config = $serviceLocator->get('Config'); + $config = $container->get('config'); if (isset($config['view_manager']['controller_map']) && (is_array($config['view_manager']['controller_map'])) diff --git a/src/Service/InputFilterManagerFactory.php b/src/Service/InputFilterManagerFactory.php index 14806f7f8..8878b78de 100644 --- a/src/Service/InputFilterManagerFactory.php +++ b/src/Service/InputFilterManagerFactory.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Service; +use Zend\InputFilter\InputFilterPluginManager; + class InputFilterManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\InputFilter\InputFilterPluginManager'; + const PLUGIN_MANAGER_CLASS = InputFilterPluginManager::class; } diff --git a/src/Service/LogProcessorManagerFactory.php b/src/Service/LogProcessorManagerFactory.php index fa3f884e8..cab6e2ea6 100644 --- a/src/Service/LogProcessorManagerFactory.php +++ b/src/Service/LogProcessorManagerFactory.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Service; +use Zend\Log\ProcessorPluginManager as LogProcessorPluginManager; + class LogProcessorManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\Log\ProcessorPluginManager'; + const PLUGIN_MANAGER_CLASS = LogProcessorPluginManager::class; } diff --git a/src/Service/LogWriterManagerFactory.php b/src/Service/LogWriterManagerFactory.php index b858dbe3c..6a984c0ab 100644 --- a/src/Service/LogWriterManagerFactory.php +++ b/src/Service/LogWriterManagerFactory.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Service; +use Zend\Log\WriterPluginManager as LogWriterPluginManager; + class LogWriterManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\Log\WriterPluginManager'; + const PLUGIN_MANAGER_CLASS = LogWriterPluginManager::class; } diff --git a/src/Service/ModuleManagerFactory.php b/src/Service/ModuleManagerFactory.php index 82a3b6f3e..a295bdd88 100644 --- a/src/Service/ModuleManagerFactory.php +++ b/src/Service/ModuleManagerFactory.php @@ -9,12 +9,12 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\ModuleManager\Listener\DefaultListenerAggregate; use Zend\ModuleManager\Listener\ListenerOptions; use Zend\ModuleManager\ModuleEvent; use Zend\ModuleManager\ModuleManager; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class ModuleManagerFactory implements FactoryInterface { @@ -29,28 +29,26 @@ class ModuleManagerFactory implements FactoryInterface * the default listener aggregate is attached. The ModuleEvent is also created * and attached to the module manager. * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return ModuleManager */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - if (!$serviceLocator->has('ServiceListener')) { - $serviceLocator->setFactory('ServiceListener', 'Zend\Mvc\Service\ServiceListenerFactory'); - } - - $configuration = $serviceLocator->get('ApplicationConfig'); + $configuration = $container->get('ApplicationConfig'); $listenerOptions = new ListenerOptions($configuration['module_listener_options']); $defaultListeners = new DefaultListenerAggregate($listenerOptions); - $serviceListener = $serviceLocator->get('ServiceListener'); + $serviceListener = $container->get('ServiceListener'); - $serviceListener->addServiceManager( - $serviceLocator, + $serviceListener->setApplicationServiceManager( 'service_manager', 'Zend\ModuleManager\Feature\ServiceProviderInterface', 'getServiceConfig' ); + $serviceListener->addServiceManager( - 'ControllerLoader', + 'ControllerManager', 'controllers', 'Zend\ModuleManager\Feature\ControllerProviderInterface', 'getControllerConfig' @@ -128,12 +126,12 @@ public function createService(ServiceLocatorInterface $serviceLocator) 'getTranslatorPluginConfig' ); - $events = $serviceLocator->get('EventManager'); + $events = $container->get('EventManager'); $defaultListeners->attach($events); $serviceListener->attach($events); $moduleEvent = new ModuleEvent; - $moduleEvent->setParam('ServiceManager', $serviceLocator); + $moduleEvent->setParam('ServiceManager', $container); $moduleManager = new ModuleManager($configuration['modules'], $events); $moduleManager->setEvent($moduleEvent); diff --git a/src/Service/PaginatorPluginManagerFactory.php b/src/Service/PaginatorPluginManagerFactory.php index 182a53a40..547db292d 100644 --- a/src/Service/PaginatorPluginManagerFactory.php +++ b/src/Service/PaginatorPluginManagerFactory.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Service; +use Zend\Paginator\AdapterPluginManager as PaginatorPluginManager; + class PaginatorPluginManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\Paginator\AdapterPluginManager'; + const PLUGIN_MANAGER_CLASS = PaginatorPluginManager::class; } diff --git a/src/Service/RequestFactory.php b/src/Service/RequestFactory.php index 3c5d4a5c1..88a0a5a4c 100644 --- a/src/Service/RequestFactory.php +++ b/src/Service/RequestFactory.php @@ -9,21 +9,23 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\Console\Console; use Zend\Console\Request as ConsoleRequest; use Zend\Http\PhpEnvironment\Request as HttpRequest; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class RequestFactory implements FactoryInterface { /** * Create and return a request instance, according to current environment. * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return ConsoleRequest|HttpRequest */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { if (Console::isConsole()) { return new ConsoleRequest(); diff --git a/src/Service/ResponseFactory.php b/src/Service/ResponseFactory.php index 707e6c9dd..9b0b24bad 100644 --- a/src/Service/ResponseFactory.php +++ b/src/Service/ResponseFactory.php @@ -9,21 +9,23 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\Console\Console; use Zend\Console\Response as ConsoleResponse; use Zend\Http\PhpEnvironment\Response as HttpResponse; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class ResponseFactory implements FactoryInterface { /** * Create and return a response instance, according to current environment. * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return \Zend\Stdlib\Message */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { if (Console::isConsole()) { return new ConsoleResponse(); diff --git a/src/Service/RoutePluginManagerFactory.php b/src/Service/RoutePluginManagerFactory.php index 2f24b8581..1752f6150 100644 --- a/src/Service/RoutePluginManagerFactory.php +++ b/src/Service/RoutePluginManagerFactory.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Service; +use Zend\Mvc\Router\RoutePluginManager; + class RoutePluginManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\Mvc\Router\RoutePluginManager'; + const PLUGIN_MANAGER_CLASS = RoutePluginManager::class; } diff --git a/src/Service/RouterConfigTrait.php b/src/Service/RouterConfigTrait.php new file mode 100644 index 000000000..fb7b08bdf --- /dev/null +++ b/src/Service/RouterConfigTrait.php @@ -0,0 +1,40 @@ +get('RoutePluginManager'); + $config['route_plugins'] = $routePluginManager; + } + + // Obtain an instance + $factory = sprintf('%s::factory', $class); + return call_user_func($factory, $config); + } +} diff --git a/src/Service/RouterFactory.php b/src/Service/RouterFactory.php index be58c8f7e..100df18de 100644 --- a/src/Service/RouterFactory.php +++ b/src/Service/RouterFactory.php @@ -9,54 +9,32 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\Console\Console; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class RouterFactory implements FactoryInterface { /** * Create and return the router * - * Retrieves the "router" key of the Config service, and uses it - * to instantiate the router. Uses the TreeRouteStack implementation by - * default. + * Delegates to either the ConsoleRouter or HttpRouter service based + * on the environment type. * - * @param ServiceLocatorInterface $serviceLocator - * @param string|null $cName - * @param string|null $rName + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return \Zend\Mvc\Router\RouteStackInterface */ - public function createService(ServiceLocatorInterface $serviceLocator, $cName = null, $rName = null) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $config = $serviceLocator->has('Config') ? $serviceLocator->get('Config') : []; - - // Defaults - $routerClass = 'Zend\Mvc\Router\Http\TreeRouteStack'; - $routerConfig = isset($config['router']) ? $config['router'] : []; - // Console environment? - if ($rName === 'ConsoleRouter' // force console router - || ($cName === 'router' && Console::isConsole()) // auto detect console + if ($name === 'ConsoleRouter' // force console router + || (strtolower($name) === 'router' && Console::isConsole()) // auto detect console ) { - // We are in a console, use console router defaults. - $routerClass = 'Zend\Mvc\Router\Console\SimpleRouteStack'; - $routerConfig = isset($config['console']['router']) ? $config['console']['router'] : []; - } - - // Obtain the configured router class, if any - if (isset($routerConfig['router_class']) && class_exists($routerConfig['router_class'])) { - $routerClass = $routerConfig['router_class']; - } - - // Inject the route plugins - if (!isset($routerConfig['route_plugins'])) { - $routePluginManager = $serviceLocator->get('RoutePluginManager'); - $routerConfig['route_plugins'] = $routePluginManager; + return $container->get('ConsoleRouter'); } - // Obtain an instance - $factory = sprintf('%s::factory', $routerClass); - return call_user_func($factory, $routerConfig); + return $container->get('HttpRouter'); } } diff --git a/src/Service/SerializerAdapterPluginManagerFactory.php b/src/Service/SerializerAdapterPluginManagerFactory.php index 11d1653ca..005001d4d 100644 --- a/src/Service/SerializerAdapterPluginManagerFactory.php +++ b/src/Service/SerializerAdapterPluginManagerFactory.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Service; +use Zend\Serializer\AdapterPluginManager as SerializerAdapterPluginManager; + class SerializerAdapterPluginManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\Serializer\AdapterPluginManager'; + const PLUGIN_MANAGER_CLASS = SerializerAdapterPluginManager::class; } diff --git a/src/Service/ServiceListenerFactory.php b/src/Service/ServiceListenerFactory.php index 299c2b3f0..a5005fea0 100644 --- a/src/Service/ServiceListenerFactory.php +++ b/src/Service/ServiceListenerFactory.php @@ -9,12 +9,13 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\ModuleManager\Listener\ServiceListener; use Zend\ModuleManager\Listener\ServiceListenerInterface; -use Zend\Mvc\Exception\InvalidArgumentException; -use Zend\Mvc\Exception\RuntimeException; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\Mvc\View; +use Zend\ServiceManager\Exception\ServiceNotCreatedException; +use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\Factory\InvokableFactory; class ServiceListenerFactory implements FactoryInterface { @@ -31,11 +32,11 @@ class ServiceListenerFactory implements FactoryInterface /** * Default mvc-related service configuration -- can be overridden by modules. * + * @todo Re-enable form abstract service factory after zend-form updated to servicemanager v3. * @var array */ protected $defaultServiceConfig = [ 'invokables' => [ - 'DispatchListener' => 'Zend\Mvc\DispatchListener', 'RouteListener' => 'Zend\Mvc\RouteListener', 'SendResponseListener' => 'Zend\Mvc\SendResponseListener', 'ViewJsonRenderer' => 'Zend\View\Renderer\JsonRenderer', @@ -43,21 +44,22 @@ class ServiceListenerFactory implements FactoryInterface ], 'factories' => [ 'Application' => 'Zend\Mvc\Service\ApplicationFactory', - 'Config' => 'Zend\Mvc\Service\ConfigFactory', - 'ControllerLoader' => 'Zend\Mvc\Service\ControllerLoaderFactory', + 'config' => 'Zend\Mvc\Service\ConfigFactory', + 'ControllerManager' => 'Zend\Mvc\Service\ControllerManagerFactory', 'ControllerPluginManager' => 'Zend\Mvc\Service\ControllerPluginManagerFactory', 'ConsoleAdapter' => 'Zend\Mvc\Service\ConsoleAdapterFactory', - 'ConsoleRouter' => 'Zend\Mvc\Service\RouterFactory', + 'ConsoleExceptionStrategy' => ConsoleExceptionStrategyFactory::class, + 'ConsoleRouter' => ConsoleRouterFactory::class, + 'ConsoleRouteNotFoundStrategy' => ConsoleRouteNotFoundStrategyFactory::class, 'ConsoleViewManager' => 'Zend\Mvc\Service\ConsoleViewManagerFactory', - 'DependencyInjector' => 'Zend\Mvc\Service\DiFactory', - 'DiAbstractServiceFactory' => 'Zend\Mvc\Service\DiAbstractServiceFactoryFactory', - 'DiServiceInitializer' => 'Zend\Mvc\Service\DiServiceInitializerFactory', - 'DiStrictAbstractServiceFactory' => 'Zend\Mvc\Service\DiStrictAbstractServiceFactoryFactory', + 'DispatchListener' => 'Zend\Mvc\Service\DispatchListenerFactory', 'FilterManager' => 'Zend\Mvc\Service\FilterManagerFactory', 'FormAnnotationBuilder' => 'Zend\Mvc\Service\FormAnnotationBuilderFactory', 'FormElementManager' => 'Zend\Mvc\Service\FormElementManagerFactory', - 'HttpRouter' => 'Zend\Mvc\Service\RouterFactory', + 'HttpExceptionStrategy' => HttpExceptionStrategyFactory::class, 'HttpMethodListener' => 'Zend\Mvc\Service\HttpMethodListenerFactory', + 'HttpRouteNotFoundStrategy' => HttpRouteNotFoundStrategyFactory::class, + 'HttpRouter' => HttpRouterFactory::class, 'HttpViewManager' => 'Zend\Mvc\Service\HttpViewManagerFactory', 'HydratorManager' => 'Zend\Mvc\Service\HydratorManagerFactory', 'InjectTemplateListener' => 'Zend\Mvc\Service\InjectTemplateListenerFactory', @@ -73,7 +75,9 @@ class ServiceListenerFactory implements FactoryInterface 'SerializerAdapterManager' => 'Zend\Mvc\Service\SerializerAdapterPluginManagerFactory', 'TranslatorPluginManager' => 'Zend\Mvc\Service\TranslatorPluginManagerFactory', 'ValidatorManager' => 'Zend\Mvc\Service\ValidatorManagerFactory', + View\Console\DefaultRenderingStrategy::class => InvokableFactory::class, 'ViewHelperManager' => 'Zend\Mvc\Service\ViewHelperManagerFactory', + View\Http\DefaultRenderingStrategy::class => HttpDefaultRenderingStrategyFactory::class, 'ViewFeedStrategy' => 'Zend\Mvc\Service\ViewFeedStrategyFactory', 'ViewJsonStrategy' => 'Zend\Mvc\Service\ViewJsonStrategyFactory', 'ViewManager' => 'Zend\Mvc\Service\ViewManagerFactory', @@ -81,24 +85,35 @@ class ServiceListenerFactory implements FactoryInterface 'ViewTemplateMapResolver' => 'Zend\Mvc\Service\ViewTemplateMapResolverFactory', 'ViewTemplatePathStack' => 'Zend\Mvc\Service\ViewTemplatePathStackFactory', 'ViewPrefixPathStackResolver' => 'Zend\Mvc\Service\ViewPrefixPathStackResolverFactory', + 'Zend\View\Renderer\PhpRenderer' => ViewPhpRendererFactory::class, + 'Zend\View\Strategy\PhpRendererStrategy' => ViewPhpRendererStrategyFactory::class, + 'Zend\View\View' => ViewFactory::class, ], 'aliases' => [ - 'Configuration' => 'Config', + 'Config' => 'config', + 'Configuration' => 'config', + 'configuration' => 'config', 'Console' => 'ConsoleAdapter', - 'Di' => 'DependencyInjector', - 'Zend\Di\LocatorInterface' => 'DependencyInjector', + 'ConsoleDefaultRenderingStrategy' => View\Console\DefaultRenderingStrategy::class, + 'HttpDefaultRenderingStrategy' => View\Http\DefaultRenderingStrategy::class, + 'View' => 'Zend\View\View', + 'ViewPhpRendererStrategy' => 'Zend\View\Strategy\PhpRendererStrategy', + 'ViewPhpRenderer' => 'Zend\View\Renderer\PhpRenderer', + 'ViewRenderer' => 'Zend\View\Renderer\PhpRenderer', 'Zend\Form\Annotation\FormAnnotationBuilder' => 'FormAnnotationBuilder', 'Zend\Mvc\Controller\PluginManager' => 'ControllerPluginManager', 'Zend\Mvc\View\Http\InjectTemplateListener' => 'InjectTemplateListener', + 'Zend\View\Renderer\RendererInterface' => 'Zend\View\Renderer\PhpRenderer', 'Zend\View\Resolver\TemplateMapResolver' => 'ViewTemplateMapResolver', 'Zend\View\Resolver\TemplatePathStack' => 'ViewTemplatePathStack', 'Zend\View\Resolver\AggregateResolver' => 'ViewResolver', 'Zend\View\Resolver\ResolverInterface' => 'ViewResolver', - 'ControllerManager' => 'ControllerLoader', ], + /* 'abstract_factories' => [ 'Zend\Form\FormAbstractServiceFactory', ], + */ ]; /** @@ -120,83 +135,125 @@ class ServiceListenerFactory implements FactoryInterface * * @param ServiceLocatorInterface $serviceLocator * @return ServiceListener - * @throws InvalidArgumentException For invalid configurations. - * @throws RuntimeException + * @throws ServiceNotCreatedException for invalid ServiceListener service + * @throws ServiceNotCreatedException For invalid configurations. */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { - $configuration = $serviceLocator->get('ApplicationConfig'); + $configuration = $container->get('ApplicationConfig'); - if ($serviceLocator->has('ServiceListenerInterface')) { - $serviceListener = $serviceLocator->get('ServiceListenerInterface'); + $serviceListener = $container->has('ServiceListenerInterface') + ? $container->get('ServiceListenerInterface') + : new ServiceListener($container, $this->defaultServiceConfig); - if (!$serviceListener instanceof ServiceListenerInterface) { - throw new RuntimeException( - 'The service named ServiceListenerInterface must implement ' . - 'Zend\ModuleManager\Listener\ServiceListenerInterface' - ); - } - - $serviceListener->setDefaultServiceConfig($this->defaultServiceConfig); - } else { - $serviceListener = new ServiceListener($serviceLocator, $this->defaultServiceConfig); + if (! $serviceListener instanceof ServiceListenerInterface) { + throw new ServiceNotCreatedException( + 'The service named ServiceListenerInterface must implement ' . + 'Zend\ModuleManager\Listener\ServiceListenerInterface' + ); } if (isset($configuration['service_listener_options'])) { - if (!is_array($configuration['service_listener_options'])) { - throw new InvalidArgumentException(sprintf( - 'The value of service_listener_options must be an array, %s given.', - gettype($configuration['service_listener_options']) - )); - } - - foreach ($configuration['service_listener_options'] as $key => $newServiceManager) { - if (!isset($newServiceManager['service_manager'])) { - throw new InvalidArgumentException(sprintf(self::MISSING_KEY_ERROR, $key, 'service_manager')); - } elseif (!is_string($newServiceManager['service_manager'])) { - throw new InvalidArgumentException(sprintf( - self::VALUE_TYPE_ERROR, - 'service_manager', - gettype($newServiceManager['service_manager']) - )); - } - if (!isset($newServiceManager['config_key'])) { - throw new InvalidArgumentException(sprintf(self::MISSING_KEY_ERROR, $key, 'config_key')); - } elseif (!is_string($newServiceManager['config_key'])) { - throw new InvalidArgumentException(sprintf( - self::VALUE_TYPE_ERROR, - 'config_key', - gettype($newServiceManager['config_key']) - )); - } - if (!isset($newServiceManager['interface'])) { - throw new InvalidArgumentException(sprintf(self::MISSING_KEY_ERROR, $key, 'interface')); - } elseif (!is_string($newServiceManager['interface'])) { - throw new InvalidArgumentException(sprintf( - self::VALUE_TYPE_ERROR, - 'interface', - gettype($newServiceManager['interface']) - )); - } - if (!isset($newServiceManager['method'])) { - throw new InvalidArgumentException(sprintf(self::MISSING_KEY_ERROR, $key, 'method')); - } elseif (!is_string($newServiceManager['method'])) { - throw new InvalidArgumentException(sprintf( - self::VALUE_TYPE_ERROR, - 'method', - gettype($newServiceManager['method']) - )); - } - - $serviceListener->addServiceManager( - $newServiceManager['service_manager'], - $newServiceManager['config_key'], - $newServiceManager['interface'], - $newServiceManager['method'] - ); - } + $this->injectServiceListenerOptions($configuration['service_listener_options'], $serviceListener); } return $serviceListener; } + + /** + * Validate and inject plugin manager options into the service listener. + * + * @param array $options + * @param ServiceListenerInterface $serviceListener + * @throws ServiceListenerInterface for invalid $options types + */ + private function injectServiceListenerOptions($options, ServiceListenerInterface $serviceListener) + { + if (! is_array($options)) { + throw new ServiceNotCreatedException(sprintf( + 'The value of service_listener_options must be an array, %s given.', + (is_object($options) ? get_class($options) : gettype($options)) + )); + } + + foreach ($options as $key => $newServiceManager) { + $this->validatePluginManagerOptions($newServiceManager, $key); + + $serviceListener->addServiceManager( + $newServiceManager['service_manager'], + $newServiceManager['config_key'], + $newServiceManager['interface'], + $newServiceManager['method'] + ); + } + } + + /** + * Validate the structure and types for plugin manager configuration options. + * + * Ensures all required keys are present in the expected types. + * + * @param array $options + * @param string $name Plugin manager service name; used for exception messages + * @throws ServiceNotCreatedException for any missing configuration options. + * @throws ServiceNotCreatedException for configuration options of invalid types. + */ + private function validatePluginManagerOptions($options, $name) + { + if (! is_array($options)) { + throw new ServiceNotCreatedException(sprintf( + 'Plugin manager configuration for "%s" is invalid; must be an array, received "%s"', + $name, + (is_object($options) ? get_class($options) : gettype($options)) + )); + } + + if (! isset($options['service_manager'])) { + throw new ServiceNotCreatedException(sprintf(self::MISSING_KEY_ERROR, $name, 'service_manager')); + } + + if (! is_string($options['service_manager'])) { + throw new ServiceNotCreatedException(sprintf( + self::VALUE_TYPE_ERROR, + 'service_manager', + gettype($options['service_manager']) + )); + } + + if (! isset($options['config_key'])) { + throw new ServiceNotCreatedException(sprintf(self::MISSING_KEY_ERROR, $name, 'config_key')); + } + + if (! is_string($options['config_key'])) { + throw new ServiceNotCreatedException(sprintf( + self::VALUE_TYPE_ERROR, + 'config_key', + gettype($options['config_key']) + )); + } + + if (! isset($options['interface'])) { + throw new ServiceNotCreatedException(sprintf(self::MISSING_KEY_ERROR, $name, 'interface')); + } + + if (! is_string($options['interface'])) { + throw new ServiceNotCreatedException(sprintf( + self::VALUE_TYPE_ERROR, + 'interface', + gettype($options['interface']) + )); + } + + if (! isset($options['method'])) { + throw new ServiceNotCreatedException(sprintf(self::MISSING_KEY_ERROR, $name, 'method')); + } + + if (! is_string($options['method'])) { + throw new ServiceNotCreatedException(sprintf( + self::VALUE_TYPE_ERROR, + 'method', + gettype($options['method']) + )); + } + } } diff --git a/src/Service/ServiceManagerConfig.php b/src/Service/ServiceManagerConfig.php index 304c3b81b..f1c363b80 100644 --- a/src/Service/ServiceManagerConfig.php +++ b/src/Service/ServiceManagerConfig.php @@ -9,81 +9,38 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\EventManager\EventManagerAwareInterface; use Zend\EventManager\EventManagerInterface; use Zend\EventManager\SharedEventManagerInterface; use Zend\ServiceManager\Config; -use Zend\ServiceManager\ServiceLocatorAwareInterface; -use Zend\ServiceManager\ServiceLocatorInterface; use Zend\ServiceManager\ServiceManager; -use Zend\ServiceManager\ServiceManagerAwareInterface; -use Zend\Stdlib\ArrayUtils; class ServiceManagerConfig extends Config { - /** - * Services that can be instantiated without factories - * - * @var array - */ - protected $invokables = [ - 'SharedEventManager' => 'Zend\EventManager\SharedEventManager', - ]; - - /** - * Service factories - * - * @var array - */ - protected $factories = [ - 'EventManager' => 'Zend\Mvc\Service\EventManagerFactory', - 'ModuleManager' => 'Zend\Mvc\Service\ModuleManagerFactory', - ]; - - /** - * Abstract factories - * - * @var array - */ - protected $abstractFactories = []; - - /** - * Aliases - * - * @var array - */ - protected $aliases = [ - 'Zend\EventManager\EventManagerInterface' => 'EventManager', - 'Zend\ServiceManager\ServiceLocatorInterface' => 'ServiceManager', - 'Zend\ServiceManager\ServiceManager' => 'ServiceManager', + protected $config = [ + 'abstract_factories' => [], + 'aliases' => [ + 'Zend\EventManager\EventManagerInterface' => 'EventManager', + 'Zend\ServiceManager\ServiceManager' => 'ServiceManager', + ], + 'delegators' => [], + 'factories' => [ + 'EventManager' => EventManagerFactory::class, + 'ModuleManager' => ModuleManagerFactory::class, + 'ServiceListener' => ServiceListenerFactory::class, + ], + 'lazy_services' => [], + 'initializers' => [], + 'invokables' => [ + 'SharedEventManager' => 'Zend\EventManager\SharedEventManager', + ], + 'services' => [], + 'shared' => [ + 'EventManager' => false, + ], ]; - /** - * Shared services - * - * Services are shared by default; this is primarily to indicate services - * that should NOT be shared - * - * @var array - */ - protected $shared = [ - 'EventManager' => false, - ]; - - /** - * Delegators - * - * @var array - */ - protected $delegators = []; - - /** - * Initializers - * - * @var array - */ - protected $initializers = []; - /** * Constructor * @@ -93,8 +50,8 @@ class ServiceManagerConfig extends Config */ public function __construct(array $configuration = []) { - $this->initializers = [ - 'EventManagerAwareInitializer' => function ($instance, ServiceLocatorInterface $serviceLocator) { + $this->config['initializers'] = array_merge($this->config['initializers'], [ + 'EventManagerAwareInitializer' => function (ContainerInterface $container, $instance) { if (! $instance instanceof EventManagerAwareInterface) { return; } @@ -108,35 +65,11 @@ public function __construct(array $configuration = []) return; } - $instance->setEventManager($serviceLocator->get('EventManager')); - }, - 'ServiceManagerAwareInitializer' => function ($instance, ServiceLocatorInterface $serviceLocator) { - if ($serviceLocator instanceof ServiceManager && $instance instanceof ServiceManagerAwareInterface) { - $instance->setServiceManager($serviceLocator); - } - }, - 'ServiceLocatorAwareInitializer' => function ($instance, ServiceLocatorInterface $serviceLocator) { - if ($instance instanceof ServiceLocatorAwareInterface) { - $instance->setServiceLocator($serviceLocator); - } + $instance->setEventManager($container->get('EventManager')); }, - ]; + ]); - $this->factories['ServiceManager'] = function (ServiceLocatorInterface $serviceLocator) { - return $serviceLocator; - }; - parent::__construct(ArrayUtils::merge( - [ - 'invokables' => $this->invokables, - 'factories' => $this->factories, - 'abstract_factories' => $this->abstractFactories, - 'aliases' => $this->aliases, - 'shared' => $this->shared, - 'delegators' => $this->delegators, - 'initializers' => $this->initializers, - ], - $configuration - )); + parent::__construct($configuration); } } diff --git a/src/Service/TranslatorPluginManagerFactory.php b/src/Service/TranslatorPluginManagerFactory.php index 2dee23cb1..5a88a25b4 100644 --- a/src/Service/TranslatorPluginManagerFactory.php +++ b/src/Service/TranslatorPluginManagerFactory.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Service; +use Zend\I18n\Translator\LoaderPluginManager as TranslatorLoaderPluginManager; + class TranslatorPluginManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\I18n\Translator\LoaderPluginManager'; + const PLUGIN_MANAGER_CLASS = TranslatorLoaderPluginManager::class; } diff --git a/src/Service/TranslatorServiceFactory.php b/src/Service/TranslatorServiceFactory.php index b48981eb9..f2b444c22 100644 --- a/src/Service/TranslatorServiceFactory.php +++ b/src/Service/TranslatorServiceFactory.php @@ -9,12 +9,12 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Traversable; use Zend\I18n\Translator\Translator; use Zend\Mvc\I18n\DummyTranslator; use Zend\Mvc\I18n\Translator as MvcTranslator; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\FactoryInterface; /** * Overrides the translator factory from the i18n component in order to @@ -23,20 +23,22 @@ class TranslatorServiceFactory implements FactoryInterface { /** - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return MvcTranslator */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { // Assume that if a user has registered a service for the // TranslatorInterface, it must be valid - if ($serviceLocator->has('Zend\I18n\Translator\TranslatorInterface')) { - return new MvcTranslator($serviceLocator->get('Zend\I18n\Translator\TranslatorInterface')); + if ($container->has('Zend\I18n\Translator\TranslatorInterface')) { + return new MvcTranslator($container->get('Zend\I18n\Translator\TranslatorInterface')); } // Load a translator from configuration, if possible - if ($serviceLocator->has('Config')) { - $config = $serviceLocator->get('Config'); + if ($container->has('config')) { + $config = $container->get('config'); // 'translator' => false if (array_key_exists('translator', $config) && $config['translator'] === false) { @@ -49,8 +51,8 @@ public function createService(ServiceLocatorInterface $serviceLocator) || $config['translator'] instanceof Traversable) ) { $i18nTranslator = Translator::factory($config['translator']); - $i18nTranslator->setPluginManager($serviceLocator->get('TranslatorPluginManager')); - $serviceLocator->setService('Zend\I18n\Translator\TranslatorInterface', $i18nTranslator); + $i18nTranslator->setPluginManager($container->get('TranslatorPluginManager')); + // $container->setService('Zend\I18n\Translator\TranslatorInterface', $i18nTranslator); return new MvcTranslator($i18nTranslator); } } diff --git a/src/Service/ValidatorManagerFactory.php b/src/Service/ValidatorManagerFactory.php index a270f8fc3..24691e487 100644 --- a/src/Service/ValidatorManagerFactory.php +++ b/src/Service/ValidatorManagerFactory.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Service; +use Zend\Validator\ValidatorPluginManager; + class ValidatorManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\Validator\ValidatorPluginManager'; + const PLUGIN_MANAGER_CLASS = ValidatorPluginManager::class; } diff --git a/src/Service/ViewFactory.php b/src/Service/ViewFactory.php new file mode 100644 index 000000000..dd9ce58e6 --- /dev/null +++ b/src/Service/ViewFactory.php @@ -0,0 +1,35 @@ +get('EventManager'); + + $view->setEventManager($events); + $container->get(PhpRendererStrategy::class)->attach($events); + + return $view; + } +} diff --git a/src/Service/ViewFeedStrategyFactory.php b/src/Service/ViewFeedStrategyFactory.php index 2e7c8d20b..b5fc41885 100644 --- a/src/Service/ViewFeedStrategyFactory.php +++ b/src/Service/ViewFeedStrategyFactory.php @@ -9,8 +9,8 @@ namespace Zend\Mvc\Service; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; use Zend\View\Strategy\FeedStrategy; class ViewFeedStrategyFactory implements FactoryInterface @@ -23,13 +23,13 @@ class ViewFeedStrategyFactory implements FactoryInterface * * It then attaches the strategy to the View service, at a priority of 100. * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return FeedStrategy */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $feedRenderer = $serviceLocator->get('ViewFeedRenderer'); - $feedStrategy = new FeedStrategy($feedRenderer); - return $feedStrategy; + return new FeedStrategy($container->get('ViewFeedRenderer')); } } diff --git a/src/Service/ViewHelperManagerFactory.php b/src/Service/ViewHelperManagerFactory.php index 6f9d3fe0f..3e974eeda 100644 --- a/src/Service/ViewHelperManagerFactory.php +++ b/src/Service/ViewHelperManagerFactory.php @@ -9,63 +9,92 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\Console\Console; -use Zend\Mvc\Exception; use Zend\Mvc\Router\RouteMatch; -use Zend\ServiceManager\ConfigInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Exception\ServiceNotCreatedException; +use Zend\Stdlib\ArrayUtils; use Zend\View\Helper as ViewHelper; -use Zend\View\Helper\HelperInterface as ViewHelperInterface; +use Zend\View\HelperPluginManager; class ViewHelperManagerFactory extends AbstractPluginManagerFactory { - const PLUGIN_MANAGER_CLASS = 'Zend\View\HelperPluginManager'; + const PLUGIN_MANAGER_CLASS = HelperPluginManager::class; /** * An array of helper configuration classes to ensure are on the helper_map stack. * + * These are *not* imported; that way they can be optional dependencies. + * + * @todo Re-enable these once their components have been updated to zend-servicemanager v3 * @var array */ protected $defaultHelperMapClasses = [ + /* 'Zend\Form\View\HelperConfig', 'Zend\I18n\View\HelperConfig', - 'Zend\Navigation\View\HelperConfig' + 'Zend\Navigation\View\HelperConfig', + */ ]; /** * Create and return the view helper manager * - * @param ServiceLocatorInterface $serviceLocator - * @return ViewHelperInterface - * @throws Exception\RuntimeException + * @param ContainerInterface $container + * @return HelperPluginManager + * @throws ServiceNotCreatedException */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { - $plugins = parent::createService($serviceLocator); + $options = $options ?: []; foreach ($this->defaultHelperMapClasses as $configClass) { - if (is_string($configClass) && class_exists($configClass)) { - $config = new $configClass; - - if (!$config instanceof ConfigInterface) { - throw new Exception\RuntimeException(sprintf( - 'Invalid service manager configuration class provided; received "%s", expected class implementing %s', - $configClass, - 'Zend\ServiceManager\ConfigInterface' - )); - } - - $config->configureServiceManager($plugins); + if (! is_string($configClass) || ! class_exists($configClass)) { + continue; + } + + $config = new $configClass(); + + if (! $config instanceof ConfigInterface) { + throw new ServiceNotCreatedException(sprintf( + 'Invalid service manager configuration class provided; received "%s", expected class implementing %s', + $configClass, + ConfigInterface::class + )); } + + $options = ArrayUtils::merge($options, $config->toArray()); } - // Configure URL view helper with router - $plugins->setFactory('url', function () use ($serviceLocator) { + $config = $container->has('config') ? $container->get('config') : []; + + $options['factories'] = isset($options['factories']) ? $options['factories'] : []; + + // Configure URL view helper factory + $options['factories'][ViewHelper\Url::class] = $this->createUrlHelperFactory(); + + // Configure basepath view helper factory + $options['factories'][ViewHelper\BasePath::class] = $this->createBasePathHelperFactory($config); + + // Configure doctype view helper factory + $options['factories'][ViewHelper\Doctype::class] = $this->createDoctypeHelperFactory(); + + return parent::__invoke($container, $requestedName, $options); + } + + /** + * Create a factory for the "url" view helper + * + * @return callable + */ + private function createUrlHelperFactory() + { + return function ($container, $name, array $options = null) { $helper = new ViewHelper\Url; $router = Console::isConsole() ? 'HttpRouter' : 'Router'; - $helper->setRouter($serviceLocator->get($router)); + $helper->setRouter($container->get($router)); - $match = $serviceLocator->get('application') + $match = $container->get('application') ->getMvcEvent() ->getRouteMatch() ; @@ -75,52 +104,62 @@ public function createService(ServiceLocatorInterface $serviceLocator) } return $helper; - }); + }; + } - $plugins->setFactory('basepath', function () use ($serviceLocator) { - $config = $serviceLocator->has('Config') ? $serviceLocator->get('Config') : []; - $basePathHelper = new ViewHelper\BasePath; + /** + * Create a factory for the "basepath" view helper + * + * @param array $config + * @return callable + */ + private function createBasePathHelperFactory($config) + { + return function ($container, $name, array $options = null) { + $config = $container->has('config') ? $container->get('config') : []; + $helper = new ViewHelper\BasePath; if (Console::isConsole() - && isset($config['view_manager']) && isset($config['view_manager']['base_path_console']) ) { - $basePathHelper->setBasePath($config['view_manager']['base_path_console']); - - return $basePathHelper; + $helper->setBasePath($config['view_manager']['base_path_console']); + return $helper; } if (isset($config['view_manager']) && isset($config['view_manager']['base_path'])) { - $basePathHelper->setBasePath($config['view_manager']['base_path']); - - return $basePathHelper; + $helper->setBasePath($config['view_manager']['base_path']); + return $helper; } - $request = $serviceLocator->get('Request'); - + $request = $container->get('Request'); if (is_callable([$request, 'getBasePath'])) { - $basePathHelper->setBasePath($request->getBasePath()); + $helper->setBasePath($request->getBasePath()); } - return $basePathHelper; - }); + return $helper; + }; + } - /** - * Configure doctype view helper with doctype from configuration, if available. - * - * Other view helpers depend on this to decide which spec to generate their tags - * based on. This is why it must be set early instead of later in the layout phtml. - */ - $plugins->setFactory('doctype', function () use ($serviceLocator) { - $config = $serviceLocator->has('Config') ? $serviceLocator->get('Config') : []; + /** + * Configure doctype view helper with doctype from configuration, if available. + * + * Other view helpers depend on this to decide which spec to generate their tags + * based on. + * + * This is why it must be set early instead of later in the layout phtml. + * + * @return callable + */ + private function createDoctypeHelperFactory() + { + return function ($container, $name, array $options = null) { + $config = $container->has('config') ? $container->get('config') : []; $config = isset($config['view_manager']) ? $config['view_manager'] : []; - $doctypeHelper = new ViewHelper\Doctype; + $helper = new ViewHelper\Doctype; if (isset($config['doctype']) && $config['doctype']) { - $doctypeHelper->setDoctype($config['doctype']); + $helper->setDoctype($config['doctype']); } - return $doctypeHelper; - }); - - return $plugins; + return $helper; + }; } } diff --git a/src/Service/ViewJsonStrategyFactory.php b/src/Service/ViewJsonStrategyFactory.php index f0935de5b..92337b299 100644 --- a/src/Service/ViewJsonStrategyFactory.php +++ b/src/Service/ViewJsonStrategyFactory.php @@ -9,8 +9,8 @@ namespace Zend\Mvc\Service; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; use Zend\View\Strategy\JsonStrategy; class ViewJsonStrategyFactory implements FactoryInterface @@ -23,12 +23,14 @@ class ViewJsonStrategyFactory implements FactoryInterface * * It then attaches the strategy to the View service, at a priority of 100. * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return JsonStrategy */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $jsonRenderer = $serviceLocator->get('ViewJsonRenderer'); + $jsonRenderer = $container->get('ViewJsonRenderer'); $jsonStrategy = new JsonStrategy($jsonRenderer); return $jsonStrategy; } diff --git a/src/Service/ViewManagerFactory.php b/src/Service/ViewManagerFactory.php index 548e530f5..a0a4c7c98 100644 --- a/src/Service/ViewManagerFactory.php +++ b/src/Service/ViewManagerFactory.php @@ -9,26 +9,28 @@ namespace Zend\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\Console\Console; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; use Zend\Mvc\View\Console\ViewManager as ConsoleViewManager; use Zend\Mvc\View\Http\ViewManager as HttpViewManager; +use Zend\ServiceManager\Factory\FactoryInterface; class ViewManagerFactory implements FactoryInterface { /** * Create and return a view manager based on detected environment * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return ConsoleViewManager|HttpViewManager */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { if (Console::isConsole()) { - return $serviceLocator->get('ConsoleViewManager'); + return $container->get('ConsoleViewManager'); } - return $serviceLocator->get('HttpViewManager'); + return $container->get('HttpViewManager'); } } diff --git a/src/Service/ViewPhpRendererFactory.php b/src/Service/ViewPhpRendererFactory.php new file mode 100644 index 000000000..770704d2c --- /dev/null +++ b/src/Service/ViewPhpRendererFactory.php @@ -0,0 +1,32 @@ +setHelperPluginManager($container->get('ViewHelperManager')); + $renderer->setResolver($container->get('ViewResolver')); + + return $renderer; + } +} diff --git a/src/Service/ViewPhpRendererStrategyFactory.php b/src/Service/ViewPhpRendererStrategyFactory.php new file mode 100644 index 000000000..2d70aaf1d --- /dev/null +++ b/src/Service/ViewPhpRendererStrategyFactory.php @@ -0,0 +1,29 @@ +get(PhpRenderer::class)); + } +} diff --git a/src/Service/ViewPrefixPathStackResolverFactory.php b/src/Service/ViewPrefixPathStackResolverFactory.php index 2c9766a85..8eb85a6a2 100644 --- a/src/Service/ViewPrefixPathStackResolverFactory.php +++ b/src/Service/ViewPrefixPathStackResolverFactory.php @@ -9,8 +9,8 @@ namespace Zend\Mvc\Service; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; use Zend\View\Resolver\PrefixPathStackResolver; class ViewPrefixPathStackResolverFactory implements FactoryInterface @@ -21,12 +21,14 @@ class ViewPrefixPathStackResolverFactory implements FactoryInterface * Creates a Zend\View\Resolver\PrefixPathStackResolver and populates it with the * ['view_manager']['prefix_template_path_stack'] * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return PrefixPathStackResolver */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $config = $serviceLocator->get('Config'); + $config = $container->get('config'); $prefixes = []; if (isset($config['view_manager']['prefix_template_path_stack'])) { diff --git a/src/Service/ViewResolverFactory.php b/src/Service/ViewResolverFactory.php index e57e6c392..1b242e0f1 100644 --- a/src/Service/ViewResolverFactory.php +++ b/src/Service/ViewResolverFactory.php @@ -9,8 +9,8 @@ namespace Zend\Mvc\Service; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; use Zend\View\Resolver as ViewResolver; class ViewResolverFactory implements FactoryInterface @@ -21,19 +21,21 @@ class ViewResolverFactory implements FactoryInterface * Creates a Zend\View\Resolver\AggregateResolver and attaches the template * map resolver and path stack resolver * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return ViewResolver\AggregateResolver */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { $resolver = new ViewResolver\AggregateResolver(); /* @var $mapResolver \Zend\View\Resolver\ResolverInterface */ - $mapResolver = $serviceLocator->get('ViewTemplateMapResolver'); + $mapResolver = $container->get('ViewTemplateMapResolver'); /* @var $pathResolver \Zend\View\Resolver\ResolverInterface */ - $pathResolver = $serviceLocator->get('ViewTemplatePathStack'); + $pathResolver = $container->get('ViewTemplatePathStack'); /* @var $prefixPathStackResolver \Zend\View\Resolver\ResolverInterface */ - $prefixPathStackResolver = $serviceLocator->get('ViewPrefixPathStackResolver'); + $prefixPathStackResolver = $container->get('ViewPrefixPathStackResolver'); $resolver ->attach($mapResolver) diff --git a/src/Service/ViewTemplateMapResolverFactory.php b/src/Service/ViewTemplateMapResolverFactory.php index 87383740b..64a911daf 100644 --- a/src/Service/ViewTemplateMapResolverFactory.php +++ b/src/Service/ViewTemplateMapResolverFactory.php @@ -9,8 +9,8 @@ namespace Zend\Mvc\Service; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; use Zend\View\Resolver as ViewResolver; class ViewTemplateMapResolverFactory implements FactoryInterface @@ -21,12 +21,14 @@ class ViewTemplateMapResolverFactory implements FactoryInterface * Creates a Zend\View\Resolver\AggregateResolver and populates it with the * ['view_manager']['template_map'] * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return ViewResolver\TemplateMapResolver */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $config = $serviceLocator->get('Config'); + $config = $container->get('config'); $map = []; if (is_array($config) && isset($config['view_manager'])) { $config = $config['view_manager']; diff --git a/src/Service/ViewTemplatePathStackFactory.php b/src/Service/ViewTemplatePathStackFactory.php index dcf6ddd4b..c4267d7e9 100644 --- a/src/Service/ViewTemplatePathStackFactory.php +++ b/src/Service/ViewTemplatePathStackFactory.php @@ -9,8 +9,8 @@ namespace Zend\Mvc\Service; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; use Zend\View\Resolver as ViewResolver; class ViewTemplatePathStackFactory implements FactoryInterface @@ -22,12 +22,14 @@ class ViewTemplatePathStackFactory implements FactoryInterface * ['view_manager']['template_path_stack'] and sets the default suffix with the * ['view_manager']['default_template_suffix'] * - * @param ServiceLocatorInterface $serviceLocator + * @param ContainerInterface $container + * @param string $name + * @param null|array $options * @return ViewResolver\TemplatePathStack */ - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $config = $serviceLocator->get('Config'); + $config = $container->get('config'); $templatePathStack = new ViewResolver\TemplatePathStack(); diff --git a/src/View/Console/ViewManager.php b/src/View/Console/ViewManager.php index 97835ff71..bf409ec0c 100644 --- a/src/View/Console/ViewManager.php +++ b/src/View/Console/ViewManager.php @@ -34,13 +34,13 @@ public function onBootstrap($event) $services = $application->getServiceManager(); $events = $application->getEventManager(); $sharedEvents = $events->getSharedManager(); - $this->config = $this->loadConfig($services->get('Config')); + $this->config = $this->loadConfig($services->get('config')); $this->services = $services; $this->event = $event; - $routeNotFoundStrategy = $this->getRouteNotFoundStrategy(); - $exceptionStrategy = $this->getExceptionStrategy(); - $mvcRenderingStrategy = $this->getMvcRenderingStrategy(); + $routeNotFoundStrategy = $services->get('ConsoleRouteNotFoundStrategy'); + $exceptionStrategy = $services->get('ConsoleExceptionStrategy'); + $mvcRenderingStrategy = $services->get('ConsoleDefaultRenderingStrategy'); $createViewModelListener = new CreateViewModelListener(); $injectViewModelListener = new InjectViewModelListener(); $injectParamsListener = new InjectNamedConsoleParamsListener(); @@ -61,90 +61,6 @@ public function onBootstrap($event) $sharedEvents->attach('Zend\Stdlib\DispatchableInterface', MvcEvent::EVENT_DISPATCH, [$injectViewModelListener, 'injectViewModel'], -100); } - /** - * Instantiates and configures the default MVC rendering strategy - * - * Overriding to ensure we pick up the MVC rendering strategy for console, - * as well as to ensure that the appropriate aliases are set. - * - * @return DefaultRenderingStrategy - */ - public function getMvcRenderingStrategy() - { - if ($this->mvcRenderingStrategy) { - return $this->mvcRenderingStrategy; - } - - $this->mvcRenderingStrategy = new DefaultRenderingStrategy(); - - $this->services->setService('DefaultRenderingStrategy', $this->mvcRenderingStrategy); - $this->services->setAlias('Zend\Mvc\View\DefaultRenderingStrategy', 'DefaultRenderingStrategy'); - $this->services->setAlias('Zend\Mvc\View\Console\DefaultRenderingStrategy', 'DefaultRenderingStrategy'); - - return $this->mvcRenderingStrategy; - } - - /** - * Instantiates and configures the exception strategy - * - * Overriding to ensure we pick up the exception strategy for console, as - * well as to ensure that the appropriate aliases are set. - * - * @return ExceptionStrategy - */ - public function getExceptionStrategy() - { - if ($this->exceptionStrategy) { - return $this->exceptionStrategy; - } - - $this->exceptionStrategy = new ExceptionStrategy(); - - if (isset($this->config['display_exceptions'])) { - $this->exceptionStrategy->setDisplayExceptions($this->config['display_exceptions']); - } - if (isset($this->config['exception_message'])) { - $this->exceptionStrategy->setMessage($this->config['exception_message']); - } - - $this->services->setService('ExceptionStrategy', $this->exceptionStrategy); - $this->services->setAlias('Zend\Mvc\View\ExceptionStrategy', 'ExceptionStrategy'); - $this->services->setAlias('Zend\Mvc\View\Console\ExceptionStrategy', 'ExceptionStrategy'); - - return $this->exceptionStrategy; - } - - /** - * Instantiates and configures the "route not found", or 404, strategy - * - * Overriding to ensure we pick up the route not found strategy for console, - * as well as to ensure that the appropriate aliases are set. - * - * @return RouteNotFoundStrategy - */ - public function getRouteNotFoundStrategy() - { - if ($this->routeNotFoundStrategy) { - return $this->routeNotFoundStrategy; - } - - $this->routeNotFoundStrategy = new RouteNotFoundStrategy(); - - $displayNotFoundReason = true; - - if (array_key_exists('display_not_found_reason', $this->config)) { - $displayNotFoundReason = $this->config['display_not_found_reason']; - } - $this->routeNotFoundStrategy->setDisplayNotFoundReason($displayNotFoundReason); - - $this->services->setService('RouteNotFoundStrategy', $this->routeNotFoundStrategy); - $this->services->setAlias('Zend\Mvc\View\RouteNotFoundStrategy', 'RouteNotFoundStrategy'); - $this->services->setAlias('Zend\Mvc\View\Console\RouteNotFoundStrategy', 'RouteNotFoundStrategy'); - $this->services->setAlias('404Strategy', 'RouteNotFoundStrategy'); - - return $this->routeNotFoundStrategy; - } - /** * Extract view manager configuration from the application's configuration * diff --git a/src/View/Http/ViewManager.php b/src/View/Http/ViewManager.php index 162cfa3c0..436ba393c 100644 --- a/src/View/Http/ViewManager.php +++ b/src/View/Http/ViewManager.php @@ -17,9 +17,7 @@ use Zend\Mvc\MvcEvent; use Zend\ServiceManager\ServiceManager; use Zend\View\HelperPluginManager as ViewHelperManager; -use Zend\View\Renderer\PhpRenderer as ViewPhpRenderer; use Zend\View\Resolver as ViewResolver; -use Zend\View\Strategy\PhpRendererStrategy; use Zend\View\View; /** @@ -65,13 +63,11 @@ class ViewManager extends AbstractListenerAggregate * Various properties representing strategies and objects instantiated and * configured by the view manager */ - protected $exceptionStrategy; protected $helperManager; protected $mvcRenderingStrategy; protected $renderer; protected $rendererStrategy; protected $resolver; - protected $routeNotFoundStrategy; protected $view; protected $viewModel; /**@-*/ @@ -94,7 +90,7 @@ public function onBootstrap($event) { $application = $event->getApplication(); $services = $application->getServiceManager(); - $config = $services->get('Config'); + $config = $services->get('config'); $events = $application->getEventManager(); $sharedEvents = $events->getSharedManager(); @@ -104,10 +100,13 @@ public function onBootstrap($event) $this->services = $services; $this->event = $event; - $routeNotFoundStrategy = $this->getRouteNotFoundStrategy(); - $exceptionStrategy = $this->getExceptionStrategy(); - $mvcRenderingStrategy = $this->getMvcRenderingStrategy(); - $injectTemplateListener = $this->getInjectTemplateListener(); + $routeNotFoundStrategy = $services->get('HttpRouteNotFoundStrategy'); + $exceptionStrategy = $services->get('HttpExceptionStrategy'); + $mvcRenderingStrategy = $services->get('HttpDefaultRenderingStrategy'); + + $this->injectViewModelIntoPlugin(); + + $injectTemplateListener = $services->get('Zend\Mvc\View\Http\InjectTemplateListener'); $createViewModelListener = new CreateViewModelListener(); $injectViewModelListener = new InjectViewModelListener(); @@ -128,82 +127,7 @@ public function onBootstrap($event) } /** - * Instantiates and configures the renderer's helper manager - * - * @return ViewHelperManager - */ - public function getHelperManager() - { - if ($this->helperManager) { - return $this->helperManager; - } - - return $this->helperManager = $this->services->get('ViewHelperManager'); - } - - /** - * Instantiates and configures the renderer's resolver - * - * @return ViewResolver\ResolverInterface - */ - public function getResolver() - { - if (null === $this->resolver) { - $this->resolver = $this->services->get('ViewResolver'); - } - - return $this->resolver; - } - - /** - * Instantiates and configures the renderer - * - * @return ViewPhpRenderer - */ - public function getRenderer() - { - if ($this->renderer) { - return $this->renderer; - } - - $this->renderer = new ViewPhpRenderer; - $this->renderer->setHelperPluginManager($this->getHelperManager()); - $this->renderer->setResolver($this->getResolver()); - - $model = $this->getViewModel(); - $modelHelper = $this->renderer->plugin('view_model'); - $modelHelper->setRoot($model); - - $this->services->setService('ViewRenderer', $this->renderer); - $this->services->setAlias('Zend\View\Renderer\PhpRenderer', 'ViewRenderer'); - $this->services->setAlias('Zend\View\Renderer\RendererInterface', 'ViewRenderer'); - - return $this->renderer; - } - - /** - * Instantiates and configures the renderer strategy for the view - * - * @return PhpRendererStrategy - */ - public function getRendererStrategy() - { - if ($this->rendererStrategy) { - return $this->rendererStrategy; - } - - $this->rendererStrategy = new PhpRendererStrategy( - $this->getRenderer() - ); - - $this->services->setService('ViewPhpRendererStrategy', $this->rendererStrategy); - $this->services->setAlias('Zend\View\Strategy\PhpRendererStrategy', 'ViewPhpRendererStrategy'); - - return $this->rendererStrategy; - } - - /** - * Instantiates and configures the view + * Retrieves the View instance * * @return View */ @@ -213,128 +137,10 @@ public function getView() return $this->view; } - $this->view = new View(); - $this->view->setEventManager($this->services->get('EventManager')); - $this->getRendererStrategy()->attach($this->view->getEventManager()); - - $this->services->setService('View', $this->view); - $this->services->setAlias('Zend\View\View', 'View'); - + $this->view = $this->services->get(View::class); return $this->view; } - /** - * Retrieves the layout template name from the configuration - * - * @return string - */ - public function getLayoutTemplate() - { - if (isset($this->config['layout'])) { - return $this->config['layout']; - } - - return 'layout/layout'; - } - - /** - * Instantiates and configures the default MVC rendering strategy - * - * @return DefaultRenderingStrategy - */ - public function getMvcRenderingStrategy() - { - if ($this->mvcRenderingStrategy) { - return $this->mvcRenderingStrategy; - } - - $this->mvcRenderingStrategy = new DefaultRenderingStrategy($this->getView()); - $this->mvcRenderingStrategy->setLayoutTemplate($this->getLayoutTemplate()); - - $this->services->setService('DefaultRenderingStrategy', $this->mvcRenderingStrategy); - $this->services->setAlias('Zend\Mvc\View\DefaultRenderingStrategy', 'DefaultRenderingStrategy'); - $this->services->setAlias('Zend\Mvc\View\Http\DefaultRenderingStrategy', 'DefaultRenderingStrategy'); - - return $this->mvcRenderingStrategy; - } - - /** - * Instantiates and configures the exception strategy - * - * @return ExceptionStrategy - */ - public function getExceptionStrategy() - { - if ($this->exceptionStrategy) { - return $this->exceptionStrategy; - } - - $this->exceptionStrategy = new ExceptionStrategy(); - - $displayExceptions = false; - $exceptionTemplate = 'error'; - - if (isset($this->config['display_exceptions'])) { - $displayExceptions = $this->config['display_exceptions']; - } - if (isset($this->config['exception_template'])) { - $exceptionTemplate = $this->config['exception_template']; - } - - $this->exceptionStrategy->setDisplayExceptions($displayExceptions); - $this->exceptionStrategy->setExceptionTemplate($exceptionTemplate); - - $this->services->setService('ExceptionStrategy', $this->exceptionStrategy); - $this->services->setAlias('Zend\Mvc\View\ExceptionStrategy', 'ExceptionStrategy'); - $this->services->setAlias('Zend\Mvc\View\Http\ExceptionStrategy', 'ExceptionStrategy'); - - return $this->exceptionStrategy; - } - - /** - * Instantiates and configures the "route not found", or 404, strategy - * - * @return RouteNotFoundStrategy - */ - public function getRouteNotFoundStrategy() - { - if ($this->routeNotFoundStrategy) { - return $this->routeNotFoundStrategy; - } - - $this->routeNotFoundStrategy = new RouteNotFoundStrategy(); - - $displayExceptions = false; - $displayNotFoundReason = false; - $notFoundTemplate = '404'; - - if (isset($this->config['display_exceptions'])) { - $displayExceptions = $this->config['display_exceptions']; - } - if (isset($this->config['display_not_found_reason'])) { - $displayNotFoundReason = $this->config['display_not_found_reason']; - } - if (isset($this->config['not_found_template'])) { - $notFoundTemplate = $this->config['not_found_template']; - } - - $this->routeNotFoundStrategy->setDisplayExceptions($displayExceptions); - $this->routeNotFoundStrategy->setDisplayNotFoundReason($displayNotFoundReason); - $this->routeNotFoundStrategy->setNotFoundTemplate($notFoundTemplate); - - $this->services->setService('RouteNotFoundStrategy', $this->routeNotFoundStrategy); - $this->services->setAlias('Zend\Mvc\View\RouteNotFoundStrategy', 'RouteNotFoundStrategy'); - $this->services->setAlias('Zend\Mvc\View\Http\RouteNotFoundStrategy', 'RouteNotFoundStrategy'); - $this->services->setAlias('404Strategy', 'RouteNotFoundStrategy'); - - return $this->routeNotFoundStrategy; - } - - public function getInjectTemplateListener() - { - return $this->services->get('Zend\Mvc\View\Http\InjectTemplateListener'); - } - /** * Configures the MvcEvent view model to ensure it has the template injected * @@ -347,7 +153,8 @@ public function getViewModel() } $this->viewModel = $model = $this->event->getViewModel(); - $model->setTemplate($this->getLayoutTemplate()); + $layoutTemplate = $this->services->get('HttpDefaultRenderingStrategy')->getLayoutTemplate(); + $model->setTemplate($layoutTemplate); return $this->viewModel; } @@ -366,19 +173,19 @@ public function getViewModel() */ protected function registerMvcRenderingStrategies(EventManagerInterface $events) { - if (!isset($this->config['mvc_strategies'])) { + if (! isset($this->config['mvc_strategies'])) { return; } $mvcStrategies = $this->config['mvc_strategies']; if (is_string($mvcStrategies)) { $mvcStrategies = [$mvcStrategies]; } - if (!is_array($mvcStrategies) && !$mvcStrategies instanceof Traversable) { + if (! is_array($mvcStrategies) && ! $mvcStrategies instanceof Traversable) { return; } foreach ($mvcStrategies as $mvcStrategy) { - if (!is_string($mvcStrategy)) { + if (! is_string($mvcStrategy)) { continue; } @@ -402,14 +209,14 @@ protected function registerMvcRenderingStrategies(EventManagerInterface $events) */ protected function registerViewStrategies() { - if (!isset($this->config['strategies'])) { + if (! isset($this->config['strategies'])) { return; } $strategies = $this->config['strategies']; if (is_string($strategies)) { $strategies = [$strategies]; } - if (!is_array($strategies) && !$strategies instanceof Traversable) { + if (! is_array($strategies) && ! $strategies instanceof Traversable) { return; } @@ -417,7 +224,7 @@ protected function registerViewStrategies() $events = $view->getEventManager(); foreach ($strategies as $strategy) { - if (!is_string($strategy)) { + if (! is_string($strategy)) { continue; } @@ -427,4 +234,15 @@ protected function registerViewStrategies() } } } + + /** + * Injects the ViewModel view helper with the root view model. + */ + private function injectViewModelIntoPlugin() + { + $model = $this->getViewModel(); + $plugins = $this->services->get('ViewHelperManager'); + $plugin = $plugins->get('viewmodel'); + $plugin->setRoot($model); + } } diff --git a/test/Application/AllowsReturningEarlyFromRoutingTest.php b/test/Application/AllowsReturningEarlyFromRoutingTest.php new file mode 100644 index 000000000..47e731a7a --- /dev/null +++ b/test/Application/AllowsReturningEarlyFromRoutingTest.php @@ -0,0 +1,34 @@ +prepareApplication(); + + $response = new Response(); + + $application->getEventManager()->attach(MvcEvent::EVENT_ROUTE, function ($e) use ($response) { + return $response; + }); + + $result = $application->run(); + $this->assertSame($application, $result); + $this->assertSame($response, $result->getResponse()); + } +} diff --git a/test/Application/BadControllerTrait.php b/test/Application/BadControllerTrait.php new file mode 100644 index 000000000..f85660211 --- /dev/null +++ b/test/Application/BadControllerTrait.php @@ -0,0 +1,96 @@ + [ + 'routes' => [ + 'path' => [ + 'type' => Router\Http\Literal::class, + 'options' => [ + 'route' => '/bad', + 'defaults' => [ + 'controller' => 'bad', + 'action' => 'test', + ], + ], + ], + ], + ], + ]; + + $serviceListener = new ServiceListenerFactory(); + $r = new ReflectionProperty($serviceListener, 'defaultServiceConfig'); + $r->setAccessible(true); + $serviceConfig = $r->getValue($serviceListener); + + $serviceConfig = ArrayUtils::merge( + $serviceConfig, + [ + 'aliases' => [ + 'ControllerLoader' => ControllerManager::class, + 'ControllerManager' => ControllerManager::class, + 'Router' => 'HttpRouter', + ], + 'factories' => [ + ControllerManager::class => function ($services) { + return new ControllerManager($services, ['factories' => [ + 'bad' => function () { + return new BadController(); + }, + ]]); + }, + ], + 'invokables' => [ + 'Request' => 'Zend\Http\PhpEnvironment\Request', + 'Response' => Response::class, + 'ViewManager' => TestAsset\MockViewManager::class, + 'SendResponseListener' => TestAsset\MockSendResponseListener::class, + 'BootstrapListener' => TestAsset\StubBootstrapListener::class, + ], + 'services' => [ + 'config' => $config, + 'ApplicationConfig' => [ + 'modules' => [], + 'module_listener_options' => [ + 'config_cache_enabled' => false, + 'cache_dir' => 'data/cache', + 'module_paths' => [], + ], + ], + ], + ] + ); + $services = new ServiceManager((new ServiceManagerConfig($serviceConfig))->toArray()); + $application = $services->get('Application'); + + $request = $services->get('Request'); + $request->setUri('http://example.local/bad'); + + $application->bootstrap(); + return $application; + } +} diff --git a/test/Application/ControllerIsDispatchedTest.php b/test/Application/ControllerIsDispatchedTest.php new file mode 100644 index 000000000..d780a6fa8 --- /dev/null +++ b/test/Application/ControllerIsDispatchedTest.php @@ -0,0 +1,27 @@ +prepareApplication(); + + $response = $application->run()->getResponse(); + $this->assertContains('PathController', $response->getContent()); + $this->assertContains(MvcEvent::EVENT_DISPATCH, $response->toString()); + } +} diff --git a/test/Application/ExceptionsRaisedInDispatchableShouldRaiseDispatchErrorEventTest.php b/test/Application/ExceptionsRaisedInDispatchableShouldRaiseDispatchErrorEventTest.php new file mode 100644 index 000000000..7defd5347 --- /dev/null +++ b/test/Application/ExceptionsRaisedInDispatchableShouldRaiseDispatchErrorEventTest.php @@ -0,0 +1,38 @@ +prepareApplication(); + + $response = $application->getResponse(); + $events = $application->getEventManager(); + $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { + $exception = $e->getParam('exception'); + $this->assertInstanceOf('Exception', $exception); + $response->setContent($exception->getMessage()); + return $response; + }); + + $application->run(); + $this->assertContains('Raised an exception', $response->getContent()); + } +} diff --git a/test/Application/InabilityToRetrieveControllerShouldTriggerDispatchErrorTest.php b/test/Application/InabilityToRetrieveControllerShouldTriggerDispatchErrorTest.php new file mode 100644 index 000000000..5d1345b65 --- /dev/null +++ b/test/Application/InabilityToRetrieveControllerShouldTriggerDispatchErrorTest.php @@ -0,0 +1,40 @@ +prepareApplication(); + + $response = $application->getResponse(); + $events = $application->getEventManager(); + $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { + $error = $e->getError(); + $controller = $e->getController(); + $response->setContent("Code: " . $error . '; Controller: ' . $controller); + return $response; + }); + + $application->run(); + $this->assertContains(Application::ERROR_CONTROLLER_NOT_FOUND, $response->getContent()); + $this->assertContains('bad', $response->getContent()); + } +} diff --git a/test/Application/InabilityToRetrieveControllerShouldTriggerExceptionTest.php b/test/Application/InabilityToRetrieveControllerShouldTriggerExceptionTest.php new file mode 100644 index 000000000..ed1c07e97 --- /dev/null +++ b/test/Application/InabilityToRetrieveControllerShouldTriggerExceptionTest.php @@ -0,0 +1,40 @@ +prepareApplication(); + + $response = $application->getResponse(); + $events = $application->getEventManager(); + $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { + $error = $e->getError(); + $controller = $e->getController(); + $response->setContent("Code: " . $error . '; Controller: ' . $controller); + return $response; + }); + + $application->run(); + $this->assertContains(Application::ERROR_CONTROLLER_NOT_FOUND, $response->getContent()); + $this->assertContains('bad', $response->getContent()); + } +} diff --git a/test/Application/InitializationIntegrationTest.php b/test/Application/InitializationIntegrationTest.php new file mode 100644 index 000000000..96d75dd76 --- /dev/null +++ b/test/Application/InitializationIntegrationTest.php @@ -0,0 +1,43 @@ + [ + 'Application', + ], + 'module_listener_options' => [ + 'module_paths' => [ + __DIR__ . '/TestAsset/modules', + ], + ], + ]; + + $application = Application::init($appConfig); + + $request = $application->getRequest(); + $request->setUri('http://example.local/path'); + $request->setRequestUri('/path'); + + $application->run(); + $response = $application->getResponse(); + $this->assertContains('Application\\Controller\\PathController', $response->getContent()); + $this->assertContains(MvcEvent::EVENT_DISPATCH, $response->toString()); + } +} diff --git a/test/Application/InvalidControllerTypeShouldTriggerDispatchErrorTest.php b/test/Application/InvalidControllerTypeShouldTriggerDispatchErrorTest.php new file mode 100644 index 000000000..c0d2d5104 --- /dev/null +++ b/test/Application/InvalidControllerTypeShouldTriggerDispatchErrorTest.php @@ -0,0 +1,41 @@ +prepareApplication(); + + $response = $application->getResponse(); + $events = $application->getEventManager(); + $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { + $error = $e->getError(); + $controller = $e->getController(); + $class = $e->getControllerClass(); + $response->setContent("Code: " . $error . '; Controller: ' . $controller . '; Class: ' . $class); + return $response; + }); + + $application->run(); + $this->assertContains(Application::ERROR_CONTROLLER_INVALID, $response->getContent()); + $this->assertContains('bad', $response->getContent()); + } +} diff --git a/test/Application/InvalidControllerTypeTrait.php b/test/Application/InvalidControllerTypeTrait.php new file mode 100644 index 000000000..e45ed2626 --- /dev/null +++ b/test/Application/InvalidControllerTypeTrait.php @@ -0,0 +1,96 @@ + [ + 'routes' => [ + 'path' => [ + 'type' => Router\Http\Literal::class, + 'options' => [ + 'route' => '/bad', + 'defaults' => [ + 'controller' => 'bad', + 'action' => 'test', + ], + ], + ], + ], + ], + ]; + + $serviceListener = new ServiceListenerFactory(); + $r = new ReflectionProperty($serviceListener, 'defaultServiceConfig'); + $r->setAccessible(true); + $serviceConfig = $r->getValue($serviceListener); + + $serviceConfig = ArrayUtils::merge( + $serviceConfig, + [ + 'aliases' => [ + 'ControllerLoader' => ControllerManager::class, + 'ControllerManager' => ControllerManager::class, + 'Router' => 'HttpRouter', + ], + 'factories' => [ + ControllerManager::class => function ($services) { + return new ControllerManager($services, ['factories' => [ + 'bad' => function () { + return new stdClass(); + }, + ]]); + }, + ], + 'invokables' => [ + 'Request' => 'Zend\Http\PhpEnvironment\Request', + 'Response' => Response::class, + 'ViewManager' => TestAsset\MockViewManager::class, + 'SendResponseListener' => TestAsset\MockSendResponseListener::class, + 'BootstrapListener' => TestAsset\StubBootstrapListener::class, + ], + 'services' => [ + 'config' => $config, + 'ApplicationConfig' => [ + 'modules' => [], + 'module_listener_options' => [ + 'config_cache_enabled' => false, + 'cache_dir' => 'data/cache', + 'module_paths' => [], + ], + ], + ], + ] + ); + $services = new ServiceManager((new ServiceManagerConfig($serviceConfig))->toArray()); + $application = $services->get('Application'); + + $request = $services->get('Request'); + $request->setUri('http://example.local/bad'); + + $application->bootstrap(); + return $application; + } +} diff --git a/test/Application/MissingControllerTrait.php b/test/Application/MissingControllerTrait.php new file mode 100644 index 000000000..16ee04c86 --- /dev/null +++ b/test/Application/MissingControllerTrait.php @@ -0,0 +1,83 @@ + [ + 'routes' => [ + 'path' => [ + 'type' => Router\Http\Literal::class, + 'options' => [ + 'route' => '/bad', + 'defaults' => [ + 'controller' => 'bad', + 'action' => 'test', + ], + ], + ], + ], + ], + ]; + + $serviceListener = new ServiceListenerFactory(); + $r = new ReflectionProperty($serviceListener, 'defaultServiceConfig'); + $r->setAccessible(true); + $serviceConfig = $r->getValue($serviceListener); + + $serviceConfig = ArrayUtils::merge( + $serviceConfig, + [ + 'aliases' => [ + 'Router' => 'HttpRouter', + ], + 'invokables' => [ + 'Request' => 'Zend\Http\PhpEnvironment\Request', + 'Response' => Response::class, + 'ViewManager' => TestAsset\MockViewManager::class, + 'SendResponseListener' => TestAsset\MockSendResponseListener::class, + 'BootstrapListener' => TestAsset\StubBootstrapListener::class, + ], + 'services' => [ + 'config' => $config, + 'ApplicationConfig' => [ + 'modules' => [], + 'module_listener_options' => [ + 'config_cache_enabled' => false, + 'cache_dir' => 'data/cache', + 'module_paths' => [], + ], + ], + ], + ] + ); + $services = new ServiceManager((new ServiceManagerConfig($serviceConfig))->toArray()); + $application = $services->get('Application'); + + $request = $services->get('Request'); + $request->setUri('http://example.local/bad'); + + $application->bootstrap(); + return $application; + } +} diff --git a/test/Application/PathControllerTrait.php b/test/Application/PathControllerTrait.php new file mode 100644 index 000000000..18376007d --- /dev/null +++ b/test/Application/PathControllerTrait.php @@ -0,0 +1,94 @@ + [ + 'routes' => [ + 'path' => [ + 'type' => Router\Http\Literal::class, + 'options' => [ + 'route' => '/path', + 'defaults' => [ + 'controller' => 'path', + ], + ], + ], + ], + ], + ]; + + $serviceListener = new ServiceListenerFactory(); + $r = new ReflectionProperty($serviceListener, 'defaultServiceConfig'); + $r->setAccessible(true); + $serviceConfig = $r->getValue($serviceListener); + + $serviceConfig = ArrayUtils::merge( + $serviceConfig, + [ + 'aliases' => [ + 'ControllerLoader' => ControllerManager::class, + 'ControllerManager' => ControllerManager::class, + 'Router' => 'HttpRouter', + ], + 'factories' => [ + ControllerManager::class => function ($services) { + return new ControllerManager($services, ['factories' => [ + 'path' => function () { + return new TestAsset\PathController(); + }, + ]]); + }, + ], + 'invokables' => [ + 'Request' => 'Zend\Http\PhpEnvironment\Request', + 'Response' => Response::class, + 'ViewManager' => TestAsset\MockViewManager::class, + 'SendResponseListener' => TestAsset\MockSendResponseListener::class, + 'BootstrapListener' => TestAsset\StubBootstrapListener::class, + ], + 'services' => [ + 'config' => $config, + 'ApplicationConfig' => [ + 'modules' => [], + 'module_listener_options' => [ + 'config_cache_enabled' => false, + 'cache_dir' => 'data/cache', + 'module_paths' => [], + ], + ], + ], + ] + ); + $services = new ServiceManager((new ServiceManagerConfig($serviceConfig))->toArray()); + $application = $services->get('Application'); + + $request = $services->get('Request'); + $request->setUri('http://example.local/path'); + + $application->bootstrap(); + return $application; + } +} diff --git a/test/Application/RoutingSuccessTest.php b/test/Application/RoutingSuccessTest.php new file mode 100644 index 000000000..5c47b2e8f --- /dev/null +++ b/test/Application/RoutingSuccessTest.php @@ -0,0 +1,36 @@ +prepareApplication(); + + $log = []; + + $application->getEventManager()->attach(MvcEvent::EVENT_ROUTE, function ($e) use (&$log) { + $match = $e->getRouteMatch(); + $this->assertInstanceOf(Router\RouteMatch::class, $match, 'Did not receive expected route match'); + $log['route-match'] = $match; + }, -100); + + $application->run(); + $this->assertArrayHasKey('route-match', $log); + $this->assertInstanceOf(Router\RouteMatch::class, $log['route-match']); + } +} diff --git a/test/Application/TestAsset/modules/Application/Module.php b/test/Application/TestAsset/modules/Application/Module.php new file mode 100644 index 000000000..acff8cf88 --- /dev/null +++ b/test/Application/TestAsset/modules/Application/Module.php @@ -0,0 +1,29 @@ + array( + 'namespaces' => array( + __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, + ), + ), + ); + } +} diff --git a/test/Application/TestAsset/modules/Application/config/module.config.php b/test/Application/TestAsset/modules/Application/config/module.config.php new file mode 100644 index 000000000..749f51cde --- /dev/null +++ b/test/Application/TestAsset/modules/Application/config/module.config.php @@ -0,0 +1,66 @@ + [ + 'factories' => [ + 'path' => function () { + return new Controller\PathController(); + }, + ], + ], + 'router' => [ + 'routes' => [ + 'path' => [ + 'type' => 'literal', + 'options' => [ + 'route' => '/path', + 'defaults' => [ + 'controller' => 'path', + ], + ], + ], + ], + ], + 'service_manager' => [ + 'factories' => [ + 'Request' => function () { + return new HttpRequest(); + }, + 'Response' => function () { + return new HttpResponse(); + }, + 'Router' => HttpRouterFactory::class, + 'ViewManager' => HttpViewManagerFactory::class, + ], + ], + 'view_manager' => array( + 'display_not_found_reason' => true, + 'display_exceptions' => true, + 'doctype' => 'HTML5', + 'not_found_template' => 'error/404', + 'exception_template' => 'error/index', + 'template_map' => array( + 'layout/layout' => __DIR__ . '/../view/layout/layout.phtml', + 'application/index/index' => __DIR__ . '/../view/application/index/index.phtml', + 'error/404' => __DIR__ . '/../view/error/404.phtml', + 'error/index' => __DIR__ . '/../view/error/index.phtml', + ), + 'template_path_stack' => array( + __DIR__ . '/../view', + ), + ), +]; diff --git a/test/Application/TestAsset/modules/Application/src/Application/Controller/PathController.php b/test/Application/TestAsset/modules/Application/src/Application/Controller/PathController.php new file mode 100644 index 000000000..2e1be4ebd --- /dev/null +++ b/test/Application/TestAsset/modules/Application/src/Application/Controller/PathController.php @@ -0,0 +1,27 @@ +setContent(__METHOD__); + return $response; + } +} diff --git a/test/Application/TestAsset/modules/Application/view/application/index/index.phtml b/test/Application/TestAsset/modules/Application/view/application/index/index.phtml new file mode 100644 index 000000000..ff98a33ff --- /dev/null +++ b/test/Application/TestAsset/modules/Application/view/application/index/index.phtml @@ -0,0 +1,5 @@ +

Home Page

+ +

+ This is the home page. +

diff --git a/test/Application/TestAsset/modules/Application/view/error/404.phtml b/test/Application/TestAsset/modules/Application/view/error/404.phtml new file mode 100644 index 000000000..f53d90ae7 --- /dev/null +++ b/test/Application/TestAsset/modules/Application/view/error/404.phtml @@ -0,0 +1,107 @@ +

A 404 error occurred

+

message ?>

+ +reason) && $this->reason): ?> + +reason) { + case 'error-controller-cannot-dispatch': + $reasonMessage = 'The requested controller was unable to dispatch the request.'; + break; + case 'error-controller-not-found': + $reasonMessage = 'The requested controller could not be mapped to an existing controller class.'; + break; + case 'error-controller-invalid': + $reasonMessage = 'The requested controller was not dispatchable.'; + break; + case 'error-router-no-match': + $reasonMessage = 'The requested URL could not be matched by routing.'; + break; + default: + $reasonMessage = 'We cannot determine at this time why a 404 was generated.'; + break; +} +?> + +

+ + + +controller) && $this->controller): ?> + +
+
Controller:
+
escapeHtml($this->controller) ?> +controller_class) + && $this->controller_class + && $this->controller_class != $this->controller +) { + echo '(' . sprintf('resolves to %s', $this->escapeHtml($this->controller_class)) . ')'; +} +?> +
+
+ + + +display_exceptions) && $this->display_exceptions): ?> + +exception) && $this->exception instanceof Exception): ?> +
+

Additional information:

+

exception); ?>

+
+
File:
+
+
exception->getFile() ?>:exception->getLine() ?>
+
+
Message:
+
+
exception->getMessage() ?>
+
+
Stack trace:
+
+
exception->getTraceAsString() ?>
+
+
+exception->getPrevious(); + if ($e) : +?> +
+

Previous exceptions:

+ + + + + +

No Exception available

+ + + + diff --git a/test/Application/TestAsset/modules/Application/view/error/index.phtml b/test/Application/TestAsset/modules/Application/view/error/index.phtml new file mode 100644 index 000000000..5f013493b --- /dev/null +++ b/test/Application/TestAsset/modules/Application/view/error/index.phtml @@ -0,0 +1,62 @@ +

An error occurred

+

message ?>

+ +display_exceptions) && $this->display_exceptions): ?> + +exception) && $this->exception instanceof Exception): ?> +
+

Additional information:

+

exception); ?>

+
+
File:
+
+
exception->getFile() ?>:exception->getLine() ?>
+
+
Message:
+
+
escapeHtml($this->exception->getMessage()) ?>
+
+
Stack trace:
+
+
escapeHtml($this->exception->getTraceAsString()) ?>
+
+
+exception->getPrevious(); + if ($e) : +?> +
+

Previous exceptions:

+ + + + + +

No Exception available

+ + + + diff --git a/test/Application/TestAsset/modules/Application/view/layout/layout.phtml b/test/Application/TestAsset/modules/Application/view/layout/layout.phtml new file mode 100644 index 000000000..ac6e48032 --- /dev/null +++ b/test/Application/TestAsset/modules/Application/view/layout/layout.phtml @@ -0,0 +1,14 @@ +doctype(); ?> + + + + + headTitle('ZF2 Skeleton Application')->setSeparator(' - ')->setAutoEscape(false) ?> + + + +
+ content; ?> +
+ + diff --git a/test/ApplicationTest.php b/test/ApplicationTest.php index 23add63af..dbb4a7aaa 100644 --- a/test/ApplicationTest.php +++ b/test/ApplicationTest.php @@ -9,15 +9,15 @@ namespace ZendTest\Mvc; -use ArrayObject; use PHPUnit_Framework_TestCase as TestCase; -use ReflectionObject; +use ReflectionMethod; use ReflectionProperty; use stdClass; use Zend\Http\PhpEnvironment\Response; use Zend\ModuleManager\Listener\ConfigListener; use Zend\ModuleManager\ModuleEvent; use Zend\Mvc\Application; +use Zend\Mvc\Controller\ControllerManager; use Zend\Mvc\MvcEvent; use Zend\Mvc\Router; use Zend\Mvc\Service\ServiceManagerConfig; @@ -42,10 +42,14 @@ class ApplicationTest extends TestCase public function setUp() { + $serviceListener = new ServiceListenerFactory(); + $r = new ReflectionProperty($serviceListener, 'defaultServiceConfig'); + $r->setAccessible(true); + $serviceConfig = $r->getValue($serviceListener); + $serviceConfig = ArrayUtils::merge( - $this->readAttribute(new ServiceListenerFactory, 'defaultServiceConfig'), + $serviceConfig, [ - 'allow_override' => true, 'invokables' => [ 'Request' => 'Zend\Http\PhpEnvironment\Request', 'Response' => 'Zend\Http\PhpEnvironment\Response', @@ -57,7 +61,7 @@ public function setUp() 'Router' => 'HttpRouter', ], 'services' => [ - 'Config' => [], + 'config' => [], 'ApplicationConfig' => [ 'modules' => [], 'module_listener_options' => [ @@ -69,10 +73,25 @@ public function setUp() ], ] ); - $this->serviceManager = new ServiceManager(new ServiceManagerConfig($serviceConfig)); + $this->serviceManager = new ServiceManager((new ServiceManagerConfig($serviceConfig))->toArray()); $this->application = $this->serviceManager->get('Application'); } + /** + * Re-inject the application service manager instance + * + * @param Application $application + * @param ServiceManager $services + * @return Application + */ + public function setApplicationServiceManager(Application $application, ServiceManager $services) + { + $r = new ReflectionProperty($application, 'serviceManager'); + $r->setAccessible(true); + $r->setValue($application, $services); + return $application; + } + public function getConfigListener() { $manager = $this->serviceManager->get('ModuleManager'); @@ -125,9 +144,13 @@ public function testServiceManagerIsPopulated() public function testConfigIsPopulated() { - $smConfig = $this->serviceManager->get('Config'); + $smConfig = $this->serviceManager->get('config'); $appConfig = $this->application->getConfig(); - $this->assertEquals($smConfig, $appConfig, sprintf('SM config: %s; App config: %s', var_export($smConfig, 1), var_export($appConfig, 1))); + $this->assertEquals( + $smConfig, + $appConfig, + sprintf('SM config: %s; App config: %s', var_export($smConfig, 1), var_export($appConfig, 1)) + ); } public function testEventsAreEmptyAtFirst() @@ -160,21 +183,24 @@ public function testBootstrapRegistersListeners($listenerServiceName, $event, $m public function bootstrapRegistersListenersProvider() { + // @codingStandardsIgnoreStart + // [ Service Name, Event, Method, isCustom ] return [ - ['RouteListener', MvcEvent::EVENT_ROUTE, 'onRoute'], - ['DispatchListener', MvcEvent::EVENT_DISPATCH, 'onDispatch'], - ['SendResponseListener', MvcEvent::EVENT_FINISH, 'sendResponse'], - ['ViewManager', MvcEvent::EVENT_BOOTSTRAP, 'onBootstrap'], - ['HttpMethodListener', MvcEvent::EVENT_ROUTE, 'onRoute'], - ['BootstrapListener', MvcEvent::EVENT_BOOTSTRAP, 'onBootstrap', true], + 'route' => ['RouteListener' , MvcEvent::EVENT_ROUTE , 'onRoute', false], + 'dispatch' => ['DispatchListener' , MvcEvent::EVENT_DISPATCH , 'onDispatch', false], + 'send_response' => ['SendResponseListener' , MvcEvent::EVENT_FINISH , 'sendResponse', false], + 'view_manager' => ['ViewManager' , MvcEvent::EVENT_BOOTSTRAP , 'onBootstrap', false], + 'http_method' => ['HttpMethodListener' , MvcEvent::EVENT_ROUTE , 'onRoute', false], + 'bootstrap' => ['BootstrapListener' , MvcEvent::EVENT_BOOTSTRAP , 'onBootstrap', true ], ]; + // @codingStandardsIgnoreEnd } public function testBootstrapAlwaysRegistersDefaultListeners() { - $refl = new ReflectionProperty($this->application, 'defaultListeners'); - $refl->setAccessible(true); - $defaultListenersNames = $refl->getValue($this->application); + $r = new ReflectionProperty($this->application, 'defaultListeners'); + $r->setAccessible(true); + $defaultListenersNames = $r->getValue($this->application); $defaultListeners = []; foreach ($defaultListenersNames as $defaultListenerName) { $defaultListeners[] = $this->serviceManager->get($defaultListenerName); @@ -230,13 +256,31 @@ public function setupPathController($addService = true) ], ]); $router->addRoute('path', $route); + $services = $this->serviceManager->withConfig([ + 'aliases' => [ + 'Router' => 'HttpRouter', + ], + 'services' => [ + 'HttpRouter' => $router, + ], + ]); + + $application = $this->setApplicationServiceManager($this->application, $services); if ($addService) { - $controllerLoader = $this->serviceManager->get('ControllerLoader'); - $controllerLoader->setFactory('path', function () { - return new TestAsset\PathController; - }); + $services = $services->withConfig(['factories' => [ + 'ControllerManager' => function ($services) { + return new ControllerManager($services, ['factories' => [ + 'path' => function () { + return new TestAsset\PathController; + }, + ]]); + }, + ]]); + $application = $this->setApplicationServiceManager($application, $services); } - $this->application->bootstrap(); + + $application->bootstrap(); + return $application; } public function setupActionController() @@ -254,11 +298,19 @@ public function setupActionController() ]); $router->addRoute('sample', $route); - $controllerLoader = $this->serviceManager->get('ControllerLoader'); - $controllerLoader->setFactory('sample', function () { - return new Controller\TestAsset\SampleController; - }); - $this->application->bootstrap(); + $services = $this->serviceManager->withConfig(['factories' => [ + 'ControllerManager' => function ($services) { + return new ControllerManager($services, ['factories' => [ + 'sample' => function () { + return new Controller\TestAsset\SampleController(); + }, + ]]); + }, + ]]); + $application = $this->setApplicationServiceManager($this->application, $services); + + $application->bootstrap(); + return $application; } public function setupBadController($addService = true) @@ -276,170 +328,36 @@ public function setupBadController($addService = true) ]); $router->addRoute('bad', $route); + $application = $this->application; if ($addService) { - $controllerLoader = $this->serviceManager->get('ControllerLoader'); - $controllerLoader->setFactory('bad', function () { - return new Controller\TestAsset\BadController; - }); + $services = $this->serviceManager->withConfig(['factories' => [ + 'ControllerManager' => function ($services) { + return new ControllerManager($services, ['factories' => [ + 'bad' => function () { + return new Controller\TestAsset\BadController(); + }, + ]]); + }, + ]]); + $application = $this->setApplicationServiceManager($application, $services); } - $this->application->bootstrap(); - } - - public function testRoutingIsExecutedDuringRun() - { - $this->setupPathController(); - - $log = []; - $this->application->getEventManager()->attach(MvcEvent::EVENT_ROUTE, function ($e) use (&$log) { - $match = $e->getRouteMatch(); - if (!$match) { - return; - } - $log['route-match'] = $match; - }); - - $this->application->run(); - $this->assertArrayHasKey('route-match', $log); - $this->assertInstanceOf(Router\RouteMatch::class, $log['route-match']); - } - - public function testAllowsReturningEarlyFromRouting() - { - $this->setupPathController(); - $response = new Response(); - $this->application->getEventManager()->attach(MvcEvent::EVENT_ROUTE, function ($e) use ($response) { - return $response; - }); - - $result = $this->application->run(); - $this->assertSame($this->application, $result); - $this->assertSame($response, $result->getResponse()); - } - - public function testControllerIsDispatchedDuringRun() - { - $this->setupPathController(); - - $response = $this->application->run()->getResponse(); - $this->assertContains('PathController', $response->getContent()); - $this->assertContains(MvcEvent::EVENT_DISPATCH, $response->toString()); - } - - /** - * @group zen-92 - */ - public function testDispatchingInjectsLocatorInLocatorAwareControllers() - { - $this->setupActionController(); - - $events = $this->application->getEventManager()->getSharedManager(); - $storage = new ArrayObject(); - $events->attach('ZendTest\Mvc\Controller\TestAsset\SampleController', MvcEvent::EVENT_DISPATCH, function ($e) use ($storage) { - $controller = $e->getTarget(); - $storage['locator'] = $controller->getServiceLocator(); - return $e->getResponse(); - }, 100); - - $this->application->run(); - - $this->assertTrue(isset($storage['locator'])); - $this->assertSame($this->serviceManager, $storage['locator']); + $application->bootstrap(); + return $application; } public function testFinishEventIsTriggeredAfterDispatching() { - $this->setupActionController(); - $this->application->getEventManager()->attach(MvcEvent::EVENT_FINISH, function ($e) { + $application = $this->setupActionController(); + $application->getEventManager()->attach(MvcEvent::EVENT_FINISH, function ($e) { return $e->getResponse()->setContent($e->getResponse()->getBody() . 'foobar'); }); - $this->application->run(); - $this->assertContains('foobar', $this->application->getResponse()->getBody(), 'The "finish" event was not triggered ("foobar" not in response)'); - } - - /** - * @group error-handling - */ - public function testExceptionsRaisedInDispatchableShouldRaiseDispatchErrorEvent() - { - $this->setupBadController(); - $response = $this->application->getResponse(); - $events = $this->application->getEventManager(); - $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { - $exception = $e->getParam('exception'); - $response->setContent($exception->getMessage()); - return $response; - }); - - $this->application->run(); - $this->assertContains('Raised an exception', $response->getContent()); - } - - /** - * @group error-handling - */ - public function testInabilityToRetrieveControllerShouldTriggerExceptionError() - { - $this->setupBadController(false); - $controllerLoader = $this->serviceManager->get('ControllerLoader'); - $response = $this->application->getResponse(); - $events = $this->application->getEventManager(); - $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { - $error = $e->getError(); - $controller = $e->getController(); - $response->setContent("Code: " . $error . '; Controller: ' . $controller); - return $response; - }); - - $this->application->run(); - $this->assertContains(Application::ERROR_CONTROLLER_NOT_FOUND, $response->getContent()); - $this->assertContains('bad', $response->getContent()); - } - - /** - * @group error-handling - */ - public function testInabilityToRetrieveControllerShouldTriggerDispatchError() - { - $this->setupBadController(false); - $response = $this->application->getResponse(); - $events = $this->application->getEventManager(); - $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { - $error = $e->getError(); - $controller = $e->getController(); - $response->setContent("Code: " . $error . '; Controller: ' . $controller); - return $response; - }); - - $this->application->run(); - $this->assertContains(Application::ERROR_CONTROLLER_NOT_FOUND, $response->getContent()); - $this->assertContains('bad', $response->getContent()); - } - - /** - * @group error-handling - */ - public function testInvalidControllerTypeShouldTriggerDispatchError() - { - $this->serviceManager->get('ControllerLoader'); - $this->setupBadController(false); - $controllerLoader = $this->serviceManager->get('ControllerLoader'); - $controllerLoader->setFactory('bad', function () { - return new stdClass; - }); - $response = $this->application->getResponse(); - $events = $this->application->getEventManager(); - $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { - $error = $e->getError(); - $controller = $e->getController(); - $class = $e->getControllerClass(); - $response->setContent("Code: " . $error . '; Controller: ' . $controller . '; Class: ' . $class); - return $response; - }); - - $this->application->run(); - $this->assertContains(Application::ERROR_CONTROLLER_INVALID, $response->getContent()); - $this->assertContains('bad', $response->getContent()); + $application->run(); + $this->assertContains( + 'foobar', + $this->application->getResponse()->getBody(), + 'The "finish" event was not triggered ("foobar" not in response)' + ); } /** @@ -447,20 +365,20 @@ public function testInvalidControllerTypeShouldTriggerDispatchError() */ public function testRoutingFailureShouldTriggerDispatchError() { - $this->setupBadController(); - $router = new Router\SimpleRouteStack(); - $event = $this->application->getMvcEvent(); + $application = $this->setupBadController(); + $router = new Router\SimpleRouteStack(); + $event = $application->getMvcEvent(); $event->setRouter($router); - $response = $this->application->getResponse(); - $events = $this->application->getEventManager(); + $response = $application->getResponse(); + $events = $application->getEventManager(); $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { $error = $e->getError(); $response->setContent("Code: " . $error); return $response; }); - $this->application->run(); + $application->run(); $this->assertTrue($event->isError()); $this->assertContains(Application::ERROR_ROUTER_NO_MATCH, $response->getContent()); } @@ -470,15 +388,15 @@ public function testRoutingFailureShouldTriggerDispatchError() */ public function testLocatorExceptionShouldTriggerDispatchError() { - $this->setupPathController(false); - $controllerLoader = $this->serviceManager->get('ControllerLoader'); + $application = $this->setupPathController(false); + $controllerLoader = $application->getServiceManager()->get('ControllerManager'); $response = new Response(); - $this->application->getEventManager()->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { + $application->getEventManager()->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { return $response; }); - $result = $this->application->run(); - $this->assertSame($this->application, $result, get_class($result)); + $result = $application->run(); + $this->assertSame($application, $result, get_class($result)); $this->assertSame($response, $result->getResponse(), get_class($result)); } @@ -487,20 +405,20 @@ public function testLocatorExceptionShouldTriggerDispatchError() */ public function testFailureForRouteToReturnRouteMatchShouldPopulateEventError() { - $this->setupBadController(); - $router = new Router\SimpleRouteStack(); - $event = $this->application->getMvcEvent(); + $application = $this->setupBadController(); + $router = new Router\SimpleRouteStack(); + $event = $application->getMvcEvent(); $event->setRouter($router); - $response = $this->application->getResponse(); - $events = $this->application->getEventManager(); + $response = $application->getResponse(); + $events = $application->getEventManager(); $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($response) { $error = $e->getError(); $response->setContent("Code: " . $error); return $response; }); - $this->application->run(); + $application->run(); $this->assertTrue($event->isError()); $this->assertEquals(Application::ERROR_ROUTER_NO_MATCH, $event->getError()); } @@ -552,30 +470,30 @@ public function testFinishShouldRunEvenIfDispatchEventReturnsResponse() public function testApplicationShouldBeEventTargetAtFinishEvent() { - $this->setupActionController(); + $application = $this->setupActionController(); - $events = $this->application->getEventManager(); - $response = $this->application->getResponse(); + $events = $application->getEventManager(); + $response = $application->getResponse(); $events->attach(MvcEvent::EVENT_FINISH, function ($e) use ($response) { $response->setContent("EventClass: " . get_class($e->getTarget())); return $response; }); - $this->application->run(); + $application->run(); $this->assertContains('Zend\Mvc\Application', $response->getContent()); } public function testOnDispatchErrorEventPassedToTriggersShouldBeTheOriginalOne() { - $this->setupPathController(false); - $controllerLoader = $this->serviceManager->get('ControllerLoader'); + $application = $this->setupPathController(false); + $controllerManager = $application->getServiceManager()->get('ControllerManager'); $model = $this->getMock('Zend\View\Model\ViewModel'); - $this->application->getEventManager()->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($model) { + $application->getEventManager()->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use ($model) { $e->setResult($model); }); - $this->application->run(); - $event = $this->application->getMvcEvent(); + $application->run(); + $event = $application->getMvcEvent(); $this->assertInstanceOf('Zend\View\Model\ViewModel', $event->getResult()); } @@ -631,13 +549,12 @@ public function testReturnsResponseFromListenerWhenDispatchEventShortCircuits() public function testCompleteRequestShouldReturnApplicationInstance() { - $r = new ReflectionObject($this->application); - $method = $r->getMethod('completeRequest'); - $method->setAccessible(true); + $r = new ReflectionMethod($this->application, 'completeRequest'); + $r->setAccessible(true); $this->application->bootstrap(); $event = $this->application->getMvcEvent(); - $result = $method->invoke($this->application, $event); + $result = $r->invoke($this->application, $event); $this->assertSame($this->application, $result); } @@ -724,10 +641,9 @@ public function testEventPropagationStatusIsClearedBetweenEventsDuringRun($event $event->stopPropagation(true); // Intentionally not calling bootstrap; setting mvc event - $r = new ReflectionObject($this->application); - $eventProp = $r->getProperty('event'); - $eventProp->setAccessible(true); - $eventProp->setValue($this->application, $event); + $r = new ReflectionProperty($this->application, 'event'); + $r->setAccessible(true); + $r->setValue($this->application, $event); // Setup listeners that stop propagation, but do nothing else $marker = []; diff --git a/test/Controller/AbstractControllerTest.php b/test/Controller/AbstractControllerTest.php index ec922fcd8..4b18a4eeb 100644 --- a/test/Controller/AbstractControllerTest.php +++ b/test/Controller/AbstractControllerTest.php @@ -99,8 +99,7 @@ public function testSetEventManagerWithDefaultIdentifiersIncludesImplementedInte ->with($this->logicalAnd( $this->contains('Zend\\EventManager\\EventManagerAwareInterface'), $this->contains('Zend\\Stdlib\\DispatchableInterface'), - $this->contains('Zend\\Mvc\\InjectApplicationEventInterface'), - $this->contains('Zend\\ServiceManager\\ServiceLocatorAwareInterface') + $this->contains('Zend\\Mvc\\InjectApplicationEventInterface') )); $this->controller->setEventManager($eventManager); diff --git a/test/Controller/ActionControllerTest.php b/test/Controller/ActionControllerTest.php index a7a336d76..5c51cc77a 100644 --- a/test/Controller/ActionControllerTest.php +++ b/test/Controller/ActionControllerTest.php @@ -18,6 +18,7 @@ use Zend\Mvc\Controller\PluginManager; use Zend\Mvc\MvcEvent; use Zend\Mvc\Router\RouteMatch; +use Zend\ServiceManager\ServiceManager; class ActionControllerTest extends TestCase { @@ -160,11 +161,6 @@ public function testDispatchInjectsEventIntoController() $this->assertSame($this->event, $event); } - public function testControllerIsLocatorAware() - { - $this->assertInstanceOf('Zend\ServiceManager\ServiceLocatorAwareInterface', $this->controller); - } - public function testControllerIsEventAware() { $this->assertInstanceOf('Zend\Mvc\InjectApplicationEventInterface', $this->controller); @@ -190,7 +186,7 @@ public function testPluginManagerComposesController() public function testInjectingPluginManagerSetsControllerWhenPossible() { - $plugins = new PluginManager(); + $plugins = new PluginManager(new ServiceManager()); $this->assertNull($plugins->getController()); $this->controller->setPluginManager($plugins); $this->assertSame($this->controller, $plugins->getController()); diff --git a/test/Controller/ControllerManagerTest.php b/test/Controller/ControllerManagerTest.php index 302cab80f..d9336bdd1 100644 --- a/test/Controller/ControllerManagerTest.php +++ b/test/Controller/ControllerManagerTest.php @@ -21,30 +21,30 @@ class ControllerManagerTest extends TestCase { public function setUp() { - $this->sharedEvents = new SharedEventManager; - $this->events = new EventManager($this->sharedEvents); - + $this->sharedEvents = new SharedEventManager; + $this->events = new EventManager($this->sharedEvents); $this->consoleAdapter = new ConsoleAdapter(); - $this->plugins = new ControllerPluginManager(); - $this->services = new ServiceManager(); - $this->services->setService('Console', $this->consoleAdapter); - $this->services->setService('Zend\ServiceManager\ServiceLocatorInterface', $this->services); - $this->services->setService('EventManager', $this->events); - $this->services->setService('SharedEventManager', $this->sharedEvents); - $this->services->setService('ControllerPluginManager', $this->plugins); + $this->services = new ServiceManager([ + 'factories' => [ + 'ControllerPluginManager' => function ($services) { + return new ControllerPluginManager($services); + }, + ], + 'services' => [ + 'Console' => $this->consoleAdapter, + 'EventManager' => $this->events, + 'SharedEventManager' => $this->sharedEvents, + ], + ]); - $this->controllers = new ControllerManager(); - $this->controllers->setServiceLocator($this->services); - $this->controllers->addPeeringServiceManager($this->services); + $this->controllers = new ControllerManager($this->services); } - public function testInjectControllerDependenciesInjectsExpectedDependencies() + public function testCanInjectEventManager() { $controller = new TestAsset\SampleController(); - $this->controllers->injectControllerDependencies($controller, $this->controllers); - $this->assertSame($this->services, $controller->getServiceLocator()); - $this->assertSame($this->plugins, $controller->getPluginManager()); + $this->controllers->injectEventManager($this->services, $controller); // The default AbstractController implementation lazy instantiates an EM // instance, which means we need to check that that instance gets injected @@ -54,19 +54,26 @@ public function testInjectControllerDependenciesInjectsExpectedDependencies() $this->assertSame($this->sharedEvents, $events->getSharedManager()); } - public function testInjectControllerDependenciesToConsoleController() + public function testCanInjectConsoleAdapter() { $controller = new TestAsset\ConsoleController(); - $this->controllers->injectControllerDependencies($controller, $this->controllers); + $this->controllers->injectConsole($this->services, $controller); $this->assertInstanceOf('Zend\Console\Adapter\AdapterInterface', $controller->getConsole()); } - public function testInjectControllerDependenciesWillNotOverwriteExistingEventManager() + public function testCanInjectPluginManager() + { + $controller = new TestAsset\SampleController(); + $this->controllers->injectPluginManager($this->services, $controller); + $this->assertSame($this->services->get('ControllerPluginManager'), $controller->getPluginManager()); + } + + public function testInjectEventManagerWillNotOverwriteExistingEventManagerIfItAlreadyHasASharedManager() { $events = new EventManager($this->sharedEvents); $controller = new TestAsset\SampleController(); $controller->setEventManager($events); - $this->controllers->injectControllerDependencies($controller, $this->controllers); + $this->controllers->injectEventManager($this->services, $controller); $this->assertSame($events, $controller->getEventManager()); $this->assertSame($this->sharedEvents, $events->getSharedManager()); } diff --git a/test/Controller/IntegrationTest.php b/test/Controller/IntegrationTest.php index 39ecea1dd..4c4bdfe75 100644 --- a/test/Controller/IntegrationTest.php +++ b/test/Controller/IntegrationTest.php @@ -20,27 +20,39 @@ class IntegrationTest extends TestCase { public function setUp() { - $this->plugins = new PluginManager(); - $this->sharedEvents = $sharedEvents = new SharedEventManager(); - $this->services = new ServiceManager(); - $this->services->setService('ControllerPluginManager', $this->plugins); - $this->services->setService('SharedEventManager', $this->sharedEvents); - $this->services->setService('Zend\ServiceManager\ServiceLocatorInterface', $this->services); - $this->services->setFactory('EventManager', function ($services) use ($sharedEvents) { - return new EventManager($sharedEvents); - }); - - $this->controllers = new ControllerManager(); - $this->controllers->setServiceLocator($this->services); + $this->sharedEvents = new SharedEventManager(); + + $this->services = new ServiceManager([ + 'services' => [ + 'SharedEventManager' => $this->sharedEvents, + ], + 'factories' => [ + 'ControllerPluginManager' => function ($services) { + return new PluginManager($services); + }, + 'EventManager' => function () { + return new EventManager($this->sharedEvents); + }, + ], + 'shared' => [ + 'EventManager' => false, + ], + ]); } public function testPluginReceivesCurrentController() { - $this->controllers->setInvokableClass('first', 'ZendTest\Mvc\Controller\TestAsset\SampleController'); - $this->controllers->setInvokableClass('second', 'ZendTest\Mvc\Controller\TestAsset\SampleController'); + $controllers = new ControllerManager($this->services, ['factories' => [ + 'first' => function ($services) { + return new TestAsset\SampleController(); + }, + 'second' => function ($services) { + return new TestAsset\SampleController(); + }, + ]]); - $first = $this->controllers->get('first'); - $second = $this->controllers->get('second'); + $first = $controllers->get('first'); + $second = $controllers->get('second'); $this->assertNotSame($first, $second); $plugin1 = $first->plugin('url'); diff --git a/test/Controller/Plugin/FilePostRedirectGetTest.php b/test/Controller/Plugin/FilePostRedirectGetTest.php index da8677683..8db119140 100644 --- a/test/Controller/Plugin/FilePostRedirectGetTest.php +++ b/test/Controller/Plugin/FilePostRedirectGetTest.php @@ -37,6 +37,8 @@ class FilePostRedirectGetTest extends TestCase public function setUp() { + $this->markTestIncomplete('Re-enable when zend-form has been updated to zend-servicemanager v3'); + $this->form = new Form(); $this->collection = new Collection('links', [ diff --git a/test/Controller/Plugin/ForwardTest.php b/test/Controller/Plugin/ForwardTest.php index 8af5c829a..c4211acac 100644 --- a/test/Controller/Plugin/ForwardTest.php +++ b/test/Controller/Plugin/ForwardTest.php @@ -20,10 +20,10 @@ use Zend\Mvc\Controller\Plugin\Forward as ForwardPlugin; use Zend\Mvc\MvcEvent; use Zend\Mvc\Router\RouteMatch; +use Zend\ServiceManager\ServiceManager; use ZendTest\Mvc\Controller\TestAsset\ForwardController; use ZendTest\Mvc\Controller\TestAsset\SampleController; use ZendTest\Mvc\Controller\TestAsset\UneventfulController; -use ZendTest\Mvc\TestAsset\Locator; class ForwardTest extends TestCase { @@ -62,41 +62,44 @@ public function setUp() $routeMatch->setMatchedRouteName('some-route'); $event->setRouteMatch($routeMatch); - $services = new Locator(); - $plugins = $this->plugins = new PluginManager(); - $plugins->setServiceLocator($services); - - $controllers = $this->controllers = new ControllerManager(); - $controllers->setFactory('forward', function () use ($plugins) { - $controller = new ForwardController(); - $controller->setPluginManager($plugins); - return $controller; - }); - $controllers->setServiceLocator($services); - $controllerLoader = function () use ($controllers) { - return $controllers; - }; - $services->add('ControllerLoader', $controllerLoader); - $services->add('ControllerManager', $controllerLoader); - $services->add('ControllerPluginManager', function () use ($plugins) { - return $plugins; - }); - $services->add('Zend\ServiceManager\ServiceLocatorInterface', function () use ($services) { - return $services; - }); - $services->add('EventManager', function () use ($eventManager) { - return new EventManager($eventManager->getSharedManager()); - }); - $services->add('SharedEventManager', function () use ($eventManager) { - return $eventManager->getSharedManager(); - }); + $this->services = $services = new ServiceManager([ + 'aliases' => [ + 'ControllerLoader' => 'ControllerManager', + ], + 'factories' => [ + 'ControllerManager' => function ($services, $name) { + $plugins = $services->get('ControllerPluginManager'); + return new ControllerManager($services, ['factories' => [ + 'forward' => function ($services) use ($plugins) { + $controller = new ForwardController(); + $controller->setPluginManager($plugins); + return $controller; + }, + ]]); + }, + 'ControllerPluginManager' => function ($services, $name) { + return new PluginManager($services); + }, + 'EventManager' => function ($services, $name) { + return new EventManager($services->get('SharedEventManager')); + }, + 'SharedEventManager' => function ($services, $name) { + return new SharedEventManager(); + }, + ], + 'shared' => [ + 'EventManager' => false, + ], + ]); + + $this->controllers = $services->get('ControllerManager'); + $plugins = $services->get('ControllerPluginManager'); $this->controller = new SampleController(); $this->controller->setEvent($event); - $this->controller->setServiceLocator($services); $this->controller->setPluginManager($plugins); - $this->plugin = $this->controller->plugin('forward'); + $this->plugin = $plugins->get('forward'); } public function testPluginWithoutEventAwareControllerRaisesDomainException() @@ -117,20 +120,66 @@ public function testPluginWithoutControllerLocatorRaisesServiceNotCreatedExcepti public function testDispatchRaisesDomainExceptionIfDiscoveredControllerIsNotDispatchable() { - $locator = $this->controller->getServiceLocator(); - $locator->add('bogus', function () { - return new stdClass; - }); - $this->setExpectedException('Zend\ServiceManager\Exception\ServiceNotFoundException'); - $this->plugin->dispatch('bogus'); + $controllers = $this->controllers->withConfig(['factories' => [ + 'bogus' => function () { + return new stdClass; + }, + ]]); + $plugin = new ForwardPlugin($controllers); + $plugin->setController($this->controller); + + $this->setExpectedException('Zend\ServiceManager\Exception\InvalidServiceException', 'DispatchableInterface'); + $plugin->dispatch('bogus'); } public function testDispatchRaisesDomainExceptionIfCircular() { + $event = $this->controller->getEvent(); + + $services = new ServiceManager([ + 'aliases' => [ + 'ControllerLoader' => 'ControllerManager', + ], + 'factories' => [ + 'ControllerManager' => function ($services) use ($event) { + $plugins = $services->get('ControllerPluginManager'); + + return new ControllerManager($services, ['factories' => [ + 'forward' => function ($services) use ($plugins) { + $controller = new ForwardController(); + $controller->setPluginManager($plugins); + return $controller; + }, + 'sample' => function ($services) use ($event, $plugins) { + $controller = new SampleController(); + $controller->setEvent($event); + $controller->setPluginManager($plugins); + return $controller; + }, + ]]); + }, + 'ControllerPluginManager' => function ($services) { + return new PluginManager($services); + }, + 'EventManager' => function ($services, $name) { + return new EventManager($services->get('SharedEventManager')); + }, + 'SharedEventManager' => function ($services, $name) { + return new SharedEventManager(); + }, + ], + 'shared' => [ + 'EventManager' => false, + ], + ]); + + $controllers = $services->get('ControllerManager'); + + $forward = new ForwardPlugin($controllers); + $forward->setController($controllers->get('sample')); + $this->setExpectedException('Zend\Mvc\Exception\DomainException', 'Circular forwarding'); - $sampleController = $this->controller; - $this->controllers->setService('sample', $sampleController); - $this->plugin->dispatch('sample', ['action' => 'test-circular']); + $forward->dispatch('sample', ['action' => 'test-circular']); } public function testPluginDispatchsRequestedControllerWhenFound() @@ -145,7 +194,7 @@ public function testPluginDispatchsRequestedControllerWhenFound() */ public function testNonArrayListenerDoesNotRaiseErrorWhenPluginDispatchsRequestedController() { - $services = $this->plugins->getServiceLocator(); + $services = $this->services; $events = $services->get('EventManager'); $sharedEvents = $this->getMock('Zend\EventManager\SharedEventManagerInterface'); // @codingStandardsIgnoreStart diff --git a/test/Controller/Plugin/TestAsset/SamplePluginFactory.php b/test/Controller/Plugin/TestAsset/SamplePluginFactory.php index 99f2bcec7..a410b271a 100644 --- a/test/Controller/Plugin/TestAsset/SamplePluginFactory.php +++ b/test/Controller/Plugin/TestAsset/SamplePluginFactory.php @@ -9,12 +9,12 @@ namespace ZendTest\Mvc\Controller\Plugin\TestAsset; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class SamplePluginFactory implements FactoryInterface { - public function createService(ServiceLocatorInterface $serviceLocator) + public function __invoke(ContainerInterface $container, $name, array $options = null) { return new SamplePlugin(); } diff --git a/test/Controller/Plugin/TestAsset/SamplePluginWithConstructorFactory.php b/test/Controller/Plugin/TestAsset/SamplePluginWithConstructorFactory.php index b251e669d..4e37df4e0 100644 --- a/test/Controller/Plugin/TestAsset/SamplePluginWithConstructorFactory.php +++ b/test/Controller/Plugin/TestAsset/SamplePluginWithConstructorFactory.php @@ -9,20 +9,15 @@ namespace ZendTest\Mvc\Controller\Plugin\TestAsset; -use Zend\ServiceManager\FactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\FactoryInterface; class SamplePluginWithConstructorFactory implements FactoryInterface { protected $options; - public function __construct($options) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $this->options = $options; - } - - public function createService(ServiceLocatorInterface $serviceLocator) - { - return new SamplePluginWithConstructor($this->options); + return new SamplePluginWithConstructor($options); } } diff --git a/test/Controller/PluginManagerTest.php b/test/Controller/PluginManagerTest.php index 0c39a4fc3..582e214d5 100644 --- a/test/Controller/PluginManagerTest.php +++ b/test/Controller/PluginManagerTest.php @@ -10,28 +10,20 @@ namespace ZendTest\Mvc\Controller; use PHPUnit_Framework_TestCase as TestCase; -use ZendTest\Mvc\Controller\TestAsset\SampleController; -use ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin; +use Zend\Authentication\AuthenticationService; use Zend\Mvc\Controller\PluginManager; use Zend\ServiceManager\ServiceManager; +use ZendTest\Mvc\Controller\TestAsset\SampleController; +use ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin; class PluginManagerTest extends TestCase { - public function testPluginManagerThrowsExceptionForMissingPluginInterface() - { - $this->setExpectedException('Zend\Mvc\Exception\InvalidPluginException'); - - $pluginManager = new PluginManager; - $pluginManager->setInvokableClass('samplePlugin', 'stdClass'); - - $plugin = $pluginManager->get('samplePlugin'); - } - public function testPluginManagerInjectsControllerInPlugin() { $controller = new SampleController; - $pluginManager = new PluginManager; - $pluginManager->setInvokableClass('samplePlugin', 'ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin'); + $pluginManager = new PluginManager(new ServiceManager(), [ + 'invokables' => ['samplePlugin' => SamplePlugin::class], + ]); $pluginManager->setController($controller); $plugin = $pluginManager->get('samplePlugin'); @@ -41,8 +33,9 @@ public function testPluginManagerInjectsControllerInPlugin() public function testPluginManagerInjectsControllerForExistingPlugin() { $controller1 = new SampleController; - $pluginManager = new PluginManager; - $pluginManager->setInvokableClass('samplePlugin', 'ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin'); + $pluginManager = new PluginManager(new ServiceManager(), [ + 'invokables' => ['samplePlugin' => SamplePlugin::class], + ]); $pluginManager->setController($controller1); // Plugin manager registers now instance of SamplePlugin @@ -55,53 +48,63 @@ public function testPluginManagerInjectsControllerForExistingPlugin() $this->assertEquals($controller2, $plugin->getController()); } - public function testGetWithConstrutor() + public function testGetWithConstructor() { - $pluginManager = new PluginManager; - $pluginManager->setInvokableClass('samplePlugin', 'ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePluginWithConstructor'); + $pluginManager = new PluginManager(new ServiceManager(), [ + 'invokables' => ['samplePlugin' => Plugin\TestAsset\SamplePluginWithConstructor::class], + ]); $plugin = $pluginManager->get('samplePlugin'); $this->assertEquals($plugin->getBar(), 'baz'); } - public function testGetWithConstrutorAndOptions() + public function testGetWithConstructorAndOptions() { - $pluginManager = new PluginManager; - $pluginManager->setInvokableClass('samplePlugin', 'ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePluginWithConstructor'); - $plugin = $pluginManager->get('samplePlugin', 'foo'); - $this->assertEquals($plugin->getBar(), 'foo'); + $pluginManager = new PluginManager(new ServiceManager(), [ + 'invokables' => ['samplePlugin' => Plugin\TestAsset\SamplePluginWithConstructor::class], + ]); + $plugin = $pluginManager->get('samplePlugin', ['foo']); + $this->assertEquals($plugin->getBar(), ['foo']); } public function testDefinesFactoryForIdentityPlugin() { - $pluginManager = new PluginManager; + $pluginManager = new PluginManager(new ServiceManager()); $this->assertTrue($pluginManager->has('identity')); } public function testIdentityFactoryCanInjectAuthenticationServiceIfInParentServiceManager() { - $services = new ServiceManager(); - $services->setInvokableClass('Zend\Authentication\AuthenticationService', 'Zend\Authentication\AuthenticationService'); - $pluginManager = new PluginManager; - $pluginManager->setServiceLocator($services); + $services = new ServiceManager([ + 'invokables' => [ + AuthenticationService::class => AuthenticationService::class, + ], + ]); + $pluginManager = new PluginManager($services); $identity = $pluginManager->get('identity'); - $expected = $services->get('Zend\Authentication\AuthenticationService'); + $expected = $services->get(AuthenticationService::class); $this->assertSame($expected, $identity->getAuthenticationService()); } public function testCanCreateByFactory() { - $pluginManager = new PluginManager; - $pluginManager->setFactory('samplePlugin', 'ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePluginFactory'); + $pluginManager = new PluginManager(new ServiceManager(), [ + 'factories' => [ + 'samplePlugin' => Plugin\TestAsset\SamplePluginFactory::class, + ] + ]); $plugin = $pluginManager->get('samplePlugin'); - $this->assertInstanceOf('\ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin', $plugin); + $this->assertInstanceOf(SamplePlugin::class, $plugin); } public function testCanCreateByFactoryWithConstrutor() { - $pluginManager = new PluginManager; - $pluginManager->setFactory('samplePlugin', 'ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePluginWithConstructorFactory'); - $plugin = $pluginManager->get('samplePlugin', 'foo'); - $this->assertInstanceOf('\ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePluginWithConstructor', $plugin); - $this->assertEquals($plugin->getBar(), 'foo'); + $pluginManager = new PluginManager(new ServiceManager(), [ + 'factories' => [ + 'samplePlugin' => Plugin\TestAsset\SamplePluginWithConstructorFactory::class, + ], + ]); + $plugin = $pluginManager->get('samplePlugin', ['foo']); + $this->assertInstanceOf(Plugin\TestAsset\SamplePluginWithConstructor::class, $plugin); + $this->assertEquals($plugin->getBar(), ['foo']); } } diff --git a/test/Controller/RestfulControllerTest.php b/test/Controller/RestfulControllerTest.php index f9df8a677..99cc1efb7 100644 --- a/test/Controller/RestfulControllerTest.php +++ b/test/Controller/RestfulControllerTest.php @@ -341,11 +341,6 @@ public function testDispatchInjectsEventIntoController() $this->assertSame($this->event, $event); } - public function testControllerIsLocatorAware() - { - $this->assertInstanceOf('Zend\ServiceManager\ServiceLocatorAwareInterface', $this->controller); - } - public function testControllerIsEventAware() { $this->assertInstanceOf('Zend\Mvc\InjectApplicationEventInterface', $this->controller); diff --git a/test/Controller/TestAsset/ControllerLoaderAbstractFactory.php b/test/Controller/TestAsset/ControllerLoaderAbstractFactory.php index 9dc280d44..9dd3c3a82 100644 --- a/test/Controller/TestAsset/ControllerLoaderAbstractFactory.php +++ b/test/Controller/TestAsset/ControllerLoaderAbstractFactory.php @@ -9,8 +9,8 @@ namespace ZendTest\Mvc\Controller\TestAsset; -use Zend\ServiceManager\AbstractFactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\AbstractFactoryInterface; class ControllerLoaderAbstractFactory implements AbstractFactoryInterface { @@ -18,16 +18,19 @@ class ControllerLoaderAbstractFactory implements AbstractFactoryInterface 'path' => 'ZendTest\Mvc\TestAsset\PathController', ); - public function canCreateServiceWithName(ServiceLocatorInterface $sl, $cName, $rName) + public function canCreateServiceWithName(ContainerInterface $container, $name) { - $classname = $this->classmap[$cName]; + if (! isset($this->classmap[$name])) { + return false; + } + + $classname = $this->classmap[$name]; return class_exists($classname); } - public function createServiceWithName(ServiceLocatorInterface $sl, $cName, $rName) + public function __invoke(ContainerInterface $container, $name, array $options = null) { - $classname = $this->classmap[$cName]; - $controller = new $classname; - return $controller; + $classname = $this->classmap[$name]; + return new $classname; } } diff --git a/test/Controller/TestAsset/UnlocatableControllerLoaderAbstractFactory.php b/test/Controller/TestAsset/UnlocatableControllerLoaderAbstractFactory.php index f31b8da53..5ab69f451 100644 --- a/test/Controller/TestAsset/UnlocatableControllerLoaderAbstractFactory.php +++ b/test/Controller/TestAsset/UnlocatableControllerLoaderAbstractFactory.php @@ -9,17 +9,17 @@ namespace ZendTest\Mvc\Controller\TestAsset; -use Zend\ServiceManager\AbstractFactoryInterface; -use Zend\ServiceManager\ServiceLocatorInterface; +use Interop\Container\ContainerInterface; +use Zend\ServiceManager\Factory\AbstractFactoryInterface; class UnlocatableControllerLoaderAbstractFactory implements AbstractFactoryInterface { - public function canCreateServiceWithName(ServiceLocatorInterface $sl, $cName, $rName) + public function canCreateServiceWithName(ContainerInterface $container, $name) { return false; } - public function createServiceWithName(ServiceLocatorInterface $sl, $cName, $rName) + public function __invoke(ContainerInterface $container, $name, array $options = null) { } } diff --git a/test/DispatchListenerTest.php b/test/DispatchListenerTest.php index d7b84d614..1cb9bb6ba 100644 --- a/test/DispatchListenerTest.php +++ b/test/DispatchListenerTest.php @@ -10,57 +10,20 @@ namespace ZendTest\Mvc; use PHPUnit_Framework_TestCase as TestCase; +use Zend\EventManager\EventManager; +use Zend\Http\Request; +use Zend\Http\Response; use Zend\Mvc\Application; +use Zend\Mvc\Controller\ControllerManager; +use Zend\Mvc\DispatchListener; use Zend\Mvc\MvcEvent; -use Zend\Mvc\Router; -use Zend\Mvc\Service\ServiceManagerConfig; -use Zend\Mvc\Service\ServiceListenerFactory; +use Zend\Mvc\Router\RouteMatch; use Zend\ServiceManager\ServiceManager; -use Zend\Stdlib\ArrayUtils; class DispatchListenerTest extends TestCase { - /** - * @var ServiceManager - */ - protected $serviceManager; - - /** - * @var Application - */ - protected $application; - public function setUp() { - $serviceConfig = ArrayUtils::merge( - $this->readAttribute(new ServiceListenerFactory, 'defaultServiceConfig'), - [ - 'allow_override' => true, - 'invokables' => [ - 'Request' => 'Zend\Http\PhpEnvironment\Request', - 'Response' => 'Zend\Http\PhpEnvironment\Response', - 'ViewManager' => 'ZendTest\Mvc\TestAsset\MockViewManager', - 'SendResponseListener' => 'ZendTest\Mvc\TestAsset\MockSendResponseListener', - 'BootstrapListener' => 'ZendTest\Mvc\TestAsset\StubBootstrapListener', - ], - 'aliases' => [ - 'Router' => 'HttpRouter', - ], - 'services' => [ - 'Config' => [], - 'ApplicationConfig' => [ - 'modules' => [], - 'module_listener_options' => [ - 'config_cache_enabled' => false, - 'cache_dir' => 'data/cache', - 'module_paths' => [], - ], - ], - ], - ] - ); - $this->serviceManager = new ServiceManager(new ServiceManagerConfig($serviceConfig)); - $this->application = $this->serviceManager->get('Application'); } public function setupPathController() @@ -79,45 +42,63 @@ public function setupPathController() $this->application->bootstrap(); } + public function createMvcEvent($controllerMatched) + { + $response = new Response(); + $routeMatch = $this->prophesize(RouteMatch::class); + $routeMatch->getParam('controller', 'not-found')->willReturn('path'); + + $eventManager = new EventManager(); + + $application = $this->prophesize(Application::class); + $application->getEventManager()->willReturn($eventManager); + $application->getResponse()->willReturn($response); + + $event = new MvcEvent(); + $event->setRequest(new Request()); + $event->setResponse($response); + $event->setApplication($application->reveal()); + $event->setRouteMatch($routeMatch->reveal()); + + return $event; + } + public function testControllerLoaderComposedOfAbstractFactory() { - $this->setupPathController(); + $controllerManager = new ControllerManager(new ServiceManager(), ['abstract_factories' => [ + Controller\TestAsset\ControllerLoaderAbstractFactory::class, + ]]); + $listener = new DispatchListener($controllerManager); - $controllerLoader = $this->serviceManager->get('ControllerLoader'); - $controllerLoader->addAbstractFactory('ZendTest\Mvc\Controller\TestAsset\ControllerLoaderAbstractFactory'); + $event = $this->createMvcEvent('path'); $log = []; - $this->application->getEventManager()->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use (&$log) { + $event->getApplication()->getEventManager()->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use (&$log) { $log['error'] = $e->getError(); }); - $this->application->run(); - - $event = $this->application->getMvcEvent(); - $dispatchListener = $this->serviceManager->get('DispatchListener'); - $return = $dispatchListener->onDispatch($event); + $return = $listener->onDispatch($event); - $this->assertEmpty($log); - $this->assertInstanceOf('Zend\Http\PhpEnvironment\Response', $return); + $this->assertEmpty($log, var_export($log, 1)); + $this->assertSame($event->getResponse(), $return); $this->assertSame(200, $return->getStatusCode()); } public function testUnlocatableControllerLoaderComposedOfAbstractFactory() { - $this->setupPathController(); + $controllerManager = new ControllerManager(new ServiceManager(), ['abstract_factories' => [ + Controller\TestAsset\UnlocatableControllerLoaderAbstractFactory::class, + ]]); + $listener = new DispatchListener($controllerManager); - $controllerLoader = $this->serviceManager->get('ControllerLoader'); - $controllerLoader->addAbstractFactory('ZendTest\Mvc\Controller\TestAsset\UnlocatableControllerLoaderAbstractFactory'); + $event = $this->createMvcEvent('path'); $log = []; - $this->application->getEventManager()->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use (&$log) { + $event->getApplication()->getEventManager()->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($e) use (&$log) { $log['error'] = $e->getError(); }); - $this->application->run(); - $event = $this->application->getMvcEvent(); - $dispatchListener = $this->serviceManager->get('DispatchListener'); - $return = $dispatchListener->onDispatch($event); + $return = $listener->onDispatch($event); $this->assertArrayHasKey('error', $log); $this->assertSame('error-controller-not-found', $log['error']); diff --git a/test/Router/Http/ChainTest.php b/test/Router/Http/ChainTest.php index 3d161d358..ce2f5168a 100644 --- a/test/Router/Http/ChainTest.php +++ b/test/Router/Http/ChainTest.php @@ -13,13 +13,14 @@ use Zend\Http\Request as Request; use Zend\Mvc\Router\RoutePluginManager; use Zend\Mvc\Router\Http\Chain; +use Zend\ServiceManager\ServiceManager; use ZendTest\Mvc\Router\FactoryTester; class ChainTest extends TestCase { public static function getRoute() { - $routePlugins = new RoutePluginManager(); + $routePlugins = new RoutePluginManager(new ServiceManager()); return new Chain( [ @@ -51,7 +52,7 @@ public static function getRoute() public static function getRouteWithOptionalParam() { - $routePlugins = new RoutePluginManager(); + $routePlugins = new RoutePluginManager(new ServiceManager()); return new Chain( [ @@ -192,7 +193,7 @@ public function testFactory() ], [ 'routes' => [], - 'route_plugins' => new RoutePluginManager(), + 'route_plugins' => new RoutePluginManager(new ServiceManager()), ] ); } diff --git a/test/Router/Http/PartTest.php b/test/Router/Http/PartTest.php index b4bd0be43..6aeaf7ba7 100644 --- a/test/Router/Http/PartTest.php +++ b/test/Router/Http/PartTest.php @@ -13,18 +13,37 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\Http\Request as Request; use Zend\Mvc\Router\RoutePluginManager; +use Zend\Mvc\Router\Http\Literal; use Zend\Mvc\Router\Http\Part; +use Zend\Mvc\Router\Http\Segment; +use Zend\Mvc\Router\Http\Wildcard; +use Zend\ServiceManager\ServiceManager; use Zend\Stdlib\Parameters; use Zend\Stdlib\Request as BaseRequest; use ZendTest\Mvc\Router\FactoryTester; class PartTest extends TestCase { - public static function getRoute() + public static function getRoutePlugins() { - $routePlugins = new RoutePluginManager(); - $routePlugins->setInvokableClass('part', 'Zend\Mvc\Router\Http\Part'); + return new RoutePluginManager(new ServiceManager(), [ + 'aliases' => [ + 'Literal' => 'literal', + 'Part' => 'part', + 'Segment' => 'segment', + 'Wildcard' => 'wildcard', + ], + 'invokables' => [ + 'literal' => Literal::class, + 'part' => Part::class, + 'segment' => Segment::class, + 'wildcard' => Wildcard::class, + ], + ]); + } + public static function getRoute() + { return new Part( [ 'type' => 'Zend\Mvc\Router\Http\Literal', @@ -36,7 +55,7 @@ public static function getRoute() ] ], true, - $routePlugins, + self::getRoutePlugins(), [ 'bar' => [ 'type' => 'Zend\Mvc\Router\Http\Literal', @@ -97,9 +116,6 @@ public static function getRoute() public static function getRouteAlternative() { - $routePlugins = new RoutePluginManager(); - $routePlugins->setInvokableClass('part', 'Zend\Mvc\Router\Http\Part'); - return new Part( [ 'type' => 'Zend\Mvc\Router\Http\Segment', @@ -112,7 +128,7 @@ public static function getRouteAlternative() ] ], true, - $routePlugins, + self::getRoutePlugins(), [ 'wildcard' => [ 'type' => 'Zend\Mvc\Router\Http\Wildcard', @@ -315,7 +331,7 @@ public function testBaseRouteMayNotBePartRoute() { $this->setExpectedException('Zend\Mvc\Router\Exception\InvalidArgumentException', 'Base route may not be a part route'); - $route = new Part(self::getRoute(), true, new RoutePluginManager()); + $route = new Part(self::getRoute(), true, new RoutePluginManager(new ServiceManager())); } public function testNoMatchWithoutUriMethod() @@ -345,7 +361,7 @@ public function testFactory() ], [ 'route' => new \Zend\Mvc\Router\Http\Literal('/foo'), - 'route_plugins' => new RoutePluginManager() + 'route_plugins' => self::getRoutePlugins(), ] ); } @@ -378,7 +394,7 @@ public function testFactoryShouldAcceptTraversableChildRoutes() ], ], ], - 'route_plugins' => new RoutePluginManager(), + 'route_plugins' => self::getRoutePlugins(), 'may_terminate' => true, 'child_routes' => $children, ]; @@ -403,7 +419,7 @@ public function testPartRouteMarkedAsMayTerminateCanMatchWhenQueryStringPresent( ], ], ], - 'route_plugins' => new RoutePluginManager(), + 'route_plugins' => self::getRoutePlugins(), 'may_terminate' => true, 'child_routes' => [ 'child' => [ @@ -446,7 +462,7 @@ public function testPartRouteMarkedAsMayTerminateButWithQueryRouteChildWillMatch ], ], ], - 'route_plugins' => new RoutePluginManager(), + 'route_plugins' => self::getRoutePlugins(), 'may_terminate' => true, /* 'child_routes' => array( diff --git a/test/Router/Http/SegmentTest.php b/test/Router/Http/SegmentTest.php index 4c09e8d34..6ccec5419 100644 --- a/test/Router/Http/SegmentTest.php +++ b/test/Router/Http/SegmentTest.php @@ -21,21 +21,6 @@ class SegmentTest extends TestCase { public function routeProvider() { - $translator = new Translator(); - $translator->setLocale('en-US'); - $enLoader = $this->getMock('Zend\I18n\Translator\Loader\FileLoaderInterface'); - $deLoader = $this->getMock('Zend\I18n\Translator\Loader\FileLoaderInterface'); - $domainLoader = $this->getMock('Zend\I18n\Translator\Loader\FileLoaderInterface'); - $enLoader->expects($this->any())->method('load')->willReturn(new TextDomain(['fw' => 'framework'])); - $deLoader->expects($this->any())->method('load')->willReturn(new TextDomain(['fw' => 'baukasten'])); - $domainLoader->expects($this->any())->method('load')->willReturn(new TextDomain(['fw' => 'fw-alternative'])); - $translator->getPluginManager()->setService('test-en', $enLoader); - $translator->getPluginManager()->setService('test-de', $deLoader); - $translator->getPluginManager()->setService('test-domain', $domainLoader); - $translator->addTranslationFile('test-en', null, 'default', 'en-US'); - $translator->addTranslationFile('test-de', null, 'default', 'de-DE'); - $translator->addTranslationFile('test-domain', null, 'alternative', 'en-US'); - return [ 'simple-match' => [ new Segment('/:foo'), @@ -181,6 +166,33 @@ public function routeProvider() null, ['bar' => 'bar', 'baz' => 'baz'] ], + ]; + } + + public function l10nRouteProvider() + { + $this->markTestIncomplete( + 'Translation tests need to be updated once zend-i18n is updated for zend-servicemanager v3' + ); + + // @codingStandardsIgnoreStart + $translator = new Translator(); + $translator->setLocale('en-US'); + $enLoader = $this->getMock('Zend\I18n\Translator\Loader\FileLoaderInterface'); + $deLoader = $this->getMock('Zend\I18n\Translator\Loader\FileLoaderInterface'); + $domainLoader = $this->getMock('Zend\I18n\Translator\Loader\FileLoaderInterface'); + $enLoader->expects($this->any())->method('load')->willReturn(new TextDomain(['fw' => 'framework'])); + $deLoader->expects($this->any())->method('load')->willReturn(new TextDomain(['fw' => 'baukasten'])); + $domainLoader->expects($this->any())->method('load')->willReturn(new TextDomain(['fw' => 'fw-alternative'])); + $translator->getPluginManager()->setService('test-en', $enLoader); + $translator->getPluginManager()->setService('test-de', $deLoader); + $translator->getPluginManager()->setService('test-domain', $domainLoader); + $translator->addTranslationFile('test-en', null, 'default', 'en-US'); + $translator->addTranslationFile('test-de', null, 'default', 'de-DE'); + $translator->addTranslationFile('test-domain', null, 'alternative', 'en-US'); + // @codingStandardsIgnoreEnd + + return [ 'translate-with-default-locale' => [ new Segment('/{fw}', [], []), '/framework', @@ -291,6 +303,59 @@ public function testAssembling(Segment $route, $path, $offset, array $params = n } } + /** + * @dataProvider l10nRouteProvider + * @param Segment $route + * @param string $path + * @param integer $offset + * @param array $params + * @param array $options + */ + public function testMatchingWithL10n(Segment $route, $path, $offset, array $params = null, array $options = []) + { + $request = new Request(); + $request->setUri('http://example.com' . $path); + $match = $route->match($request, $offset, $options); + + if ($params === null) { + $this->assertNull($match); + } else { + $this->assertInstanceOf('Zend\Mvc\Router\Http\RouteMatch', $match); + + if ($offset === null) { + $this->assertEquals(strlen($path), $match->getLength()); + } + + foreach ($params as $key => $value) { + $this->assertEquals($value, $match->getParam($key)); + } + } + } + + /** + * @dataProvider l10nRouteProvider + * @param Segment $route + * @param string $path + * @param integer $offset + * @param array $params + * @param array $options + */ + public function testAssemblingWithL10n(Segment $route, $path, $offset, array $params = null, array $options = []) + { + if ($params === null) { + // Data which will not match are not tested for assembling. + return; + } + + $result = $route->assemble($params, $options); + + if ($offset !== null) { + $this->assertEquals($offset, strpos($path, $result, $offset)); + } else { + $this->assertEquals($path, $result); + } + } + /** * @dataProvider parseExceptionsProvider * @param string $route diff --git a/test/Router/Http/TranslatorAwareTreeRouteStackTest.php b/test/Router/Http/TranslatorAwareTreeRouteStackTest.php index f3b2bae08..c1f98542c 100644 --- a/test/Router/Http/TranslatorAwareTreeRouteStackTest.php +++ b/test/Router/Http/TranslatorAwareTreeRouteStackTest.php @@ -34,6 +34,8 @@ class TranslatorAwareTreeRouteStackTest extends TestCase public function setUp() { + $this->markTestIncomplete('Re-enable once zend-i18n is updated to zend-servicemanager v3'); + $this->testFilesDir = __DIR__ . '/_files'; $this->translator = new Translator(); @@ -142,7 +144,7 @@ public function testAssembleRouteWithParameterLocale() ); $this->assertEquals('/de/hauptseite', $stack->assemble(['locale' => 'de'], ['name' => 'foo/index'])); - $this->assertEquals('/en/homepage', $stack->assemble(['locale' => 'en'], ['name' => 'foo/index'])); + $this->assertEquals('/en/homepage', $stack->assemble(['locale' => 'en'], ['name' => 'foo/index'])); } public function testMatchRouteWithParameterLocale() diff --git a/test/Router/RoutePluginManagerTest.php b/test/Router/RoutePluginManagerTest.php index c763a58b5..d9dff5d95 100644 --- a/test/Router/RoutePluginManagerTest.php +++ b/test/Router/RoutePluginManagerTest.php @@ -9,105 +9,26 @@ namespace ZendTest\Mvc\Router; -use Zend\Di\Di; -use Zend\Mvc\Router\RoutePluginManager; -use Zend\ServiceManager\Di\DiAbstractServiceFactory; use PHPUnit_Framework_TestCase as TestCase; +use Zend\Mvc\Router\RoutePluginManager; +use Zend\ServiceManager\ServiceManager; -/** - * @group Zend_Router - */ class RoutePluginManagerTest extends TestCase { public function testLoadNonExistentRoute() { - $routes = new RoutePluginManager(); + $routes = new RoutePluginManager(new ServiceManager()); $this->setExpectedException('Zend\ServiceManager\Exception\ServiceNotFoundException'); $routes->get('foo'); } public function testCanLoadAnyRoute() { - $routes = new RoutePluginManager(); - $routes->setInvokableClass('DummyRoute', 'ZendTest\Mvc\Router\TestAsset\DummyRoute'); + $routes = new RoutePluginManager(new ServiceManager(), ['invokables' => [ + 'DummyRoute' => 'ZendTest\Mvc\Router\TestAsset\DummyRoute', + ]]); $route = $routes->get('DummyRoute'); $this->assertInstanceOf('ZendTest\Mvc\Router\TestAsset\DummyRoute', $route); } - - public function shippedRoutes() - { - return [ - 'hostname' => ['Zend\Mvc\Router\Http\Hostname', ['route' => 'example.com']], - 'literal' => ['Zend\Mvc\Router\Http\Literal', ['route' => '/example']], - 'regex' => ['Zend\Mvc\Router\Http\Regex', ['regex' => '[a-z]+', 'spec' => '%s']], - 'scheme' => ['Zend\Mvc\Router\Http\Scheme', ['scheme' => 'http']], - 'segment' => ['Zend\Mvc\Router\Http\Segment', ['route' => '/:segment']], - 'wildcard' => ['Zend\Mvc\Router\Http\Wildcard', []], - //'query' => array('Zend\Mvc\Router\Http\Query', array()), - 'method' => ['Zend\Mvc\Router\Http\Method', ['verb' => 'GET']], - ]; - } - - /** - * @dataProvider shippedRoutes - */ - public function testDoesNotInvokeDiForShippedRoutes($routeName, $options) - { - // Setup route plugin manager - $routes = new RoutePluginManager(); - foreach ($this->shippedRoutes() as $name => $info) { - $routes->setInvokableClass($name, $info[0]); - } - - // Add DI abstract factory - $di = new Di; - $diAbstractFactory = new DiAbstractServiceFactory($di, DiAbstractServiceFactory::USE_SL_BEFORE_DI); - $routes->addAbstractFactory($diAbstractFactory); - - $this->assertTrue($routes->has($routeName)); - - try { - $route = $routes->get($routeName, $options); - $this->assertInstanceOf($routeName, $route); - } catch (\Exception $e) { - $messages = []; - do { - $messages[] = $e->getMessage() . "\n" . $e->getTraceAsString(); - } while ($e = $e->getPrevious()); - $this->fail(implode("\n\n", $messages)); - } - } - - /** - * @dataProvider shippedRoutes - */ - public function testDoesNotInvokeDiForShippedRoutesUsingShortName($routeName, $options) - { - // Setup route plugin manager - $routes = new RoutePluginManager(); - foreach ($this->shippedRoutes() as $name => $info) { - $routes->setInvokableClass($name, $info[0]); - } - - // Add DI abstract factory - $di = new Di; - $diAbstractFactory = new DiAbstractServiceFactory($di, DiAbstractServiceFactory::USE_SL_BEFORE_DI); - $routes->addAbstractFactory($diAbstractFactory); - - $shortName = substr($routeName, strrpos($routeName, '\\') + 1); - - $this->assertTrue($routes->has($shortName)); - - try { - $route = $routes->get($shortName, $options); - $this->assertInstanceOf($routeName, $route); - } catch (\Exception $e) { - $messages = []; - do { - $messages[] = $e->getMessage() . "\n" . $e->getTraceAsString(); - } while ($e = $e->getPrevious()); - $this->fail(implode("\n\n", $messages)); - } - } } diff --git a/test/Router/SimpleRouteStackTest.php b/test/Router/SimpleRouteStackTest.php index b0e55d4be..f62d8b7d4 100644 --- a/test/Router/SimpleRouteStackTest.php +++ b/test/Router/SimpleRouteStackTest.php @@ -14,12 +14,13 @@ use Zend\Stdlib\Request; use Zend\Mvc\Router\RoutePluginManager; use Zend\Mvc\Router\SimpleRouteStack; +use Zend\ServiceManager\ServiceManager; class SimpleRouteStackTest extends TestCase { public function testSetRoutePluginManager() { - $routes = new RoutePluginManager(); + $routes = new RoutePluginManager(new ServiceManager()); $stack = new SimpleRouteStack(); $stack->setRoutePluginManager($routes); @@ -239,7 +240,7 @@ public function testFactory() 'Zend\Mvc\Router\SimpleRouteStack', [], [ - 'route_plugins' => new RoutePluginManager(), + 'route_plugins' => new RoutePluginManager(new ServiceManager()), 'routes' => [], 'default_params' => [] ] diff --git a/test/Service/ConsoleAdapterFactoryTest.php b/test/Service/ConsoleAdapterFactoryTest.php new file mode 100644 index 000000000..e2cea142a --- /dev/null +++ b/test/Service/ConsoleAdapterFactoryTest.php @@ -0,0 +1,105 @@ +setConsoleEnvironment(true); + } + + public function testFactoryReturnsAnonymousObjectIfNotConsoleEnvironment() + { + $this->setConsoleEnvironment(false); + $factory = new ConsoleAdapterFactory(); + $result = $factory($this->createContainer(), 'ConsoleAdapter'); + $this->assertInstanceOf(stdClass::class, $result); + } + + public function testFactoryCanUseAdapterFromConfiguration() + { + $this->setConsoleEnvironment(true); + $adapter = $this->prophesize(AdapterInterface::class); + + $container = $this->prophesize(ContainerInterface::class); + $container->get('config')->willReturn([ + 'console' => [ + 'adapter' => 'TestAdapter', + ], + ]); + $container->get('TestAdapter')->will(function () use ($adapter) { + return $adapter->reveal(); + }); + + $factory = new ConsoleAdapterFactory(); + $result = $factory($container->reveal(), 'ConsoleAdapter'); + $this->assertSame($adapter->reveal(), $result); + } + + public function testFactoryReturnsAnonymousObjectIfConfiguredAdapterIsInvalid() + { + $this->setConsoleEnvironment(true); + $container = $this->prophesize(ContainerInterface::class); + $container->get('config')->willReturn([ + 'console' => [ + 'adapter' => 'TestAdapter', + ], + ]); + $container->get('TestAdapter')->willReturn([]); + + $factory = new ConsoleAdapterFactory(); + $result = $factory($container->reveal(), 'ConsoleAdapter'); + $this->assertInstanceOf(stdClass::class, $result); + } + + public function testFactoryWillDetectBestAdapterWhenNoneConfigured() + { + $this->setConsoleEnvironment(true); + + $container = $this->prophesize(ContainerInterface::class); + $container->get('config')->willReturn([]); + + $factory = new ConsoleAdapterFactory(); + $result = $factory($container->reveal(), 'ConsoleAdapter'); + $this->assertInstanceOf(AdapterInterface::class, $result); + } + + public function testFactoryWillInjectCharsetIfConfigured() + { + $this->setConsoleEnvironment(true); + + $charset = $this->prophesize(CharsetInterface::class); + + $container = $this->prophesize(ContainerInterface::class); + $container->get('config')->willReturn([ + 'console' => [ + 'charset' => 'CustomCharset', + ], + ]); + $container->get('CustomCharset')->will(function () use ($charset) { + return $charset->reveal(); + }); + + $factory = new ConsoleAdapterFactory(); + $result = $factory($container->reveal(), 'ConsoleAdapter'); + $this->assertInstanceOf(AdapterInterface::class, $result); + $this->assertSame($charset->reveal(), $result->getCharset()); + } +} diff --git a/test/Service/ConsoleViewManagerFactoryTest.php b/test/Service/ConsoleViewManagerFactoryTest.php new file mode 100644 index 000000000..80307f655 --- /dev/null +++ b/test/Service/ConsoleViewManagerFactoryTest.php @@ -0,0 +1,41 @@ +setConsoleEnvironment(true); + } + + public function testRaisesExceptionWhenNotInConsoleEnvironment() + { + $this->setConsoleEnvironment(false); + $factory = new ConsoleViewManagerFactory(); + $this->setExpectedException(ServiceNotCreatedException::class); + $factory($this->createContainer(), 'ConsoleViewManager'); + } + + public function testReturnsConsoleViewManagerWhenInConsoleEnvironment() + { + $this->setConsoleEnvironment(true); + $factory = new ConsoleViewManagerFactory(); + $result = $factory($this->createContainer(), 'ConsoleViewManager'); + $this->assertInstanceOf(ViewManager::class, $result); + } +} diff --git a/test/Service/ControllerLoaderFactoryTest.php b/test/Service/ControllerLoaderFactoryTest.php deleted file mode 100644 index d7ae43002..000000000 --- a/test/Service/ControllerLoaderFactoryTest.php +++ /dev/null @@ -1,183 +0,0 @@ - []]); - $this->services = new ServiceManager(); - $this->services->setService('Zend\ServiceManager\ServiceLocatorInterface', $this->services); - $this->services->setFactory('ControllerLoader', $loaderFactory); - $this->services->setService('Config', $config); - $this->services->setFactory('ControllerPluginManager', new ControllerPluginManagerFactory()); - $this->services->setFactory('Di', new DiFactory()); - $this->services->setFactory('DiStrictAbstractServiceFactory', new DiStrictAbstractServiceFactoryFactory()); - $this->services->setFactory('DiAbstractServiceFactory', new DiAbstractServiceFactoryFactory()); - $this->services->setFactory('DiServiceInitializer', new DiServiceInitializerFactory()); - $this->services->setFactory('EventManager', new EventManagerFactory()); - $this->services->setInvokableClass('SharedEventManager', 'Zend\EventManager\SharedEventManager'); - } - - public function testCannotLoadInvalidDispatchable() - { - $this->loader = $this->services->get('ControllerLoader'); - - // Ensure the class exists and can be autoloaded - $this->assertTrue(class_exists('ZendTest\Mvc\Service\TestAsset\InvalidDispatchableClass')); - - try { - $this->loader->get('ZendTest\Mvc\Service\TestAsset\InvalidDispatchableClass'); - $this->fail('Retrieving the invalid dispatchable should fail'); - } catch (\Exception $e) { - do { - $this->assertNotContains('Should not instantiate this', $e->getMessage()); - } while ($e = $e->getPrevious()); - } - } - - public function testCannotLoadControllerFromPeer() - { - $this->loader = $this->services->get('ControllerLoader'); - $this->services->setService('foo', $this); - - $this->setExpectedException('Zend\ServiceManager\Exception\ExceptionInterface'); - $this->loader->get('foo'); - } - - public function testControllerLoadedCanBeInjectedWithValuesFromPeer() - { - $this->loader = $this->services->get('ControllerLoader'); - $config = [ - 'invokables' => [ - 'ZendTest\Dispatchable' => 'ZendTest\Mvc\Service\TestAsset\Dispatchable', - ], - ]; - $config = new Config($config); - $config->configureServiceManager($this->loader); - - $controller = $this->loader->get('ZendTest\Dispatchable'); - $this->assertInstanceOf('ZendTest\Mvc\Service\TestAsset\Dispatchable', $controller); - $this->assertSame($this->services, $controller->getServiceLocator()); - $this->assertSame($this->services->get('EventManager'), $controller->getEventManager()); - $this->assertSame($this->services->get('ControllerPluginManager'), $controller->getPluginManager()); - } - - public function testWillInstantiateControllersFromDiAbstractFactoryWhenWhitelisted() - { - $config = new ArrayObject([ - 'di' => [ - 'instance' => [ - 'alias' => [ - 'my-controller' => 'stdClass', - ], - ], - 'allowed_controllers' => [ - 'my-controller', - ], - ], - ]); - $this->services->setAllowOverride(true); - $this->services->setService('Config', $config); - $this->loader = $this->services->get('ControllerLoader'); - - $this->assertTrue($this->loader->has('my-controller')); - // invalid controller exception (because we're getting an \stdClass after all) - $this->setExpectedException('Zend\Mvc\Exception\InvalidControllerException'); - $this->loader->get('my-controller'); - } - - public function testWillNotInstantiateControllersFromDiAbstractFactoryWhenNotWhitelisted() - { - $config = new ArrayObject([ - 'di' => [ - 'instance' => [ - 'alias' => [ - 'evil-controller' => 'stdClass', - ], - ], - 'allowed_controllers' => [ - 'my-controller', - ], - ], - ]); - $this->services->setAllowOverride(true); - $this->services->setService('Config', $config); - $this->loader = $this->services->get('ControllerLoader'); - $this->setExpectedException('Zend\ServiceManager\Exception\ServiceNotFoundException'); - $this->loader->get('evil-controller'); - } - - public function testWillFetchDiDependenciesFromControllerLoaderServiceManager() - { - $controllerName = __NAMESPACE__ . '\TestAsset\ControllerWithDependencies'; - // rewriting since controller loader does not have the correct config, but is already fetched - $config = new ArrayObject([ - 'di' => [ - 'instance' => [ - $controllerName => [ - 'parameters' => [ - 'injected' => 'stdClass', - ], - ], - ], - 'allowed_controllers' => [ - $controllerName, - ], - ], - ]); - $this->services->setAllowOverride(true); - $this->services->setService('Config', $config); - $this->loader = $this->services->get('ControllerLoader'); - - $testService = new \stdClass(); - $this->services->setService('stdClass', $testService); - // invalid controller exception (because we're not getting a \Zend\Stdlib\DispatchableInterface after all) - $controller = $this->loader->get($controllerName); - $this->assertSame($testService, $controller->injectedValue); - } - - public function testCallPluginWithControllerPluginManager() - { - $controllerpluginManager = $this->services->get('ControllerPluginManager'); - $controllerpluginManager->setInvokableClass('samplePlugin', 'ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin'); - - $controller = new \ZendTest\Mvc\Controller\TestAsset\SampleController; - $controllerpluginManager->setController($controller); - - $plugin = $controllerpluginManager->get('samplePlugin'); - $this->assertEquals($controller, $plugin->getController()); - } -} diff --git a/test/Service/ControllerManagerFactoryTest.php b/test/Service/ControllerManagerFactoryTest.php new file mode 100644 index 000000000..2253ad7f0 --- /dev/null +++ b/test/Service/ControllerManagerFactoryTest.php @@ -0,0 +1,111 @@ +defaultServiceConfig = [ + 'invokables' => [ + 'SharedEventManager' => SharedEventManager::class, + ], + 'factories' => [ + 'ControllerManager' => $loaderFactory, + 'ControllerPluginManager' => ControllerPluginManagerFactory::class, + 'EventManager' => EventManagerFactory::class, + ], + 'services' => [ + 'config' => [], + ], + ]; + $this->services = new ServiceManager($this->defaultServiceConfig); + } + + public function testCannotLoadInvalidDispatchable() + { + $loader = $this->services->get('ControllerManager'); + + // Ensure the class exists and can be autoloaded + $this->assertTrue(class_exists('ZendTest\Mvc\Service\TestAsset\InvalidDispatchableClass')); + + try { + $loader->get('ZendTest\Mvc\Service\TestAsset\InvalidDispatchableClass'); + $this->fail('Retrieving the invalid dispatchable should fail'); + } catch (\Exception $e) { + do { + $this->assertNotContains('Should not instantiate this', $e->getMessage()); + } while ($e = $e->getPrevious()); + } + } + + public function testCannotLoadControllerFromPeer() + { + $services = new ServiceManager(array_merge_recursive($this->defaultServiceConfig, ['services' => [ + 'foo' => $this, + ]])); + $loader = $services->get('ControllerManager'); + + $this->setExpectedException('Zend\ServiceManager\Exception\ExceptionInterface'); + $loader->get('foo'); + } + + public function testControllerLoadedCanBeInjectedWithValuesFromPeer() + { + $loader = $this->services->get('ControllerManager'); + $loader = $loader->withConfig(['invokables' => [ + 'ZendTest\Dispatchable' => TestAsset\Dispatchable::class, + ]]); + + $controller = $loader->get('ZendTest\Dispatchable'); + $this->assertInstanceOf(TestAsset\Dispatchable::class, $controller); + $this->assertSame($this->services->get('EventManager'), $controller->getEventManager()); + $this->assertSame($this->services->get('ControllerPluginManager'), $controller->getPluginManager()); + } + + public function testCallPluginWithControllerPluginManager() + { + $controllerPluginManager = $this->services->get('ControllerPluginManager'); + $controllerPluginManager = $controllerPluginManager->withConfig([ + 'invokables' => [ + 'samplePlugin' => 'ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin', + ], + ]); + + $controller = new \ZendTest\Mvc\Controller\TestAsset\SampleController; + $controllerPluginManager->setController($controller); + + $services = $this->services->withConfig(['services' => [ + 'ControllerPluginManager' => $controllerPluginManager, + ]]); + + $plugin = $controllerPluginManager->get('samplePlugin'); + $this->assertEquals($controller, $plugin->getController()); + } +} diff --git a/test/Service/DiFactoryTest.php b/test/Service/DiFactoryTest.php deleted file mode 100644 index 88a0b48b8..000000000 --- a/test/Service/DiFactoryTest.php +++ /dev/null @@ -1,26 +0,0 @@ -setService('Config', ['di' => ['']]); - $serviceManager->setFactory('Di', new DiFactory()); - - $di = $serviceManager->get('Di'); - $this->assertInstanceOf('Zend\Di\Di', $di); - } -} diff --git a/test/Service/DiStrictAbstractServiceFactoryTest.php b/test/Service/DiStrictAbstractServiceFactoryTest.php deleted file mode 100644 index 047cce53f..000000000 --- a/test/Service/DiStrictAbstractServiceFactoryTest.php +++ /dev/null @@ -1,64 +0,0 @@ -getMock('Zend\Di\Di')); - $instance->setAllowedServiceNames(['first-service', 'second-service']); - $allowedServices = $instance->getAllowedServiceNames(); - $this->assertCount(2, $allowedServices); - $this->assertContains('first-service', $allowedServices); - $this->assertContains('second-service', $allowedServices); - } - - public function testWillOnlyCreateServiceInWhitelist() - { - $instance = new DiStrictAbstractServiceFactory($this->getMock('Zend\Di\Di')); - $instance->setAllowedServiceNames(['a-whitelisted-service-name']); - $im = $instance->instanceManager(); - $im->addSharedInstance(new \stdClass(), 'a-whitelisted-service-name'); - $locator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); - - $this->assertTrue($instance->canCreateServiceWithName($locator, 'a-whitelisted-service-name', 'a-whitelisted-service-name')); - $this->assertInstanceOf('stdClass', $instance->createServiceWithName($locator, 'a-whitelisted-service-name', 'a-whitelisted-service-name')); - - $this->assertFalse($instance->canCreateServiceWithName($locator, 'not-whitelisted', 'not-whitelisted')); - $this->setExpectedException('Zend\ServiceManager\Exception\InvalidServiceNameException'); - $instance->createServiceWithName($locator, 'not-whitelisted', 'not-whitelisted'); - } - - public function testWillFetchDependenciesFromServiceManagerBeforeDi() - { - $controllerName = __NAMESPACE__ . '\TestAsset\ControllerWithDependencies'; - $config = new Config([ - 'instance' => [ - $controllerName => ['parameters' => ['injected' => 'stdClass']], - ], - ]); - $locator = new ServiceManager(); - $testService = new \stdClass(); - $locator->setService('stdClass', $testService); - - $di = new Di; - $config->configure($di); - $instance = new DiStrictAbstractServiceFactory($di, DiStrictAbstractServiceFactory::USE_SL_BEFORE_DI); - $instance->setAllowedServiceNames([$controllerName]); - $service = $instance->createServiceWithName($locator, $controllerName, $controllerName); - $this->assertSame($testService, $service->injectedValue); - } -} diff --git a/test/Service/FactoryEnvironmentTrait.php b/test/Service/FactoryEnvironmentTrait.php new file mode 100644 index 000000000..0808284cf --- /dev/null +++ b/test/Service/FactoryEnvironmentTrait.php @@ -0,0 +1,29 @@ +setAccessible(true); + $r->setValue((bool) $isConsole); + } + + private function createContainer() + { + return $this->prophesize(ContainerInterface::class)->reveal(); + } +} diff --git a/test/Service/FormAnnotationBuilderFactoryTest.php b/test/Service/FormAnnotationBuilderFactoryTest.php index 9527097c4..eeb3f1e96 100644 --- a/test/Service/FormAnnotationBuilderFactoryTest.php +++ b/test/Service/FormAnnotationBuilderFactoryTest.php @@ -15,13 +15,18 @@ class FormAnnotationBuilderFactoryTest extends TestCase { + public function setUp() + { + $this->markTestIncomplete('Re-enable once zend-form is migrated to zend-servicemanager v3'); + } + public function testCreateService() { $mockElementManager = $this->getMock('Zend\Form\FormElementManager'); $serviceLocator = new ServiceManager(); $serviceLocator->setService('FormElementManager', $mockElementManager); - $serviceLocator->setService('Config', []); + $serviceLocator->setService('config', []); $sut = new FormAnnotationBuilderFactory(); @@ -35,7 +40,7 @@ public function testCreateServiceSetsPreserveDefinedOrder() $serviceLocator = new ServiceManager(); $serviceLocator->setService('FormElementManager', $mockElementManager); $config = ['form_annotation_builder' => ['preserve_defined_order' => true]]; - $serviceLocator->setService('Config', $config); + $serviceLocator->setService('config', $config); $sut = new FormAnnotationBuilderFactory(); diff --git a/test/Service/FormElementManagerFactoryTest.php b/test/Service/FormElementManagerFactoryTest.php index 6577e72bb..bf25c230d 100644 --- a/test/Service/FormElementManagerFactoryTest.php +++ b/test/Service/FormElementManagerFactoryTest.php @@ -9,12 +9,8 @@ namespace ZendTest\Mvc\Service; -use ArrayObject; use PHPUnit_Framework_TestCase as TestCase; use Zend\Mvc\Service\FormElementManagerFactory; -use Zend\Mvc\Service\DiFactory; -use Zend\Mvc\Service\DiAbstractServiceFactoryFactory; -use Zend\Mvc\Service\DiServiceInitializerFactory; use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; use Zend\Form\FormElementManager; @@ -33,15 +29,17 @@ class FormElementManagerFactoryTest extends TestCase public function setUp() { + $this->markTestIncomplete('Re-enable once zend-form is migrated to zend-servicemanager v3'); + $formElementManagerFactory = new FormElementManagerFactory(); - $config = new ArrayObject(['di' => []]); - $this->services = new ServiceManager(); - $this->services->setService('Zend\ServiceManager\ServiceLocatorInterface', $this->services); - $this->services->setFactory('FormElementManager', $formElementManagerFactory); - $this->services->setService('Config', $config); - $this->services->setFactory('Di', new DiFactory()); - $this->services->setFactory('DiAbstractServiceFactory', new DiAbstractServiceFactoryFactory()); - $this->services->setFactory('DiServiceInitializer', new DiServiceInitializerFactory()); + $this->services = new ServiceManager([ + 'factories' => [ + 'FormElementManager' => $formElementManagerFactory, + ], + 'services' => [ + 'config' => [], + ], + ]); } public function testWillGetFormElementManager() @@ -56,16 +54,4 @@ public function testWillInstantiateFormFromInvokable() $form = $formElementManager->get('form'); $this->assertInstanceof('Zend\Form\Form', $form); } - - public function testWillInstantiateFormFromDiAbstractFactory() - { - //without DiAbstractFactory - $standaloneFormElementManager = new FormElementManager(); - $this->assertFalse($standaloneFormElementManager->has('ZendTest\Mvc\Service\TestAsset\CustomForm')); - //with DiAbstractFactory - $formElementManager = $this->services->get('FormElementManager'); - $this->assertTrue($formElementManager->has('ZendTest\Mvc\Service\TestAsset\CustomForm')); - $form = $formElementManager->get('ZendTest\Mvc\Service\TestAsset\CustomForm'); - $this->assertInstanceof('ZendTest\Mvc\Service\TestAsset\CustomForm', $form); - } } diff --git a/test/Service/HttpMethodListenerFactoryTest.php b/test/Service/HttpMethodListenerFactoryTest.php index 0653f3933..67daf78e5 100644 --- a/test/Service/HttpMethodListenerFactoryTest.php +++ b/test/Service/HttpMethodListenerFactoryTest.php @@ -32,7 +32,7 @@ public function setUp() public function testCreateWithDefaults() { $factory = new HttpMethodListenerFactory(); - $listener = $factory->createService($this->serviceLocator); + $listener = $factory($this->serviceLocator, 'HttpMethodListener'); $this->assertTrue($listener->isEnabled()); $this->assertNotEmpty($listener->getAllowedMethods()); } @@ -50,7 +50,7 @@ public function testCreateWithConfig() ->willReturn($config); $factory = new HttpMethodListenerFactory(); - $listener = $factory->createService($this->serviceLocator); + $listener = $factory($this->serviceLocator, 'HttpMethodListener'); $listenerConfig = $config['http_methods_listener']; diff --git a/test/Service/InjectTemplateListenerFactoryTest.php b/test/Service/InjectTemplateListenerFactoryTest.php index a89fccaab..6b8aa560e 100644 --- a/test/Service/InjectTemplateListenerFactoryTest.php +++ b/test/Service/InjectTemplateListenerFactoryTest.php @@ -62,10 +62,10 @@ private function buildInjectTemplateListenerWithConfig($config) /* @var $serviceLocator \Zend\ServiceManager\ServiceLocatorInterface|\PHPUnit_Framework_MockObject_MockObject */ $serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); - $serviceLocator->expects($this->any())->method('get')->with('Config')->will($this->returnValue($config)); + $serviceLocator->expects($this->any())->method('get')->with('config')->will($this->returnValue($config)); $factory = new InjectTemplateListenerFactory(); - $listener = $factory->createService($serviceLocator); + $listener = $factory($serviceLocator, 'InjectTemplateListener'); $this->assertInstanceOf('Zend\Mvc\View\Http\InjectTemplateListener', $listener); diff --git a/test/Service/RequestFactoryTest.php b/test/Service/RequestFactoryTest.php new file mode 100644 index 000000000..1efe7f23c --- /dev/null +++ b/test/Service/RequestFactoryTest.php @@ -0,0 +1,41 @@ +setConsoleEnvironment(true); + } + + public function testFactoryCreatesConsoleRequestInConsoleEnvironment() + { + $this->setConsoleEnvironment(true); + $factory = new RequestFactory(); + $request = $factory($this->createContainer(), 'Request'); + $this->assertInstanceOf(ConsoleRequest::class, $request); + } + + public function testFactoryCreatesHttpRequestInNonConsoleEnvironment() + { + $this->setConsoleEnvironment(false); + $factory = new RequestFactory(); + $request = $factory($this->createContainer(), 'Request'); + $this->assertInstanceOf(HttpRequest::class, $request); + } +} diff --git a/test/Service/ResponseFactoryTest.php b/test/Service/ResponseFactoryTest.php new file mode 100644 index 000000000..f6d5433da --- /dev/null +++ b/test/Service/ResponseFactoryTest.php @@ -0,0 +1,41 @@ +setConsoleEnvironment(true); + } + + public function testFactoryCreatesConsoleResponseInConsoleEnvironment() + { + $this->setConsoleEnvironment(true); + $factory = new ResponseFactory(); + $response = $factory($this->createContainer(), 'Response'); + $this->assertInstanceOf(ConsoleResponse::class, $response); + } + + public function testFactoryCreatesHttpResponseInNonConsoleEnvironment() + { + $this->setConsoleEnvironment(false); + $factory = new ResponseFactory(); + $response = $factory($this->createContainer(), 'Response'); + $this->assertInstanceOf(HttpResponse::class, $response); + } +} diff --git a/test/Service/RouterFactoryTest.php b/test/Service/RouterFactoryTest.php index a782f0ec0..8fe4485db 100644 --- a/test/Service/RouterFactoryTest.php +++ b/test/Service/RouterFactoryTest.php @@ -11,6 +11,8 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\Mvc\Router\RoutePluginManager; +use Zend\Mvc\Service\ConsoleRouterFactory; +use Zend\Mvc\Service\HttpRouterFactory; use Zend\Mvc\Service\RouterFactory; use Zend\ServiceManager\ServiceManager; @@ -18,37 +20,49 @@ class RouterFactoryTest extends TestCase { public function setUp() { - $this->services = new ServiceManager(); - $this->services->setService('RoutePluginManager', new RoutePluginManager()); + $this->defaultServiceConfig = [ + 'factories' => [ + 'ConsoleRouter' => ConsoleRouterFactory::class, + 'HttpRouter' => HttpRouterFactory::class, + 'RoutePluginManager' => function ($services, $name, array $options = null) { + return new RoutePluginManager($services); + }, + ], + ]; + $this->factory = new RouterFactory(); } public function testFactoryCanCreateRouterBasedOnConfiguredName() { - $this->services->setService('Config', [ - 'router' => [ - 'router_class' => 'ZendTest\Mvc\Service\TestAsset\Router', - ], - 'console' => [ + $services = new ServiceManager(array_merge_recursive($this->defaultServiceConfig, [ + 'services' => [ 'config' => [ 'router' => [ 'router_class' => 'ZendTest\Mvc\Service\TestAsset\Router', ], - ], - ]); + 'console' => [ + 'router' => [ + 'router_class' => 'ZendTest\Mvc\Service\TestAsset\Router', + ], + ], + ]], + ])); - $router = $this->factory->createService($this->services, 'router', 'Router'); + $router = $this->factory->__invoke($services, 'router'); $this->assertInstanceOf('ZendTest\Mvc\Service\TestAsset\Router', $router); } public function testFactoryCanCreateRouterWhenOnlyHttpRouterConfigPresent() { - $this->services->setService('Config', [ - 'router' => [ - 'router_class' => 'ZendTest\Mvc\Service\TestAsset\Router', - ], - ]); + $services = new ServiceManager(array_merge_recursive($this->defaultServiceConfig, [ + 'services' => [ 'config' => [ + 'router' => [ + 'router_class' => 'ZendTest\Mvc\Service\TestAsset\Router', + ], + ]], + ])); - $router = $this->factory->createService($this->services, 'router', 'Router'); + $router = $this->factory->__invoke($services, 'router'); $this->assertInstanceOf('Zend\Mvc\Router\Console\SimpleRouteStack', $router); } } diff --git a/test/Service/ServiceListenerFactoryTest.php b/test/Service/ServiceListenerFactoryTest.php index 8abd44280..c419aad1d 100644 --- a/test/Service/ServiceListenerFactoryTest.php +++ b/test/Service/ServiceListenerFactoryTest.php @@ -24,7 +24,7 @@ public function setUp() } /** - * @expectedException Zend\Mvc\Exception\InvalidArgumentException + * @expectedException Zend\ServiceManager\Exception\ServiceNotCreatedException * @expectedExceptionMessage The value of service_listener_options must be an array, string given. */ public function testInvalidOptionType() @@ -33,11 +33,11 @@ public function testInvalidOptionType() ->method('get') ->will($this->returnValue(['service_listener_options' => 'string'])); - $this->factory->createService($this->sm); + $this->factory->__invoke($this->sm, 'ServiceListener'); } /** - * @expectedException Zend\Mvc\Exception\InvalidArgumentException + * @expectedException Zend\ServiceManager\Exception\ServiceNotCreatedException * @expectedExceptionMessage Invalid service listener options detected, 0 array must contain service_manager key. */ public function testMissingServiceManager() @@ -51,11 +51,11 @@ public function testMissingServiceManager() ->method('get') ->will($this->returnValue($config)); - $this->factory->createService($this->sm); + $this->factory->__invoke($this->sm, 'ServiceListener'); } /** - * @expectedException Zend\Mvc\Exception\InvalidArgumentException + * @expectedException Zend\ServiceManager\Exception\ServiceNotCreatedException * @expectedExceptionMessage Invalid service listener options detected, service_manager must be a string, integer given. */ public function testInvalidTypeServiceManager() @@ -69,11 +69,11 @@ public function testInvalidTypeServiceManager() ->method('get') ->will($this->returnValue($config)); - $this->factory->createService($this->sm); + $this->factory->__invoke($this->sm, 'ServiceListener'); } /** - * @expectedException Zend\Mvc\Exception\InvalidArgumentException + * @expectedException Zend\ServiceManager\Exception\ServiceNotCreatedException * @expectedExceptionMessage Invalid service listener options detected, 0 array must contain config_key key. */ public function testMissingConfigKey() @@ -87,11 +87,11 @@ public function testMissingConfigKey() ->method('get') ->will($this->returnValue($config)); - $this->factory->createService($this->sm); + $this->factory->__invoke($this->sm, 'ServiceListener'); } /** - * @expectedException Zend\Mvc\Exception\InvalidArgumentException + * @expectedException Zend\ServiceManager\Exception\ServiceNotCreatedException * @expectedExceptionMessage Invalid service listener options detected, config_key must be a string, integer given. */ public function testInvalidTypeConfigKey() @@ -105,11 +105,11 @@ public function testInvalidTypeConfigKey() ->method('get') ->will($this->returnValue($config)); - $this->factory->createService($this->sm); + $this->factory->__invoke($this->sm, 'ServiceListener'); } /** - * @expectedException Zend\Mvc\Exception\InvalidArgumentException + * @expectedException Zend\ServiceManager\Exception\ServiceNotCreatedException * @expectedExceptionMessage Invalid service listener options detected, 0 array must contain interface key. */ public function testMissingInterface() @@ -123,11 +123,11 @@ public function testMissingInterface() ->method('get') ->will($this->returnValue($config)); - $this->factory->createService($this->sm); + $this->factory->__invoke($this->sm, 'ServiceListener'); } /** - * @expectedException Zend\Mvc\Exception\InvalidArgumentException + * @expectedException Zend\ServiceManager\Exception\ServiceNotCreatedException * @expectedExceptionMessage Invalid service listener options detected, interface must be a string, integer given. */ public function testInvalidTypeInterface() @@ -141,11 +141,11 @@ public function testInvalidTypeInterface() ->method('get') ->will($this->returnValue($config)); - $this->factory->createService($this->sm); + $this->factory->__invoke($this->sm, 'ServiceListener'); } /** - * @expectedException Zend\Mvc\Exception\InvalidArgumentException + * @expectedException Zend\ServiceManager\Exception\ServiceNotCreatedException * @expectedExceptionMessage Invalid service listener options detected, 0 array must contain method key. */ public function testMissingMethod() @@ -159,11 +159,11 @@ public function testMissingMethod() ->method('get') ->will($this->returnValue($config)); - $this->factory->createService($this->sm); + $this->factory->__invoke($this->sm, 'ServiceListener'); } /** - * @expectedException Zend\Mvc\Exception\InvalidArgumentException + * @expectedException Zend\ServiceManager\Exception\ServiceNotCreatedException * @expectedExceptionMessage Invalid service listener options detected, method must be a string, integer given. */ public function testInvalidTypeMethod() @@ -177,6 +177,6 @@ public function testInvalidTypeMethod() ->method('get') ->will($this->returnValue($config)); - $this->factory->createService($this->sm); + $this->factory->__invoke($this->sm, 'ServiceListener'); } } diff --git a/test/Service/ServiceManagerConfigTest.php b/test/Service/ServiceManagerConfigTest.php index b496ed82a..ef63793a4 100644 --- a/test/Service/ServiceManagerConfigTest.php +++ b/test/Service/ServiceManagerConfigTest.php @@ -10,9 +10,10 @@ namespace ZendTest\Mvc\Service; use PHPUnit_Framework_TestCase as TestCase; +use stdClass; use Zend\EventManager\EventManager; use Zend\Mvc\Service\ServiceManagerConfig; -use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\ServiceManager\Factory\InvokableFactory; use Zend\ServiceManager\ServiceManager; /** @@ -35,9 +36,8 @@ class ServiceManagerConfigTest extends TestCase */ protected function setUp() { - $this->config = new ServiceManagerConfig(); - $this->services = new ServiceManager(); - $this->config->configureServiceManager($this->services); + $this->config = new ServiceManagerConfig(); + $this->services = $this->config->configureServiceManager(new ServiceManager()); } /** @@ -48,12 +48,14 @@ public function testEventManagerAwareInterfaceIsNotInjectedIfPresentButSharedMan $events = new EventManager($this->services->get('SharedEventManager')); TestAsset\EventManagerAwareObject::$defaultEvents = $events; - $this->services->setInvokableClass('EventManagerAwareObject', __NAMESPACE__ . '\TestAsset\EventManagerAwareObject'); + $services = $this->services->withConfig(['invokables' => [ + 'EventManagerAwareObject' => TestAsset\EventManagerAwareObject::class, + ]]); - $instance = $this->services->get('EventManagerAwareObject'); - $this->assertInstanceOf(__NAMESPACE__ . '\TestAsset\EventManagerAwareObject', $instance); + $instance = $services->get('EventManagerAwareObject'); + $this->assertInstanceOf(TestAsset\EventManagerAwareObject::class, $instance); $this->assertSame($events, $instance->getEventManager()); - $this->assertSame($this->services->get('SharedEventManager'), $events->getSharedManager()); + $this->assertSame($services->get('SharedEventManager'), $events->getSharedManager()); } /** @@ -63,18 +65,17 @@ public function testCanMergeCustomConfigWithDefaultConfig() { $custom = [ 'invokables' => [ - 'foo' => '\stdClass', + 'foo' => stdClass::class, ], 'factories' => [ 'bar' => function () { - return new \stdClass(); + return new stdClass(); }, ], ]; $config = new ServiceManagerConfig($custom); - $sm = new ServiceManager(); - $config->configureServiceManager($sm); + $sm = $config->configureServiceManager(new ServiceManager()); $this->assertTrue($sm->has('foo')); $this->assertTrue($sm->has('bar')); @@ -88,23 +89,22 @@ public function testCanOverrideDefaultConfigWithCustomConfig() { $custom = [ 'invokables' => [ - 'foo' => '\stdClass', + 'foo' => stdClass::class, ], 'factories' => [ 'ModuleManager' => function () { - return new \stdClass(); + return new stdClass(); }, ], ]; $config = new ServiceManagerConfig($custom); - $sm = new ServiceManager(); - $config->configureServiceManager($sm); + $sm = $config->configureServiceManager(new ServiceManager()); $this->assertTrue($sm->has('foo')); $this->assertTrue($sm->has('ModuleManager')); - $this->assertInstanceOf('stdClass', $sm->get('ModuleManager')); + $this->assertInstanceOf(stdClass::class, $sm->get('ModuleManager')); } /** @@ -113,162 +113,53 @@ public function testCanOverrideDefaultConfigWithCustomConfig() public function testCanAddDelegators() { $config = [ - 'invokables' => [ - 'foo' => '\stdClass', + 'aliases' => [ + 'foo' => stdClass::class, + ], + 'factories' => [ + stdClass::class => InvokableFactory::class, ], 'delegators' => [ - 'foo' => [ - function (ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback) { + stdClass::class => [ + function ($container, $name, $callback, array $options = null) { $service = $callback(); $service->bar = 'baz'; return $service; }, - ] + ], ], ]; - $config = new ServiceManagerConfig($config); - $sm = new ServiceManager(); - $config->configureServiceManager($sm); - + $sm = new ServiceManager((new ServiceManagerConfig($config))->toArray()); $std = $sm->get('foo'); - $this->assertInstanceOf('stdClass', $std); + $this->assertInstanceOf(stdClass::class, $std); $this->assertEquals('baz', $std->bar); } - /** - * @group 6266 - */ - public function testDefinesServiceManagerService() - { - $this->assertSame($this->services, $this->services->get('ServiceManager')); - } - - /** - * @group 6266 - */ - public function testCanOverrideServiceManager() - { - $serviceManager = new ServiceManager(new ServiceManagerConfig([ - 'factories' => [ - 'ServiceManager' => function () { - return $this; - } - ], - ])); - - $this->assertSame($this, $serviceManager->get('ServiceManager')); - } - - /** - * @group 6266 - */ - public function testServiceManagerInitializerIsUsedForServiceManagerAwareObjects() - { - $instance = $this->getMock('Zend\ServiceManager\ServiceManagerAwareInterface'); - - $instance->expects($this->once())->method('setServiceManager')->with($this->services); - - $this->services->setFactory( - 'service-manager-aware', - function () use ($instance) { - return $instance; - } - ); - - $this->services->get('service-manager-aware'); - } - - /** - * @group 6266 - */ - public function testServiceManagerInitializerCanBeReplaced() - { - $instance = $this->getMock('Zend\ServiceManager\ServiceManagerAwareInterface'); - $initializer = $this->getMock('stdClass', ['__invoke']); - $serviceManager = new ServiceManager(new ServiceManagerConfig([ - 'initializers' => [ - 'ServiceManagerAwareInitializer' => $initializer - ], - 'factories' => [ - 'service-manager-aware' => function () use ($instance) { - return $instance; - }, - ], - ])); - - $initializer->expects($this->once())->method('__invoke')->with($instance, $serviceManager); - $instance->expects($this->never())->method('setServiceManager'); - - $serviceManager->get('service-manager-aware'); - } - - /** - * @group 6266 - */ - public function testServiceLocatorInitializerIsUsedForServiceLocatorAwareObjects() - { - $instance = $this->getMock('Zend\ServiceManager\ServiceLocatorAwareInterface'); - - $instance->expects($this->once())->method('setServiceLocator')->with($this->services); - - $this->services->setFactory( - 'service-locator-aware', - function () use ($instance) { - return $instance; - } - ); - - $this->services->get('service-locator-aware'); - } - - /** - * @group 6266 - */ - public function testServiceLocatorInitializerCanBeReplaced() - { - $instance = $this->getMock('Zend\ServiceManager\ServiceLocatorAwareInterface'); - $initializer = $this->getMock('stdClass', ['__invoke']); - $serviceManager = new ServiceManager(new ServiceManagerConfig([ - 'initializers' => [ - 'ServiceLocatorAwareInitializer' => $initializer - ], - 'factories' => [ - 'service-locator-aware' => function () use ($instance) { - return $instance; - }, - ], - ])); - - $initializer->expects($this->once())->method('__invoke')->with($instance, $serviceManager); - $instance->expects($this->never())->method('setServiceLocator'); - - $serviceManager->get('service-locator-aware'); - } - /** * @group 6266 */ public function testEventManagerInitializerCanBeReplaced() { $instance = $this->getMock('Zend\EventManager\EventManagerAwareInterface'); - $initializer = $this->getMock('stdClass', ['__invoke']); - $serviceManager = new ServiceManager(new ServiceManagerConfig([ + $initializer = $this->getMock(stdClass::class, ['__invoke']); + $config = new ServiceManagerConfig([ 'initializers' => [ - 'EventManagerAwareInitializer' => $initializer + 'EventManagerAwareInitializer' => $initializer, ], 'factories' => [ - 'event-manager-aware' => function () use ($instance) { + 'EventManagerAware' => function () use ($instance) { return $instance; }, ], - ])); + ]); + $serviceManager = $config->configureServiceManager(new ServiceManager()); - $initializer->expects($this->once())->method('__invoke')->with($instance, $serviceManager); + $initializer->expects($this->once())->method('__invoke')->with($serviceManager, $instance); $instance->expects($this->never())->method('getEventManager'); $instance->expects($this->never())->method('setEventManager'); - $serviceManager->get('event-manager-aware'); + $serviceManager->get('EventManagerAware'); } } diff --git a/test/Service/TranslatorServiceFactoryTest.php b/test/Service/TranslatorServiceFactoryTest.php index 8697a9e93..feb2a356b 100644 --- a/test/Service/TranslatorServiceFactoryTest.php +++ b/test/Service/TranslatorServiceFactoryTest.php @@ -10,6 +10,8 @@ namespace ZendTest\Mvc\Service; use PHPUnit_Framework_TestCase as TestCase; +use Zend\I18n\Translator\LoaderPluginManager; +use Zend\I18n\Translator\TranslatorInterface; use Zend\Mvc\Service\RoutePluginManagerFactory; use Zend\Mvc\Service\ServiceManagerConfig; use Zend\Mvc\Service\TranslatorServiceFactory; @@ -19,20 +21,22 @@ class TranslatorServiceFactoryTest extends TestCase { public function setUp() { + $this->markTestIncomplete('Re-enable and refactor once zend-i18n is updated to zend-servicemanager v3'); + $this->factory = new TranslatorServiceFactory(); - $this->services = new ServiceManager(); - $this->services->setService( - 'TranslatorPluginManager', - $this->getMock('Zend\I18n\Translator\LoaderPluginManager') - ); + $this->services = new ServiceManager(['services' => [ + 'TranslatorPluginManager' => $this->getMock(LoaderPluginManager::class), + ]]); } public function testReturnsMvcTranslatorWithTranslatorInterfaceServiceComposedWhenPresent() { $i18nTranslator = $this->getMock('Zend\I18n\Translator\TranslatorInterface'); - $this->services->setService('Zend\I18n\Translator\TranslatorInterface', $i18nTranslator); + $services = $this->services->withConfig(['services' => [ + TranslatorInterface::class => $i18nTranslator, + ]]); - $translator = $this->factory->createService($this->services); + $translator = $this->factory->__invoke($services); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertSame($i18nTranslator, $translator->getTranslator()); } @@ -43,7 +47,7 @@ public function testReturnsMvcTranslatorWithDummyTranslatorComposedWhenExtIntlIs $this->markTestSkipped('This test will only run if ext/intl is not present'); } - $translator = $this->factory->createService($this->services); + $translator = $this->factory->__invoke($this->services); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertInstanceOf('Zend\Mvc\I18n\DummyTranslator', $translator->getTranslator()); } @@ -54,7 +58,7 @@ public function testReturnsMvcTranslatorWithI18nTranslatorComposedWhenNoTranslat $this->markTestSkipped('This test will only run if ext/intl is present'); } - $translator = $this->factory->createService($this->services); + $translator = $this->factory->__invoke($this->services); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertInstanceOf('Zend\I18n\Translator\Translator', $translator->getTranslator()); } @@ -64,15 +68,17 @@ public function testReturnsTranslatorBasedOnConfigurationWhenNoTranslatorInterfa $config = ['translator' => [ 'locale' => 'en_US', ]]; - $this->services->setService('Config', $config); + $services = $this->services->withConfig(['services' => [ + 'config' => $config, + ]]); - $translator = $this->factory->createService($this->services); + $translator = $this->factory->__invoke($services); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertInstanceOf('Zend\I18n\Translator\Translator', $translator->getTranslator()); return [ 'translator' => $translator->getTranslator(), - 'services' => $this->services, + 'services' => $services, ]; } @@ -95,17 +101,14 @@ public function testSetsPluginManagerFromServiceLocatorBasedOnConfiguration() 'module_listener_options' => [], 'modules' => [], ]; - $serviceLocator = new ServiceManager(new ServiceManagerConfig()); - $serviceLocator->setService('ApplicationConfig', $applicationConfig); + $config = new ServiceManagerConfig(); + $config = array_merge_recursive($config->toArray(), ['services' => [ + 'ApplicationConfig' => $applicationConfig, + ]]); + $serviceLocator = new ServiceManager($config); $serviceLocator->get('ModuleManager')->loadModules(); $serviceLocator->get('Application')->bootstrap(); - //enable to re-write Config - $ref = new \ReflectionObject($serviceLocator); - $prop = $ref->getProperty('allowOverride'); - $prop->setAccessible(true); - $prop->setValue($serviceLocator, true); - $config = [ 'di' => [], 'translator' => [ @@ -113,12 +116,14 @@ public function testSetsPluginManagerFromServiceLocatorBasedOnConfiguration() ], ]; - $serviceLocator->setService('Config', $config); + $services = $serviceLocator->withConfig(['services' => [ + 'config' => $config, + ]]); - $translator = $this->factory->createService($serviceLocator); + $translator = $this->factory->__invoke($services); $this->assertEquals( - $serviceLocator->get('TranslatorPluginManager'), + $services->get('TranslatorPluginManager'), $translator->getPluginManager() ); } @@ -134,17 +139,13 @@ public function testReturnsTranslatorBasedOnConfigurationWhenNoTranslatorInterfa 'module_listener_options' => [], 'modules' => [], ]; - $serviceLocator = new ServiceManager(new ServiceManagerConfig()); - $serviceLocator->setService('ApplicationConfig', $applicationConfig); + $config = array_merge_recursive((new ServiceManagerConfig())->toArray(), ['services' => [ + 'ApplicationConfig' => $applicationConfig, + ]]); + $serviceLocator = new ServiceManager($config); $serviceLocator->get('ModuleManager')->loadModules(); $serviceLocator->get('Application')->bootstrap(); - //enable to re-write Config - $ref = new \ReflectionObject($serviceLocator); - $prop = $ref->getProperty('allowOverride'); - $prop->setAccessible(true); - $prop->setValue($serviceLocator, true); - $config = [ 'di' => [], 'translator' => [ @@ -152,14 +153,16 @@ public function testReturnsTranslatorBasedOnConfigurationWhenNoTranslatorInterfa ], ]; - $serviceLocator->setService('Config', $config); + $services = $serviceLocator->withConfig(['services' => [ + 'config' => $config, + ]]); //#5959 //get any plugins with AbstractPluginManagerFactory $routePluginManagerFactory = new RoutePluginManagerFactory; - $routePluginManager = $routePluginManagerFactory->createService($serviceLocator); + $routePluginManager = $routePluginManagerFactory($services, 'RoutePluginManager'); - $translator = $this->factory->createService($serviceLocator); + $translator = $this->factory->__invoke($services); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertInstanceOf('Zend\I18n\Translator\Translator', $translator->getTranslator()); } @@ -169,6 +172,7 @@ public function testReturnsTranslatorBasedOnConfigurationWhenNoTranslatorInterfa */ public function testSetsInstantiatedI18nTranslatorInstanceInServiceManager($dependencies) { + $this->markTestIncomplete('Test disabled for v3; need to determine if needed'); $translator = $dependencies['translator']; $services = $dependencies['services']; $this->assertTrue($services->has('Zend\I18n\Translator\TranslatorInterface')); @@ -180,12 +184,13 @@ public function testPrefersTranslatorInterfaceImplementationOverConfig() $config = ['translator' => [ 'locale' => 'en_US', ]]; - $this->services->setService('Config', $config); - $i18nTranslator = $this->getMock('Zend\I18n\Translator\TranslatorInterface'); - $this->services->setService('Zend\I18n\Translator\TranslatorInterface', $i18nTranslator); + $services = $this->services->withConfig(['services' => [ + 'config' => $config, + 'Zend\I18n\Translator\TranslatorInterface' => $i18nTranslator, + ]]); - $translator = $this->factory->createService($this->services); + $translator = $this->factory->__invoke($services); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertSame($i18nTranslator, $translator->getTranslator()); } @@ -193,8 +198,10 @@ public function testPrefersTranslatorInterfaceImplementationOverConfig() public function testReturnsDummyTranslatorWhenTranslatorConfigIsBooleanFalse() { $config = ['translator' => false]; - $this->services->setService('Config', $config); - $translator = $this->factory->createService($this->services); + $services = $this->services->withConfig(['services' => [ + 'config' => $config, + ]]); + $translator = $this->factory->__invoke($services); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertInstanceOf('Zend\Mvc\I18n\DummyTranslator', $translator->getTranslator()); } diff --git a/test/Service/ViewFeedStrategyFactoryTest.php b/test/Service/ViewFeedStrategyFactoryTest.php new file mode 100644 index 000000000..a3541ce6a --- /dev/null +++ b/test/Service/ViewFeedStrategyFactoryTest.php @@ -0,0 +1,36 @@ +prophesize(FeedRenderer::class); + $container = $this->prophesize(ContainerInterface::class); + $container->get('ViewFeedRenderer')->will(function () use ($renderer) { + return $renderer->reveal(); + }); + return $container->reveal(); + } + + public function testReturnsFeedStrategy() + { + $factory = new ViewFeedStrategyFactory(); + $result = $factory($this->createContainer(), 'ViewFeedStrategy'); + $this->assertInstanceOf(FeedStrategy::class, $result); + } +} diff --git a/test/Service/ViewHelperManagerFactoryTest.php b/test/Service/ViewHelperManagerFactoryTest.php index 955ea2302..c43aed988 100644 --- a/test/Service/ViewHelperManagerFactoryTest.php +++ b/test/Service/ViewHelperManagerFactoryTest.php @@ -9,8 +9,16 @@ namespace ZendTest\Mvc\Service; +use Interop\Container\ContainerInterface; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionProperty; +use Zend\Console\Console; use Zend\Console\Request as ConsoleRequest; +use Zend\Http\PhpEnvironment\Request as HttpRequest; +use Zend\Mvc\Application; +use Zend\Mvc\MvcEvent; +use Zend\Mvc\Router\RouteMatch; +use Zend\Mvc\Router\RouteStackInterface; use Zend\Mvc\Service\ViewHelperManagerFactory; use Zend\ServiceManager\ServiceManager; @@ -41,8 +49,10 @@ public function emptyConfiguration() */ public function testDoctypeFactoryDoesNotRaiseErrorOnMissingConfiguration($config) { - $this->services->setService('Config', $config); - $manager = $this->factory->createService($this->services); + $services = $this->services->withConfig(['services' => [ + 'config' => $config, + ]]); + $manager = $this->factory->__invoke($services, 'ViewHelperManager'); $this->assertInstanceof('Zend\View\HelperPluginManager', $manager); $doctype = $manager->get('doctype'); $this->assertInstanceof('Zend\View\Helper\Doctype', $doctype); @@ -50,10 +60,12 @@ public function testDoctypeFactoryDoesNotRaiseErrorOnMissingConfiguration($confi public function testConsoleRequestsResultInSilentFailure() { - $this->services->setService('Config', []); - $this->services->setService('Request', new ConsoleRequest()); + $services = $this->services->withConfig(['services' => [ + 'config' => [], + 'Request' => new ConsoleRequest(), + ]]); - $manager = $this->factory->createService($this->services); + $manager = $this->factory->__invoke($services, 'ViewHelperManager'); $doctype = $manager->get('doctype'); $this->assertInstanceof('Zend\View\Helper\Doctype', $doctype); @@ -67,18 +79,141 @@ public function testConsoleRequestsResultInSilentFailure() */ public function testConsoleRequestWithBasePathConsole() { - $this->services->setService('Config', - [ + // Force Console context + $r = new ReflectionProperty(Console::class, 'isConsole'); + $r->setAccessible(true); + $r->setValue(true); + + if (! Console::isConsole()) { + $this->markTestSkipped('Cannot force console context; skipping test'); + } + + $services = $this->services->withConfig(['services' => [ + 'config' => [ 'view_manager' => [ - 'base_path_console' => 'http://test.com' - ] - ] + 'base_path_console' => 'http://test.com', + ], + ], + 'Request' => new ConsoleRequest(), + ]]); + + $this->assertTrue($services->has('config'), 'Config service does not appear to be present'); + $config = $services->get('config'); + $this->assertArrayHasKey( + 'view_manager', + $config, + 'Config service is missing view_manager configuration' + ); + $this->assertArrayHasKey( + 'base_path_console', + $config['view_manager'], + 'Config service is missing base_path_console view_manager configuration' ); - $this->services->setService('Request', new ConsoleRequest()); - $manager = $this->factory->createService($this->services); + $manager = $this->factory->__invoke($services, 'ViewHelperManager'); $basePath = $manager->get('basepath'); $this->assertEquals('http://test.com', $basePath()); } + + public function testCreatesCustomUrlHelperFactory() + { + $routeMatch = $this->prophesize(RouteMatch::class); + + $mvcEvent = $this->prophesize(MvcEvent::class); + $mvcEvent->getRouteMatch()->will(function () use ($routeMatch) { + return $routeMatch->reveal(); + }); + + $application = $this->prophesize(Application::class); + $application->getMvcEvent()->will(function () use ($mvcEvent) { + return $mvcEvent->reveal(); + }); + + $router = $this->prophesize(RouteStackInterface::class); + + $container = $this->prophesize(ContainerInterface::class); + $container->has('config')->willReturn(false); + $container->get('Router')->will(function () use ($router) { + return $router->reveal(); + }); + $container->get('HttpRouter')->will(function () use ($router) { + return $router->reveal(); + }); + $container->get('application')->will(function () use ($application) { + return $application->reveal(); + }); + + $factory = $this->factory; + $manager = $factory($container->reveal(), 'ViewHelperManager'); + $helper = $manager->get('url'); + $this->assertAttributeSame($router->reveal(), 'router', $helper); + $this->assertAttributeSame($routeMatch->reveal(), 'routeMatch', $helper); + } + + public function testCustomBasePathHelperFactoryCanUseViewManagerConfig() + { + $container = $this->prophesize(ContainerInterface::class); + $container->has('config')->willReturn(true); + $container->get('config')->willReturn([ + 'view_manager' => [ + 'base_path' => 'https://example.com/test', + ], + ]); + + $factory = $this->factory; + $manager = $factory($container->reveal(), 'ViewHelperManager'); + $helper = $manager->get('basepath'); + $this->assertEquals('https://example.com/test', $helper()); + } + + public function testCustomBasePathHelperFactoryCanUseViewManagerConsoleConfig() + { + $container = $this->prophesize(ContainerInterface::class); + $container->has('config')->willReturn(true); + $container->get('config')->willReturn([ + 'view_manager' => [ + 'base_path_console' => 'https://example.com/test', + ], + ]); + + $factory = $this->factory; + $manager = $factory($container->reveal(), 'ViewHelperManager'); + $helper = $manager->get('basepath'); + $this->assertEquals('https://example.com/test', $helper()); + } + + public function testCustomBasePathHelperFactoryCanUseRequestService() + { + $request = $this->prophesize(HttpRequest::class); + $request->getBasePath()->willReturn('https://example.com/test'); + + $container = $this->prophesize(ContainerInterface::class); + $container->has('config')->willReturn(true); + $container->get('config')->willReturn([]); + $container->get('Request')->will(function () use ($request) { + return $request->reveal(); + }); + + $factory = $this->factory; + $manager = $factory($container->reveal(), 'ViewHelperManager'); + $helper = $manager->get('basepath'); + $this->assertEquals('https://example.com/test', $helper()); + } + + public function testCustomDoctypeHelperFactoryCanUseViewManagerConfig() + { + $container = $this->prophesize(ContainerInterface::class); + $container->has('config')->willReturn(true); + $container->get('config')->willReturn([ + 'view_manager' => [ + 'doctype' => 'CUSTOM', + ], + ]); + + $factory = $this->factory; + $manager = $factory($container->reveal(), 'ViewHelperManager'); + $helper = $manager->get('doctype'); + $this->assertEquals('CUSTOM', $helper->getDoctype()); + } } diff --git a/test/Service/ViewJsonStrategyFactoryTest.php b/test/Service/ViewJsonStrategyFactoryTest.php new file mode 100644 index 000000000..f364589d4 --- /dev/null +++ b/test/Service/ViewJsonStrategyFactoryTest.php @@ -0,0 +1,36 @@ +prophesize(JsonRenderer::class); + $container = $this->prophesize(ContainerInterface::class); + $container->get('ViewJsonRenderer')->will(function () use ($renderer) { + return $renderer->reveal(); + }); + return $container->reveal(); + } + + public function testReturnsJsonStrategy() + { + $factory = new ViewJsonStrategyFactory(); + $result = $factory($this->createContainer(), 'ViewJsonStrategy'); + $this->assertInstanceOf(JsonStrategy::class, $result); + } +} diff --git a/test/Service/ViewManagerFactoryTest.php b/test/Service/ViewManagerFactoryTest.php new file mode 100644 index 000000000..a81bea773 --- /dev/null +++ b/test/Service/ViewManagerFactoryTest.php @@ -0,0 +1,56 @@ +setConsoleEnvironment(true); + } + + private function createContainer() + { + $console = $this->prophesize(ConsoleViewManager::class); + $http = $this->prophesize(HttpViewManager::class); + $container = $this->prophesize(ContainerInterface::class); + $container->get('ConsoleViewManager')->will(function () use ($console) { + return $console->reveal(); + }); + $container->get('HttpViewManager')->will(function () use ($http) { + return $http->reveal(); + }); + return $container->reveal(); + } + + public function testReturnsConsoleViewManagerInConsoleEnvironment() + { + $this->setConsoleEnvironment(true); + $factory = new ViewManagerFactory(); + $result = $factory($this->createContainer(), 'ViewManager'); + $this->assertInstanceOf(ConsoleViewManager::class, $result); + } + + public function testReturnsHttpViewManagerInNonConsoleEnvironment() + { + $this->setConsoleEnvironment(false); + $factory = new ViewManagerFactory(); + $result = $factory($this->createContainer(), 'ViewManager'); + $this->assertInstanceOf(HttpViewManager::class, $result); + } +} diff --git a/test/Service/ViewPrefixPathStackResolverFactoryTest.php b/test/Service/ViewPrefixPathStackResolverFactoryTest.php index eff5c39e3..87a5d251b 100644 --- a/test/Service/ViewPrefixPathStackResolverFactoryTest.php +++ b/test/Service/ViewPrefixPathStackResolverFactoryTest.php @@ -20,7 +20,7 @@ public function testCreateService() $serviceLocator->expects($this->once()) ->method('get') - ->with('Config') + ->with('config') ->will($this->returnValue([ 'view_manager' => [ 'prefix_template_path_stack' => [ @@ -30,7 +30,7 @@ public function testCreateService() ])); $factory = new ViewPrefixPathStackResolverFactory(); - $resolver = $factory->createService($serviceLocator); + $resolver = $factory($serviceLocator, 'ViewPrefixPathStackResolver'); $this->assertInstanceOf('Zend\View\Resolver\PrefixPathStackResolver', $resolver); } diff --git a/test/TestAsset/Locator.php b/test/TestAsset/Locator.php index 1b77624b4..2546ea7d4 100644 --- a/test/TestAsset/Locator.php +++ b/test/TestAsset/Locator.php @@ -10,7 +10,7 @@ namespace ZendTest\Mvc\TestAsset; use Zend\ServiceManager\ServiceLocatorInterface; -use Zend\Di\Exception\ClassNotFoundException; +use Zend\ServiceManager\Exception\ServiceNotFoundException; /** * Dummy locator used to test handling of locator objects by Application @@ -19,14 +19,13 @@ class Locator implements ServiceLocatorInterface { protected $services = array(); - public function get($name, array $params = array()) + public function get($name) { if (!isset($this->services[$name])) { - throw new ClassNotFoundException(); + throw new ServiceNotFoundException(); } - $service = call_user_func_array($this->services[$name], $params); - return $service; + return call_user_func_array($this->services[$name]); } public function has($name) @@ -34,6 +33,15 @@ public function has($name) return (isset($this->services[$name])); } + public function build($name, array $options = null) + { + if (!isset($this->services[$name])) { + throw new ServiceNotFoundException(); + } + + return call_user_func_array($this->services[$name], $options); + } + public function add($name, $callback) { $this->services[$name] = $callback; diff --git a/test/View/Console/CreateViewModelListenerTest.php b/test/View/Console/CreateViewModelListenerTest.php new file mode 100644 index 000000000..61f09087d --- /dev/null +++ b/test/View/Console/CreateViewModelListenerTest.php @@ -0,0 +1,102 @@ +listener = new CreateViewModelListener(); + } + + public function testAttachesListenersAtExpectedPriorities() + { + $events = new EventManager(); + $this->listener->attach($events); + + $this->assertListenerAtPriority( + [$this->listener, 'createViewModelFromString'], + -80, + MvcEvent::EVENT_DISPATCH, + $events, + 'View model from string listener not found' + ); + + $this->assertListenerAtPriority( + [$this->listener, 'createViewModelFromArray'], + -80, + MvcEvent::EVENT_DISPATCH, + $events, + 'View model from array listener not found' + ); + + $this->assertListenerAtPriority( + [$this->listener, 'createViewModelFromNull'], + -80, + MvcEvent::EVENT_DISPATCH, + $events, + 'View model from null listener not found' + ); + } + + public function testCanDetachListenersFromEventManager() + { + $events = new EventManager(); + $this->listener->attach($events); + + $listeners = $this->getArrayOfListenersForEvent(MvcEvent::EVENT_DISPATCH, $events); + $this->assertCount(3, $listeners); + + $this->listener->detach($events); + $listeners = $this->getArrayOfListenersForEvent(MvcEvent::EVENT_DISPATCH, $events); + $this->assertCount(0, $listeners); + } + + public function testCanCreateViewModelFromStringResult() + { + $event = new MvcEvent(); + $event->setResult('content'); + $this->listener->createViewModelFromString($event); + + $result = $event->getResult(); + $this->assertInstanceOf(ConsoleModel::class, $result); + $this->assertSame('content', $result->getVariable(ConsoleModel::RESULT)); + } + + public function testCanCreateViewModelFromArrayResult() + { + $expected = ['foo' => 'bar']; + $event = new MvcEvent(); + $event->setResult($expected); + $this->listener->createViewModelFromArray($event); + + $result = $event->getResult(); + $this->assertInstanceOf(ConsoleModel::class, $result); + $this->assertSame($expected, $result->getVariables()); + } + + public function testCanCreateViewModelFromNullResult() + { + $event = new MvcEvent(); + $this->listener->createViewModelFromNull($event); + + $result = $event->getResult(); + $this->assertInstanceOf(ConsoleModel::class, $result); + } +} diff --git a/test/View/Console/DefaultRenderingStrategyTest.php b/test/View/Console/DefaultRenderingStrategyTest.php index 43020d80a..25eea159c 100644 --- a/test/View/Console/DefaultRenderingStrategyTest.php +++ b/test/View/Console/DefaultRenderingStrategyTest.php @@ -67,8 +67,9 @@ public function testIgnoresNonConsoleModelNotContainingResultKeyWhenObtainingRes ->willReturnArgument(0); //Register console service - $sm = new ServiceManager(); - $sm->setService('console', $console); + $sm = new ServiceManager(['services' => [ + 'console' => $console, + ]]); /* @var \PHPUnit_Framework_MockObject_MockObject|ApplicationInterface $mockApplication */ $mockApplication = $this->getMock(ApplicationInterface::class); @@ -98,8 +99,9 @@ public function testIgnoresNonModel() ->willReturnArgument(0); //Register console service - $sm = new ServiceManager(); - $sm->setService('console', $console); + $sm = new ServiceManager(['services' => [ + 'console' => $console, + ]]); /* @var \PHPUnit_Framework_MockObject_MockObject|ApplicationInterface $mockApplication */ $mockApplication = $this->getMock(ApplicationInterface::class); diff --git a/test/View/Console/ViewManagerTest.php b/test/View/Console/ViewManagerTest.php index 9d1d735fa..4bd7aea5d 100644 --- a/test/View/Console/ViewManagerTest.php +++ b/test/View/Console/ViewManagerTest.php @@ -10,15 +10,19 @@ namespace ZendTest\Mvc\View\Console; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionProperty; +use Zend\Console\Request as ConsoleRequest; use Zend\Console\Response as ConsoleResponse; use Zend\EventManager\EventManager; use Zend\EventManager\SharedEventManager; use Zend\Mvc\Application; use Zend\Mvc\MvcEvent; use Zend\Mvc\Service\ConsoleViewManagerFactory; +use Zend\Mvc\Service\ServiceListenerFactory; use Zend\Mvc\Service\ServiceManagerConfig; +use Zend\Mvc\View\Console\ViewManager; use Zend\ServiceManager\ServiceManager; -use Zend\Console\Request as ConsoleRequest; +use Zend\Stdlib\ArrayUtils; /** * Tests for {@see \Zend\Mvc\View\Console\ViewManager} @@ -44,9 +48,18 @@ class ViewManagerTest extends TestCase public function setUp() { - $this->config = new ServiceManagerConfig(); - $this->services = new ServiceManager(); - $this->factory = new ConsoleViewManagerFactory(); + $this->services = new ServiceManager($this->prepareServiceManagerConfig()); + $this->factory = new ConsoleViewManagerFactory(); + } + + private function prepareServiceManagerConfig() + { + $serviceListener = new ServiceListenerFactory(); + $r = new ReflectionProperty($serviceListener, 'defaultServiceConfig'); + $r->setAccessible(true); + + $config = $r->getValue($serviceListener); + return ArrayUtils::merge((new ServiceManagerConfig())->toArray(), $config); } /** @@ -105,27 +118,29 @@ public function viewManagerConfiguration() * * @group 6866 */ - public function testConsoleKeyWillOverrideDisplayExceptionAndDisplayNotFoundReason($config) + public function testConsoleKeyWillOverrideDisplayExceptionAndExceptionMessage($config) { $eventManager = new EventManager(new SharedEventManager()); $request = new ConsoleRequest(); $response = new ConsoleResponse(); - $this->services->setService('Config', $config); - $this->services->setService('Request', $request); - $this->services->setService('EventManager', $eventManager); - $this->services->setService('Response', $response); + $services = $this->services->withConfig(['services' => [ + 'config' => $config, + 'Request' => $request, + 'EventManager' => $eventManager, + 'Response' => $response, + ]]); - $manager = $this->factory->createService($this->services); + $manager = $this->factory->__invoke($services, 'ConsoleViewRenderer'); - $application = new Application($config, $this->services, $eventManager, $request, $response); + $application = new Application($config, $services, $eventManager, $request, $response); $event = new MvcEvent(); $event->setApplication($application); $manager->onBootstrap($event); - $this->assertFalse($manager->getExceptionStrategy()->displayExceptions()); - $this->assertFalse($manager->getRouteNotFoundStrategy()->displayNotFoundReason()); + $this->assertFalse($services->get('ConsoleExceptionStrategy')->displayExceptions()); + $this->assertFalse($services->get('ConsoleRouteNotFoundStrategy')->displayNotFoundReason()); } /** @@ -137,20 +152,28 @@ public function testConsoleDisplayExceptionIsTrue() $request = new ConsoleRequest(); $response = new ConsoleResponse(); - $this->services->setService('Config', []); - $this->services->setService('Request', $request); - $this->services->setService('EventManager', $eventManager); - $this->services->setService('Response', $response); - - $manager = $this->factory->createService($this->services); - - $application = new Application([], $this->services, $eventManager, $request, $response); + $services = $this->services->withConfig([ + 'services' => [ + 'config' => [], + 'Request' => $request, + 'EventManager' => $eventManager, + 'Response' => $response, + ], + ]); - $event = new MvcEvent(); + $manager = new ViewManager; + $application = new Application([], $services, $eventManager, $request, $response); + $event = new MvcEvent(); $event->setApplication($application); + $manager->onBootstrap($event); - $this->assertTrue($manager->getExceptionStrategy()->displayExceptions()); - $this->assertTrue($manager->getRouteNotFoundStrategy()->displayNotFoundReason()); + $exceptionStrategy = $services->get('ConsoleExceptionStrategy'); + $this->assertInstanceOf('Zend\Mvc\View\Console\ExceptionStrategy', $exceptionStrategy); + $this->assertTrue($exceptionStrategy->displayExceptions()); + + $routeNotFoundStrategy = $services->get('ConsoleRouteNotFoundStrategy'); + $this->assertInstanceOf('Zend\Mvc\View\Console\RouteNotFoundStrategy', $routeNotFoundStrategy); + $this->assertTrue($routeNotFoundStrategy->displayNotFoundReason()); } } diff --git a/test/View/DefaultRendereringStrategyTest.php b/test/View/DefaultRendereringStrategyTest.php index 18715e64d..87f242a78 100644 --- a/test/View/DefaultRendereringStrategyTest.php +++ b/test/View/DefaultRendereringStrategyTest.php @@ -134,15 +134,25 @@ public function testTriggersRenderErrorEventInCaseOfRenderingException() $model->setTemplate('exception'); $this->event->setViewModel($model); - $services = new ServiceManager(); - $services->setService('Request', $this->request); - $services->setService('Response', $this->response); - $services->setInvokableClass('SharedEventManager', 'Zend\EventManager\SharedEventManager'); - $services->setFactory('EventManager', function ($services) { - $sharedEvents = $services->get('SharedEventManager'); - $events = new EventManager($sharedEvents); - return $events; - }, false); + $services = new ServiceManager([ + 'invokables' => [ + 'SharedEventManager' => 'Zend\EventManager\SharedEventManager', + ], + 'factories' => [ + 'EventManager' => function ($services, $name, array $options = null) { + $sharedEvents = $services->get('SharedEventManager'); + $events = new EventManager($sharedEvents); + return $events; + }, + ], + 'services' => [ + 'Request' => $this->request, + 'Response' => $this->response, + ], + 'shared' => [ + 'EventManager' => false, + ], + ]); $application = new Application([], $services, $services->get('EventManager'), $this->request, $this->response); $this->event->setApplication($application);