diff --git a/.travis.yml b/.travis.yml index 1ef118c43..c3d3d1abf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,17 +11,48 @@ cache: directories: - $HOME/.composer/cache +env: + global: + - EVENT_MANAGER_VERSION="^3.0" + - HYDRATOR_VERSION="^2.1" + - SERVICE_MANAGER_VERSION="^3.0.3" + - STDLIB_VERSION="^3.0" + matrix: fast_finish: true include: - php: 5.5 env: - EXECUTE_CS_CHECK=true + - php: 5.5 + env: + - EVENT_MANAGER_VERSION="^2.6.2" + - HYDRATOR_VERSION="^1.1" + - SERVICE_MANAGER_VERSION="^2.7.5" + - STDLIB_VERSION="^2.7.5" - php: 5.6 env: - EXECUTE_TEST_COVERALLS=true + - php: 5.6 + env: + - EVENT_MANAGER_VERSION="^2.6.2" + - HYDRATOR_VERSION="^1.1" + - SERVICE_MANAGER_VERSION="^2.7.5" + - STDLIB_VERSION="^2.7.5" - php: 7 + - php: 7 + env: + - EVENT_MANAGER_VERSION="^2.6.2" + - HYDRATOR_VERSION="^1.1" + - SERVICE_MANAGER_VERSION="^2.7.5" + - STDLIB_VERSION="^2.7.5" - php: hhvm + - php: hhvm + env: + - EVENT_MANAGER_VERSION="^2.6.2" + - HYDRATOR_VERSION="^1.1" + - SERVICE_MANAGER_VERSION="^2.7.5" + - STDLIB_VERSION="^2.7.5" allow_failures: - php: hhvm @@ -33,6 +64,7 @@ before_install: - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi - composer self-update - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then composer require --dev --no-update satooshi/php-coveralls ; fi + - composer require --no-update "zendframework/zend-eventmanager:$EVENT_MANAGER_VERSION" "zendframework/zend-servicemanager:$SERVICE_MANAGER_VERSION" "zendframework/zend-hydrator:$HYDRATOR_VERSION" "zendframework/zend-stdlib:$STDLIB_VERSION" install: - travis_retry composer install --no-interaction --ignore-platform-reqs diff --git a/CHANGELOG.md b/CHANGELOG.md index 646529690..8b377afd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,12 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. -## 3.0.0 - TBD +## 2.7.0 - TBD ### Added -- [#31](https://github.com/zendframework/zend-mvc/pull/31) adds three required - arguments to the `Zend\Mvc\Application` constructor: an EventManager +- [#31](https://github.com/zendframework/zend-mvc/pull/31) adds three new + optional 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 @@ -40,56 +40,38 @@ All notable changes to this project will be documented in this file, in reverse ### Deprecated -- Nothing. +- Two initializers registered by `Zend\Mvc\Service\ServiceManagerConfig` are now + deprecated, and will be removed starting in version 3.0: + - `ServiceManagerAwareInitializer`, which injects classes implementing + `Zend\ServiceManager\ServiceManagerAwareInterface` with the service manager + instance. Users should create factories for such classes that directly + inject their dependencies instead. + - `ServiceLocatorAwareInitializer`, which injects classes implementing + `Zend\ServiceManager\ServiceLocatorAwareInterface` with the service manager + instance. Users should create factories for such classes that directly + inject their dependencies instead. ### Removed -- [#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. +- Nothing. ### 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). +- [#31](https://github.com/zendframework/zend-mvc/pull/31) and + [#76](https://github.com/zendframework/zend-mvc/pull/76) update the component + to be forwards-compatible with zend-eventmanager v3. +- [#36](https://github.com/zendframework/zend-mvc/pull/36) and + [#76](https://github.com/zendframework/zend-mvc/pull/76) update the component + to be forwards-compatible with zend-servicemanager v3. Several changes were + introduced to support this effort: - 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`. + `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. -- [#38](https://github.com/zendframework/zend-mvc/pull/38) Ensure middleware - tests against abstract factories - - zend-servicemanager v3 modified the behavior of has() to not search abstract - factories by default. You can force it to do so by passing an optional - second argument, a boolean flag, with a value of boolean true. + within separated into discrete factories. ## 2.6.4 - TBD diff --git a/composer.json b/composer.json index 867a79cac..44ef7d9b4 100644 --- a/composer.json +++ b/composer.json @@ -14,33 +14,33 @@ }, "require": { "php": "^5.5 || ^7.0", - "zendframework/zend-eventmanager": "dev-develop as 2.7.0", - "zendframework/zend-servicemanager": "dev-develop as 2.6.0", - "zendframework/zend-hydrator": "~1.0", - "zendframework/zend-form": "~2.6", - "zendframework/zend-stdlib": "^2.7.5", + "zendframework/zend-eventmanager": "^2.6.2 || ^3.0", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-hydrator": "^1.1 || ^2.1", + "zendframework/zend-form": "^2.7", + "zendframework/zend-stdlib": "^2.7.5 || ^3.0", "zendframework/zend-psr7bridge": "^0.2", "container-interop/container-interop": "^1.1" }, "require-dev": { - "zendframework/zend-authentication": "~2.5", - "zendframework/zend-cache": "~2.5", - "zendframework/zend-console": "~2.5", - "zendframework/zend-di": "~2.5", - "zendframework/zend-filter": "~2.5", - "zendframework/zend-http": "~2.5", - "zendframework/zend-i18n": "~2.5", - "zendframework/zend-inputfilter": "~2.5", - "zendframework/zend-json": "~2.5", - "zendframework/zend-log": "~2.5", - "zendframework/zend-modulemanager": "dev-develop as 2.7.0", - "zendframework/zend-session": "~2.5", - "zendframework/zend-serializer": "~2.5", - "zendframework/zend-text": "~2.5", - "zendframework/zend-uri": "~2.5", - "zendframework/zend-validator": "~2.5", - "zendframework/zend-version": "~2.5", - "zendframework/zend-view": "dev-develop as 2.6.0", + "zendframework/zend-authentication": "^2.5.3", + "zendframework/zend-cache": "^2.6.1", + "zendframework/zend-console": "^2.6", + "zendframework/zend-di": "^2.6", + "zendframework/zend-filter": "^2.6.1", + "zendframework/zend-http": "^2.5.4", + "zendframework/zend-i18n": "^2.6", + "zendframework/zend-inputfilter": "^2.6", + "zendframework/zend-json": "^2.6.1", + "zendframework/zend-log": "^2.7.1", + "zendframework/zend-modulemanager": "^2.7.1", + "zendframework/zend-session": "^2.6.2", + "zendframework/zend-serializer": "^2.6.1", + "zendframework/zend-text": "^2.6", + "zendframework/zend-uri": "^2.5", + "zendframework/zend-validator": "^2.6", + "zendframework/zend-version": "^2.5", + "zendframework/zend-view": "^2.6.3", "fabpot/php-cs-fixer": "1.7.*", "phpunit/PHPUnit": "~4.0" }, @@ -64,12 +64,10 @@ "zendframework/zend-version": "Zend\\Version component", "zendframework/zend-view": "Zend\\View component" }, - "minimum-stability": "dev", - "prefer-stable": true, "extra": { "branch-alias": { "dev-master": "2.6-dev", - "dev-develop": "3.0-dev" + "dev-develop": "2.7-dev" } }, "autoload-dev": { diff --git a/src/Application.php b/src/Application.php index 517c7aa7a..07682fbf1 100644 --- a/src/Application.php +++ b/src/Application.php @@ -106,19 +106,22 @@ class Application implements * * @param mixed $configuration * @param ServiceManager $serviceManager + * @param null|EventManagerInterface $events + * @param null|RequestInterface $request + * @param null|ResponseInterface $response */ public function __construct( $configuration, ServiceManager $serviceManager, - EventManagerInterface $events, - RequestInterface $request, - ResponseInterface $response + EventManagerInterface $events = null, + RequestInterface $request = null, + ResponseInterface $response = null ) { $this->configuration = $configuration; $this->serviceManager = $serviceManager; - $this->setEventManager($events); - $this->request = $request; - $this->response = $response; + $this->setEventManager($events ?: $serviceManager->get('EventManager')); + $this->request = $request ?: $serviceManager->get('Request'); + $this->response = $response ?: $serviceManager->get('Response'); } /** @@ -143,8 +146,8 @@ public function getConfig() */ public function bootstrap(array $listeners = []) { - $events = $this->events; $serviceManager = $this->serviceManager; + $events = $this->events; // Setup default listeners $listeners = array_unique(array_merge($this->defaultListeners, $listeners)); @@ -261,20 +264,13 @@ public static function init($configuration = []) $smConfig = isset($configuration['service_manager']) ? $configuration['service_manager'] : []; $smConfig = new Service\ServiceManagerConfig($smConfig); - $serviceManager = new ServiceManager($smConfig->toArray()); - $serviceManager = $serviceManager->withConfig(['services' => [ - 'ApplicationConfig' => $configuration, - ]]); + $serviceManager = new ServiceManager(); + $smConfig->configureServiceManager($serviceManager); + $serviceManager->setService('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'); @@ -319,6 +315,7 @@ public function run() // Trigger route event $event->setName(MvcEvent::EVENT_ROUTE); + $event->stopPropagation(false); // Clear before triggering $result = $events->triggerEventUntil($shortCircuit, $event); if ($result->stopped()) { $response = $result->last(); @@ -326,6 +323,7 @@ public function run() $event->setName(MvcEvent::EVENT_FINISH); $event->setTarget($this); $event->setResponse($response); + $event->stopPropagation(false); // Clear before triggering $events->triggerEvent($event); $this->response = $response; return $this; @@ -338,6 +336,7 @@ public function run() // Trigger dispatch event $event->setName(MvcEvent::EVENT_DISPATCH); + $event->stopPropagation(false); // Clear before triggering $result = $events->triggerEventUntil($shortCircuit, $event); // Complete response @@ -346,6 +345,7 @@ public function run() $event->setName(MvcEvent::EVENT_FINISH); $event->setTarget($this); $event->setResponse($response); + $event->stopPropagation(false); // Clear before triggering $events->triggerEvent($event); $this->response = $response; return $this; @@ -380,9 +380,11 @@ protected function completeRequest(MvcEvent $event) $event->setTarget($this); $event->setName(MvcEvent::EVENT_RENDER); + $event->stopPropagation(false); // Clear before triggering $events->triggerEvent($event); $event->setName(MvcEvent::EVENT_FINISH); + $event->stopPropagation(false); // Clear before triggering $events->triggerEvent($event); return $this; diff --git a/src/Controller/ControllerManager.php b/src/Controller/ControllerManager.php index 57cd64184..a159b5807 100644 --- a/src/Controller/ControllerManager.php +++ b/src/Controller/ControllerManager.php @@ -12,7 +12,10 @@ 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\Exception\InvalidServiceException; use Zend\Stdlib\DispatchableInterface; /** @@ -22,6 +25,18 @@ */ class ControllerManager extends AbstractPluginManager { + /** + * We do not want arbitrary classes instantiated as controllers. + * + * @var bool + */ + protected $autoAddInvokableClass = false; + + /** + * Controllers must be of this type. + * + * @var string + */ protected $instanceOf = DispatchableInterface::class; /** @@ -30,15 +45,51 @@ class ControllerManager extends AbstractPluginManager * Injects an initializer for injecting controllers with an * event manager and plugin manager. * - * @param ContainerInterface $container - * @param array $configuration + * @param ConfigInterface|ContainerInterface $container + * @param array $v3config */ - public function __construct(ContainerInterface $container, array $configuration = []) + public function __construct($configOrContainerInstance, array $v3config = []) { - $this->initializers[] = [$this, 'injectEventManager']; - $this->initializers[] = [$this, 'injectConsole']; - $this->initializers[] = [$this, 'injectPluginManager']; - parent::__construct($container, $configuration); + $this->addInitializer([$this, 'injectEventManager']); + $this->addInitializer([$this, 'injectConsole']); + $this->addInitializer([$this, 'injectPluginManager']); + parent::__construct($configOrContainerInstance, $v3config); + } + + /** + * Validate a plugin (v3) + * + * {@inheritDoc} + */ + public function validate($plugin) + { + if (! $plugin instanceof $this->instanceOf) { + throw new InvalidServiceException(sprintf( + 'Plugin of type "%s" is invalid; must implement %s', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)), + $this->instanceOf + )); + } + } + + /** + * Validate a plugin (v2) + * + * {@inheritDoc} + * + * @throws Exception\InvalidControllerException + */ + public function validatePlugin($plugin) + { + try { + $this->validate($plugin); + } catch (InvalidServiceException $e) { + throw new Exception\InvalidControllerException( + $e->getMessage(), + $e->getCode(), + $e + ); + } } /** @@ -51,17 +102,32 @@ public function __construct(ContainerInterface $container, array $configuration * the shared EM injection needs to happen; the conditional will always * pass. * - * @param ContainerInterface $container - * @param DispatchableInterface $controller + * @param ContainerInterface|DispatchableInterface $first Container when + * using zend-servicemanager v3; controller under v2. + * @param DispatchableInterface|ContainerInterface $second Controller when + * using zend-servicemanager v3; container under v2. */ - public function injectEventManager(ContainerInterface $container, $controller) + public function injectEventManager($first, $second) { + if ($first instanceof ContainerInterface) { + $container = $first; + $controller = $second; + } else { + $container = $second; + $controller = $first; + } + if (! $controller instanceof EventManagerAwareInterface) { return; } $events = $controller->getEventManager(); if (! $events || ! $events->getSharedManager() instanceof SharedEventManagerInterface) { + // For v2, we need to pull the parent service locator + if (! method_exists($container, 'configure')) { + $container = $container->getServiceLocator() ?: $container; + } + $controller->setEventManager($container->get('EventManager')); } } @@ -69,30 +135,60 @@ public function injectEventManager(ContainerInterface $container, $controller) /** * Initializer: inject Console adapter instance * - * @param ContainerInterface $container - * @param DispatchableInterface $controller + * @param ContainerInterface|DispatchableInterface $first Container when + * using zend-servicemanager v3; controller under v2. + * @param DispatchableInterface|ContainerInterface $second Controller when + * using zend-servicemanager v3; container under v2. */ - public function injectConsole(ContainerInterface $container, $controller) + public function injectConsole($first, $second) { + if ($first instanceof ContainerInterface) { + $container = $first; + $controller = $second; + } else { + $container = $second; + $controller = $first; + } + if (! $controller instanceof AbstractConsoleController) { return; } + // For v2, we need to pull the parent service locator + if (! method_exists($container, 'configure')) { + $container = $container->getServiceLocator() ?: $container; + } + $controller->setConsole($container->get('Console')); } /** * Initializer: inject plugin manager * - * @param ContainerInterface $container - * @param DispatchableInterface $controller + * @param ContainerInterface|DispatchableInterface $first Container when + * using zend-servicemanager v3; controller under v2. + * @param DispatchableInterface|ContainerInterface $second Controller when + * using zend-servicemanager v3; container under v2. */ - public function injectPluginManager(ContainerInterface $container, $controller) + public function injectPluginManager($first, $second) { + if ($first instanceof ContainerInterface) { + $container = $first; + $controller = $second; + } else { + $container = $second; + $controller = $first; + } + if (! method_exists($controller, 'setPluginManager')) { return; } + // For v2, we need to pull the parent service locator + if (! method_exists($container, 'configure')) { + $container = $container->getServiceLocator() ?: $container; + } + $controller->setPluginManager($container->get('ControllerPluginManager')); } } diff --git a/src/Controller/Plugin/Forward.php b/src/Controller/Plugin/Forward.php index d26065ec4..8fb87ddfa 100644 --- a/src/Controller/Plugin/Forward.php +++ b/src/Controller/Plugin/Forward.php @@ -177,7 +177,7 @@ protected function detachProblemListeners(SharedEvents $sharedEvents) $results[$id] = []; foreach ($eventArray as $eventName => $classArray) { $results[$id][$eventName] = []; - $events = $sharedEvents->getListeners([$id], $eventName); + $events = $this->getSharedListenersById($id, $eventName, $sharedEvents); foreach ($events as $currentEvent) { $currentCallback = $currentEvent; @@ -255,4 +255,25 @@ protected function getEvent() return $this->event; } + + /** + * Retrieve shared listeners for an event by identifier. + * + * Varies retrieval based on zend-eventmanager version. + * + * @param string|int $id + * @param string $event + * @param SharedEvents $sharedEvents + * @return array|\Traversable + */ + private function getSharedListenersById($id, $event, SharedEvents $sharedEvents) + { + if (method_exists($sharedEvents, 'attachAggregate')) { + // v2 + return $sharedEvents->getListeners($id, $event) ?: []; + } + + // v3 + return $sharedEvents->getListeners([$id], $event); + } } diff --git a/src/Controller/Plugin/Service/ForwardFactory.php b/src/Controller/Plugin/Service/ForwardFactory.php index 89076fe5c..405e29eda 100644 --- a/src/Controller/Plugin/Service/ForwardFactory.php +++ b/src/Controller/Plugin/Service/ForwardFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\Mvc\Controller\Plugin\Forward; class ForwardFactory implements FactoryInterface @@ -35,4 +36,18 @@ public function __invoke(ContainerInterface $container, $name, array $options = return new Forward($controllers); } + + /** + * Create and return Forward instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return Forward + */ + public function createService(ServiceLocatorInterface $container) + { + $parentContainer = $container->getServiceLocator() ?: $container; + return $this($parentContainer, Forward::class); + } } diff --git a/src/Controller/Plugin/Service/IdentityFactory.php b/src/Controller/Plugin/Service/IdentityFactory.php index dc3b7acfb..41fb3467e 100644 --- a/src/Controller/Plugin/Service/IdentityFactory.php +++ b/src/Controller/Plugin/Service/IdentityFactory.php @@ -12,14 +12,15 @@ use Interop\Container\ContainerInterface; use Zend\Authentication\AuthenticationService; use Zend\Mvc\Controller\Plugin\Identity; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class IdentityFactory implements FactoryInterface { /** * {@inheritDoc} * - * @return \Zend\Mvc\Controller\Plugin\Identity + * @return Identity */ public function __invoke(ContainerInterface $container, $name, array $options = null) { @@ -29,4 +30,22 @@ public function __invoke(ContainerInterface $container, $name, array $options = } return $helper; } + + /** + * Create and return Identity instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return Identity + */ + public function createService(ServiceLocatorInterface $container) + { + // Retrieve the parent container when under zend-servicemanager v2 + if (! method_exists($container, 'configure')) { + $container = $container->getServiceLocator() ?: $container; + } + + return $this($container, Identity::class); + } } diff --git a/src/Controller/PluginManager.php b/src/Controller/PluginManager.php index bca5687a8..e2cb53cea 100644 --- a/src/Controller/PluginManager.php +++ b/src/Controller/PluginManager.php @@ -9,7 +9,9 @@ namespace Zend\Mvc\Controller; +use Zend\Mvc\Exception; use Zend\ServiceManager\AbstractPluginManager; +use Zend\ServiceManager\Exception\InvalidServiceException; use Zend\ServiceManager\Factory\InvokableFactory; use Zend\Stdlib\DispatchableInterface; @@ -21,6 +23,11 @@ */ class PluginManager extends AbstractPluginManager { + /** + * Plugins must be of this type. + * + * @var string + */ protected $instanceOf = Plugin\PluginInterface::class; /** @@ -77,6 +84,21 @@ class PluginManager extends AbstractPluginManager Plugin\Url::class => InvokableFactory::class, Plugin\CreateHttpNotFoundModel::class => InvokableFactory::class, Plugin\CreateConsoleNotFoundModel::class => InvokableFactory::class, + + // v2 normalized names + + 'zendmvccontrollerpluginforward' => Plugin\Service\ForwardFactory::class, + 'zendmvccontrollerpluginidentity' => Plugin\Service\IdentityFactory::class, + 'zendmvccontrollerpluginacceptableviewmodelselector' => InvokableFactory::class, + 'zendmvccontrollerpluginfilepostredirectget' => InvokableFactory::class, + 'zendmvccontrollerpluginflashmessenger' => InvokableFactory::class, + 'zendmvccontrollerpluginlayout' => InvokableFactory::class, + 'zendmvccontrollerpluginparams' => InvokableFactory::class, + 'zendmvccontrollerpluginpostredirectget' => InvokableFactory::class, + 'zendmvccontrollerpluginredirect' => InvokableFactory::class, + 'zendmvccontrollerpluginurl' => InvokableFactory::class, + 'zendmvccontrollerplugincreatehttpnotfoundmodel' => InvokableFactory::class, + 'zendmvccontrollerplugincreateconsolenotfoundmodel' => InvokableFactory::class, ]; /** @@ -150,4 +172,40 @@ public function injectController($plugin) $plugin->setController($controller); } + + /** + * Validate a plugin (v3) + * + * {@inheritDoc} + */ + public function validate($plugin) + { + if (! $plugin instanceof $this->instanceOf) { + throw new InvalidServiceException(sprintf( + 'Plugin of type "%s" is invalid; must implement %s', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)), + $this->instanceOf + )); + } + } + + /** + * Validate a plugin (v2) + * + * {@inheritDoc} + * + * @throws Exception\InvalidPluginException + */ + public function validatePlugin($plugin) + { + try { + $this->validate($plugin); + } catch (InvalidServiceException $e) { + throw new Exception\InvalidPluginException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + } } diff --git a/src/DispatchListener.php b/src/DispatchListener.php index bba9ff555..ca97412c3 100644 --- a/src/DispatchListener.php +++ b/src/DispatchListener.php @@ -85,13 +85,16 @@ public function onDispatch(MvcEvent $e) // Query abstract controllers, too! - if (! $controllerManager->has($controllerName, true)) { + if (! $controllerManager->has($controllerName)) { $return = $this->marshalControllerNotFoundEvent($application::ERROR_CONTROLLER_NOT_FOUND, $controllerName, $e, $application); return $this->complete($return, $e); } try { $controller = $controllerManager->get($controllerName); + } catch (Exception\InvalidControllerException $exception) { + $return = $this->marshalControllerNotFoundEvent($application::ERROR_CONTROLLER_INVALID, $controllerName, $e, $application, $exception); + return $this->complete($return, $e); } catch (InvalidServiceException $exception) { $return = $this->marshalControllerNotFoundEvent($application::ERROR_CONTROLLER_INVALID, $controllerName, $e, $application, $exception); return $this->complete($return, $e); diff --git a/src/Exception/InvalidControllerException.php b/src/Exception/InvalidControllerException.php new file mode 100644 index 000000000..166f1fcdb --- /dev/null +++ b/src/Exception/InvalidControllerException.php @@ -0,0 +1,14 @@ +getServiceManager(); $middlewareName = is_string($middleware) ? $middleware : get_class($middleware); - if (is_string($middleware) && $serviceManager->has($middleware, true)) { + if (is_string($middleware) && $serviceManager->has($middleware)) { $middleware = $serviceManager->get($middleware); } if (! is_callable($middleware)) { diff --git a/src/Router/Console/SimpleRouteStack.php b/src/Router/Console/SimpleRouteStack.php index 21c144503..ae7db35d2 100644 --- a/src/Router/Console/SimpleRouteStack.php +++ b/src/Router/Console/SimpleRouteStack.php @@ -11,7 +11,9 @@ use Traversable; use Zend\Mvc\Router\Exception; +use Zend\Mvc\Router\RouteInvokableFactory; use Zend\Mvc\Router\SimpleRouteStack as BaseSimpleRouteStack; +use Zend\ServiceManager\Config; use Zend\Stdlib\ArrayUtils; /** @@ -26,11 +28,24 @@ class SimpleRouteStack extends BaseSimpleRouteStack */ protected function init() { - $routes = $this->routePluginManager; - $this->routePluginManager = $routes->withConfig(['invokables' => [ - 'catchall' => __NAMESPACE__ . '\Catchall', - 'simple' => __NAMESPACE__ . '\Simple', - ]]); + (new Config([ + 'aliases' => [ + 'catchall' => Catchall::class, + 'catchAll' => Catchall::class, + 'Catchall' => Catchall::class, + 'CatchAll' => Catchall::class, + 'simple' => Simple::class, + 'Simple' => Simple::class, + ], + 'factories' => [ + Catchall::class => RouteInvokableFactory::class, + Simple::class => RouteInvokableFactory::class, + + // v2 normalized names + 'zendmvcrouterconsoleCatchall' => RouteInvokableFactory::class, + 'zendmvcrouterconsoleSimple' => RouteInvokableFactory::class, + ], + ]))->configureServiceManager($this->routePluginManager); } /** diff --git a/src/Router/Http/TreeRouteStack.php b/src/Router/Http/TreeRouteStack.php index 7581d40d6..373953c4d 100644 --- a/src/Router/Http/TreeRouteStack.php +++ b/src/Router/Http/TreeRouteStack.php @@ -12,7 +12,9 @@ use ArrayObject; use Traversable; use Zend\Mvc\Router\Exception; +use Zend\Mvc\Router\RouteInvokableFactory; use Zend\Mvc\Router\SimpleRouteStack; +use Zend\ServiceManager\Config; use Zend\Stdlib\ArrayUtils; use Zend\Stdlib\RequestInterface as Request; use Zend\Uri\Http as HttpUri; @@ -58,7 +60,9 @@ public static function factory($options = []) { if ($options instanceof Traversable) { $options = ArrayUtils::iteratorToArray($options); - } elseif (!is_array($options)) { + } + + if (! is_array($options)) { throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable set of options'); } @@ -80,33 +84,59 @@ protected function init() { $this->prototypes = new ArrayObject; - $routes = $this->routePluginManager; - $this->routePluginManager = $routes->withConfig([ + (new Config([ 'aliases' => [ - 'Chain' => 'chain', - 'Hostname' => 'hostname', - 'Literal' => 'literal', - 'Method' => 'method', - 'Part' => 'part', - 'Query' => 'query', - 'Regex' => 'regex', - 'Scheme' => 'scheme', - 'Segment' => 'segment', - 'Wildcard' => 'wildcard', + 'chain' => Chain::class, + 'Chain' => Chain::class, + 'hostname' => Hostname::class, + 'Hostname' => Hostname::class, + 'hostName' => Hostname::class, + 'HostName' => Hostname::class, + 'literal' => Literal::class, + 'Literal' => Literal::class, + 'method' => Method::class, + 'Method' => Method::class, + 'part' => Part::class, + 'Part' => Part::class, + 'query' => Query::class, + 'Query' => Query::class, + 'regex' => Regex::class, + 'Regex' => Regex::class, + 'scheme' => Scheme::class, + 'Scheme' => Scheme::class, + 'segment' => Segment::class, + 'Segment' => Segment::class, + 'wildcard' => Wildcard::class, + 'Wildcard' => Wildcard::class, + 'wildCard' => Wildcard::class, + 'WildCard' => Wildcard::class, ], - 'invokables' => [ - 'chain' => __NAMESPACE__ . '\Chain', - 'hostname' => __NAMESPACE__ . '\Hostname', - 'literal' => __NAMESPACE__ . '\Literal', - 'method' => __NAMESPACE__ . '\Method', - 'part' => __NAMESPACE__ . '\Part', - 'query' => __NAMESPACE__ . '\Query', - 'regex' => __NAMESPACE__ . '\Regex', - 'scheme' => __NAMESPACE__ . '\Scheme', - 'segment' => __NAMESPACE__ . '\Segment', - 'wildcard' => __NAMESPACE__ . '\Wildcard', + 'factories' => [ + Chain::class => RouteInvokableFactory::class, + Hostname::class => RouteInvokableFactory::class, + Literal::class => RouteInvokableFactory::class, + Method::class => RouteInvokableFactory::class, + Part::class => RouteInvokableFactory::class, + Query::class => RouteInvokableFactory::class, + Regex::class => RouteInvokableFactory::class, + Scheme::class => RouteInvokableFactory::class, + Segment::class => RouteInvokableFactory::class, + Wildcard::class => RouteInvokableFactory::class, + + // v2 normalized names + + 'zendmvcrouterhttpchain' => RouteInvokableFactory::class, + 'zendmvcrouterhttphostname' => RouteInvokableFactory::class, + 'zendmvcrouterhttpliteral' => RouteInvokableFactory::class, + 'zendmvcrouterhttpmethod' => RouteInvokableFactory::class, + 'zendmvcrouterhttppart' => RouteInvokableFactory::class, + 'zendmvcrouterhttpquery' => RouteInvokableFactory::class, + 'zendmvcrouterhttpregex' => RouteInvokableFactory::class, + 'zendmvcrouterhttpscheme' => RouteInvokableFactory::class, + 'zendmvcrouterhttpsegment' => RouteInvokableFactory::class, + 'zendmvcrouterhttpwildcard' => RouteInvokableFactory::class, ], - ]); + ]))->configureServiceManager($this->routePluginManager); } /** diff --git a/src/Router/RouteInvokableFactory.php b/src/Router/RouteInvokableFactory.php index 11c477882..c17e33cac 100644 --- a/src/Router/RouteInvokableFactory.php +++ b/src/Router/RouteInvokableFactory.php @@ -11,7 +11,9 @@ use Interop\Container\ContainerInterface; use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\ServiceManager\Factory\AbstractFactoryInterface; +use Zend\ServiceManager\AbstractFactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; /** * Specialized invokable/abstract factory for use with RoutePluginManager. @@ -19,10 +21,19 @@ * Can be mapped directly to specific route plugin names, or used as an * abstract factory to map FQCN services to invokables. */ -class RouteInvokableFactory implements AbstractFactoryInterface +class RouteInvokableFactory implements + AbstractFactoryInterface, + FactoryInterface { /** - * Can we create a route instance with the given name? + * Options used to create instance (used with zend-servicemanager v2) + * + * @var array + */ + protected $creationOptions = []; + + /** + * Can we create a route instance with the given name? (v3) * * Only works for FQCN $routeName values, for classes that implement RouteInterface. * @@ -30,7 +41,7 @@ class RouteInvokableFactory implements AbstractFactoryInterface * @param string $routeName * @return bool */ - public function canCreateServiceWithName(ContainerInterface $container, $routeName) + public function canCreate(ContainerInterface $container, $routeName) { if (! class_exists($routeName)) { return false; @@ -43,6 +54,21 @@ public function canCreateServiceWithName(ContainerInterface $container, $routeNa return true; } + /** + * Can we create a route instance with the given name? (v2) + * + * Proxies to canCreate(). + * + * @param ServiceLocatorInterface $container + * @param string $normalizedName + * @param string $routeName + * @return bool + */ + public function canCreateServiceWithName(ServiceLocatorInterface $container, $normalizedName, $routeName) + { + return $this->canCreate($container, $routeName); + } + /** * Create and return a RouteInterface instance. * @@ -80,4 +106,43 @@ public function __invoke(ContainerInterface $container, $routeName, array $optio return $routeName::factory($options); } + + /** + * Create a route instance with the given name. (v2) + * + * Proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @param string $normalizedName + * @param string $routeName + * @return RouteInterface + */ + public function createServiceWithName(ServiceLocatorInterface $container, $normalizedName, $routeName) + { + return $this($container, $routeName, $this->creationOptions); + } + + /** + * Create and return RouteInterface instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return RouteInterface + */ + public function createService(ServiceLocatorInterface $container, $normalizedName = null, $routeName = null) + { + $routeName = $routeName ?: RouteInterface::class; + return $this($container, $routeName, $this->creationOptions); + } + + /** + * Set options to use when creating a service (v2) + * + * @param array $creationOptions + */ + public function setCreationOptions(array $creationOptions) + { + $this->creationOptions = $creationOptions; + } } diff --git a/src/Router/RoutePluginManager.php b/src/Router/RoutePluginManager.php index b58e0f4c1..65cfa1beb 100644 --- a/src/Router/RoutePluginManager.php +++ b/src/Router/RoutePluginManager.php @@ -11,7 +11,7 @@ use Interop\Container\ContainerInterface; use Zend\ServiceManager\AbstractPluginManager; -use Zend\Stdlib\ArrayUtils; +use Zend\ServiceManager\Exception\InvalidServiceException; /** * Plugin manager implementation for routes @@ -33,32 +33,72 @@ class RoutePluginManager extends AbstractPluginManager protected $instanceOf = RouteInterface::class; /** - * Do not share instances. + * Do not share instances. (v3) * * @var bool */ protected $shareByDefault = false; + /** + * Do not share instances. (v2) + * + * @var bool + */ + protected $sharedByDefault = false; + /** * Constructor * * Ensure that the instance is seeded with the RouteInvokableFactory as an * abstract factory. * - * @param ContainerInterface $container - * @param array $config + * @param ContainerInterface|\Zend\ServiceManager\ConfigInterface $configOrContainerInstance + * @param array $v3config */ - public function __construct(ContainerInterface $container, array $config = []) + public function __construct($configOrContainerInstance, array $v3config = []) { - $config = ArrayUtils::merge(['abstract_factories' => [ - RouteInvokableFactory::class, - ]], $config); + $this->addAbstractFactory(RouteInvokableFactory::class); + parent::__construct($configOrContainerInstance, $v3config); + } - parent::__construct($container, $config); + /** + * Validate a route plugin. (v2) + * + * @param object $plugin + * @throws InvalidServiceException + */ + public function validate($plugin) + { + if (! $plugin instanceof $this->instanceOf) { + throw new InvalidServiceException(sprintf( + 'Plugin of type %s is invalid; must implement %s', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)), + RouteInterface::class + )); + } + } + + /** + * Validate a route plugin. (v2) + * + * @param object $plugin + * @throws Exception\RuntimeException + */ + public function validatePlugin($plugin) + { + try { + $this->validate($plugin); + } catch (InvalidServiceException $e) { + throw new Exception\RuntimeException( + $e->getMessage(), + $e->getCode(), + $e + ); + } } /** - * Pre-process configuration. + * Pre-process configuration. (v3) * * Checks for invokables, and, if found, maps them to the * component-specific RouteInvokableFactory; removes the invokables entry @@ -67,7 +107,7 @@ public function __construct(ContainerInterface $container, array $config = []) * @param array $config * @return void */ - protected function configure(array $config) + public function configure(array $config) { if (isset($config['invokables']) && ! empty($config['invokables'])) { $aliases = $this->createAliasesForInvokables($config['invokables']); diff --git a/src/Router/SimpleRouteStack.php b/src/Router/SimpleRouteStack.php index a89dbde33..911d906ab 100644 --- a/src/Router/SimpleRouteStack.php +++ b/src/Router/SimpleRouteStack.php @@ -262,13 +262,17 @@ protected function routeFromArray($specs) { if ($specs instanceof Traversable) { $specs = ArrayUtils::iteratorToArray($specs); - } elseif (!is_array($specs)) { + } + + if (! is_array($specs)) { throw new Exception\InvalidArgumentException('Route definition must be an array or Traversable object'); } - if (!isset($specs['type'])) { + if (! isset($specs['type'])) { throw new Exception\InvalidArgumentException('Missing "type" option'); - } elseif (!isset($specs['options'])) { + } + + if (! isset($specs['options'])) { $specs['options'] = []; } diff --git a/src/Service/AbstractPluginManagerFactory.php b/src/Service/AbstractPluginManagerFactory.php index 11995a97b..2875c2bc4 100644 --- a/src/Service/AbstractPluginManagerFactory.php +++ b/src/Service/AbstractPluginManagerFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\ServiceManager\AbstractPluginManager; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; abstract class AbstractPluginManagerFactory implements FactoryInterface { @@ -34,4 +35,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = $pluginManagerClass = static::PLUGIN_MANAGER_CLASS; return new $pluginManagerClass($container, $options); } + + /** + * Create and return AbstractPluginManager instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return AbstractPluginManager + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, AbstractPluginManager::class); + } } diff --git a/src/Service/ApplicationFactory.php b/src/Service/ApplicationFactory.php index a87edb4c8..f8e5d9f81 100644 --- a/src/Service/ApplicationFactory.php +++ b/src/Service/ApplicationFactory.php @@ -11,12 +11,13 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\Application; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class ApplicationFactory implements FactoryInterface { /** - * Create the Application service + * Create the Application service (v3) * * Creates a Zend\Mvc\Application service, passing it the configuration * service and the service manager instance. @@ -36,4 +37,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = $container->get('Response') ); } + + /** + * Create the Application service (v2) + * + * Proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return Application + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, Application::class); + } } diff --git a/src/Service/ConfigFactory.php b/src/Service/ConfigFactory.php new file mode 100644 index 000000000..6fc33e1f1 --- /dev/null +++ b/src/Service/ConfigFactory.php @@ -0,0 +1,52 @@ +get('ModuleManager'); + $moduleManager->loadModules(); + $moduleParams = $moduleManager->getEvent()->getParams(); + return $moduleParams['configListener']->getMergedConfig(false); + } + + /** + * Create and return config instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return array|\Traversable + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, 'config'); + } +} diff --git a/src/Service/ConsoleAdapterFactory.php b/src/Service/ConsoleAdapterFactory.php index bd4ea3ee8..6172b4489 100644 --- a/src/Service/ConsoleAdapterFactory.php +++ b/src/Service/ConsoleAdapterFactory.php @@ -13,7 +13,8 @@ use stdClass; use Zend\Console\Adapter\AdapterInterface; use Zend\Console\Console; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class ConsoleAdapterFactory implements FactoryInterface { @@ -74,4 +75,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $adapter; } + + /** + * Create and return AdapterInterface instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return AdapterInterface|stdClass + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, AdapterInterface::class); + } } diff --git a/src/Service/ConsoleExceptionStrategyFactory.php b/src/Service/ConsoleExceptionStrategyFactory.php index e56ab73dc..10c06deff 100644 --- a/src/Service/ConsoleExceptionStrategyFactory.php +++ b/src/Service/ConsoleExceptionStrategyFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\View\Console\ExceptionStrategy; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class ConsoleExceptionStrategyFactory implements FactoryInterface { @@ -34,6 +35,19 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $strategy; } + /** + * Create and return ExceptionStrategy instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return ExceptionStrategy + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, ExceptionStrategy::class); + } + /** * Inject strategy with configured display_exceptions flag. * diff --git a/src/Service/ConsoleRouteNotFoundStrategyFactory.php b/src/Service/ConsoleRouteNotFoundStrategyFactory.php index 43bc723e4..628ae966c 100644 --- a/src/Service/ConsoleRouteNotFoundStrategyFactory.php +++ b/src/Service/ConsoleRouteNotFoundStrategyFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\View\Console\RouteNotFoundStrategy; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class ConsoleRouteNotFoundStrategyFactory implements FactoryInterface { @@ -33,6 +34,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $strategy; } + /** + * Create and return RouteNotFoundStrategy instance + * + * @param ServiceLocatorInterface $container + * @return RouteNotFoundStrategy + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, RouteNotFoundStrategy::class); + } + /** * Inject strategy with configured display_not_found_reason flag. * diff --git a/src/Service/ConsoleRouterFactory.php b/src/Service/ConsoleRouterFactory.php index 2d75e8cc0..dc18deb3b 100644 --- a/src/Service/ConsoleRouterFactory.php +++ b/src/Service/ConsoleRouterFactory.php @@ -11,7 +11,9 @@ use Interop\Container\ContainerInterface; use Zend\Console\Console; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\Mvc\Router\RouteStackInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class ConsoleRouterFactory implements FactoryInterface { @@ -23,7 +25,7 @@ class ConsoleRouterFactory implements FactoryInterface * @param ContainerInterface $container * @param string $name * @param null|array $options - * @return \Zend\Mvc\Router\RouteStackInterface + * @return RouteStackInterface */ public function __invoke(ContainerInterface $container, $name, array $options = null) { @@ -35,4 +37,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $this->createRouter($class, $config, $container); } + + /** + * Create and return RouteStackInterface instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return RouteStackInterface + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, RouteStackInterface::class); + } } diff --git a/src/Service/ConsoleViewManagerFactory.php b/src/Service/ConsoleViewManagerFactory.php index 79cf6f21f..7a725f48d 100644 --- a/src/Service/ConsoleViewManagerFactory.php +++ b/src/Service/ConsoleViewManagerFactory.php @@ -12,7 +12,8 @@ use Interop\Container\ContainerInterface; use Zend\Console\Console; use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\Mvc\View\Console\ViewManager as ConsoleViewManager; class ConsoleViewManagerFactory implements FactoryInterface @@ -35,4 +36,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return new ConsoleViewManager(); } + + /** + * Create and return ConsoleViewManager instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return ConsoleViewManager + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, ConsoleViewManager::class); + } } diff --git a/src/Service/ControllerLoaderFactory.php b/src/Service/ControllerLoaderFactory.php new file mode 100644 index 000000000..cf5cda2d0 --- /dev/null +++ b/src/Service/ControllerLoaderFactory.php @@ -0,0 +1,48 @@ +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 index 69ad463ac..c0d8d650f 100644 --- a/src/Service/ControllerManagerFactory.php +++ b/src/Service/ControllerManagerFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\Controller\ControllerManager; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class ControllerManagerFactory implements FactoryInterface { @@ -37,4 +38,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = } return new ControllerManager($container); } + + /** + * Create and return ControllerManager instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return ControllerManager + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, ControllerManager::class); + } } diff --git a/src/Service/DiAbstractServiceFactoryFactory.php b/src/Service/DiAbstractServiceFactoryFactory.php new file mode 100644 index 000000000..da508f8af --- /dev/null +++ b/src/Service/DiAbstractServiceFactoryFactory.php @@ -0,0 +1,51 @@ +get('Di'), DiAbstractServiceFactory::USE_SL_BEFORE_DI); + + if ($serviceLocator instanceof ServiceManager) { + $serviceLocator->addAbstractFactory($factory, false); + } + + return $factory; + } + + /** + * Create and return DiAbstractServiceFactory instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return DiAbstractServiceFactory + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, DiAbstractServiceFactory::class); + } +} diff --git a/src/Service/DiFactory.php b/src/Service/DiFactory.php new file mode 100644 index 000000000..24ebd3137 --- /dev/null +++ b/src/Service/DiFactory.php @@ -0,0 +1,60 @@ +get('config'); + + if (isset($config['di'])) { + $config = new Config($config['di']); + $config->configure($di); + } + + return $di; + } + + /** + * Create and return Di instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return Di + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, Di::class); + } +} diff --git a/src/Service/DiServiceInitializerFactory.php b/src/Service/DiServiceInitializerFactory.php new file mode 100644 index 000000000..20afd2926 --- /dev/null +++ b/src/Service/DiServiceInitializerFactory.php @@ -0,0 +1,44 @@ +get('Di'), $container); + } + + /** + * Create and return DiServiceInitializer instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return DiServiceInitializer + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, DiServiceInitializer::class); + } +} diff --git a/src/Service/DiStrictAbstractServiceFactory.php b/src/Service/DiStrictAbstractServiceFactory.php new file mode 100644 index 000000000..9587f6a5d --- /dev/null +++ b/src/Service/DiStrictAbstractServiceFactory.php @@ -0,0 +1,162 @@ +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 __invoke(ContainerInterface $container, $name, array $options = null) + { + if (!isset($this->allowedServiceNames[$name])) { + throw new Exception\InvalidServiceException('Service "' . $name . '" is not whitelisted'); + } + + if ($container instanceof AbstractPluginManager) { + $this->serviceLocator = $container->getServiceLocator(); + } else { + $this->serviceLocator = $container; + } + + return parent::get($name); + } + + /** + * {@inheritDoc} + * + * For use with zend-servicemanager v2; proxies to __invoke(). + */ + public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $serviceName, $requestedName) + { + return $this($serviceLocator, $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 canCreate(ContainerInterface $container, $requestedName) + { + // won't check if the service exists, we are trusting the user's whitelist + return isset($this->allowedServiceNames[$requestedName]); + } + + /** + * {@inheritDoc} + * + * For use with zend-servicemanager v2; proxies to canCreate(). + */ + public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName) + { + return $this->canCreate($serviceLocator, $requestedName); + } +} diff --git a/src/Service/DiStrictAbstractServiceFactoryFactory.php b/src/Service/DiStrictAbstractServiceFactoryFactory.php new file mode 100644 index 000000000..2d9424204 --- /dev/null +++ b/src/Service/DiStrictAbstractServiceFactoryFactory.php @@ -0,0 +1,53 @@ +get('Di'), + DiStrictAbstractServiceFactory::USE_SL_BEFORE_DI + ); + $config = $container->get('config'); + + if (isset($config['di']['allowed_controllers'])) { + $diAbstractFactory->setAllowedServiceNames($config['di']['allowed_controllers']); + } + + return $diAbstractFactory; + } + + /** + * Create and return DiStrictAbstractServiceFactory instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return DiStrictAbstractServiceFactory + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, DiStrictAbstractServiceFactory::class); + } +} diff --git a/src/Service/DispatchListenerFactory.php b/src/Service/DispatchListenerFactory.php index 75c375f7e..7c9515718 100644 --- a/src/Service/DispatchListenerFactory.php +++ b/src/Service/DispatchListenerFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\DispatchListener; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class DispatchListenerFactory implements FactoryInterface { @@ -27,4 +28,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = { return new DispatchListener($container->get('ControllerManager')); } + + /** + * Create and return DispatchListener instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return DispatchListener + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, DispatchListener::class); + } } diff --git a/src/Service/EventManagerFactory.php b/src/Service/EventManagerFactory.php index 0f4352afe..57d39bbff 100644 --- a/src/Service/EventManagerFactory.php +++ b/src/Service/EventManagerFactory.php @@ -10,8 +10,10 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; +use ReflectionClass; use Zend\EventManager\EventManager; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class EventManagerFactory implements FactoryInterface { @@ -28,9 +30,48 @@ class EventManagerFactory implements FactoryInterface */ public function __invoke(ContainerInterface $container, $name, array $options = null) { + if ($this->acceptsSharedManagerToConstructor()) { + // zend-eventmanager v3 + return new EventManager( + $container->has('SharedEventManager') ? $container->get('SharedEventManager') : null + ); + } + + // zend-eventmanager v2 + $events = new EventManager(); + if ($container->has('SharedEventManager')) { - return new EventManager($container->get('SharedEventManager')); + $events->setSharedManager($container->get('SharedEventManager')); } - return new EventManager(); + + return $events; + } + + /** + * Create and return EventManager instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return EventManager + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, EventManager::class); + } + + /** + * Does the EventManager accept the shared manager to the constructor? + * + * In zend-eventmanager v3, the EventManager accepts the shared manager + * instance to the constructor *only*, while in v2, it must be injected + * via the setSharedManager() method. + * + * @return bool + */ + private function acceptsSharedManagerToConstructor() + { + $r = new ReflectionClass(EventManager::class); + return ! $r->hasMethod('setSharedManager'); } } diff --git a/src/Service/FormAnnotationBuilderFactory.php b/src/Service/FormAnnotationBuilderFactory.php index 90d7a0db9..d37ce2d5e 100644 --- a/src/Service/FormAnnotationBuilderFactory.php +++ b/src/Service/FormAnnotationBuilderFactory.php @@ -13,7 +13,8 @@ use Zend\EventManager\ListenerAggregateInterface; use Zend\Form\Annotation\AnnotationBuilder; use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class FormAnnotationBuilderFactory implements FactoryInterface { @@ -23,7 +24,7 @@ class FormAnnotationBuilderFactory implements FactoryInterface * @param ContainerInterface $container * @param string $name * @param null|array $options - * @return mixed + * @return AnnotationBuilder * @throws ServiceNotCreatedException for invalid listener configuration. */ public function __invoke(ContainerInterface $container, $name, array $options = null) @@ -63,4 +64,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $annotationBuilder; } + + /** + * Create and return AnnotationBuilder instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return AnnotationBuilder + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, AnnotationBuilder::class); + } } diff --git a/src/Service/HttpDefaultRenderingStrategyFactory.php b/src/Service/HttpDefaultRenderingStrategyFactory.php index 19a7f5a6d..329cd0407 100644 --- a/src/Service/HttpDefaultRenderingStrategyFactory.php +++ b/src/Service/HttpDefaultRenderingStrategyFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\View\Http\DefaultRenderingStrategy; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\View; class HttpDefaultRenderingStrategyFactory implements FactoryInterface @@ -34,6 +35,27 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $strategy; } + /** + * Create and return DefaultRendererStrategy instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return DefaultRendererStrategy + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, DefaultRendererStrategy::class); + } + + /** + * Inject layout template. + * + * Uses layout template from configuration; if none available, defaults to "layout/layout". + * + * @param DefaultRendererStrategy $strategy + * @param array $config + */ private function injectLayoutTemplate(DefaultRenderingStrategy $strategy, array $config) { $layout = isset($config['layout']) ? $config['layout'] : 'layout/layout'; diff --git a/src/Service/HttpExceptionStrategyFactory.php b/src/Service/HttpExceptionStrategyFactory.php index 51555f436..9a94bd9e7 100644 --- a/src/Service/HttpExceptionStrategyFactory.php +++ b/src/Service/HttpExceptionStrategyFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\View\Http\ExceptionStrategy; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class HttpExceptionStrategyFactory implements FactoryInterface { @@ -34,6 +35,19 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $strategy; } + /** + * Create and return ExceptionStrategy instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return ExceptionStrategy + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, ExceptionStrategy::class); + } + /** * Inject strategy with configured display_exceptions flag. * diff --git a/src/Service/HttpMethodListenerFactory.php b/src/Service/HttpMethodListenerFactory.php index d4c83f3dc..1ef58bff5 100644 --- a/src/Service/HttpMethodListenerFactory.php +++ b/src/Service/HttpMethodListenerFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\HttpMethodListener; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class HttpMethodListenerFactory implements FactoryInterface { @@ -37,4 +38,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return new HttpMethodListener($enabled, $allowedMethods); } + + /** + * Create and return HttpMethodListener instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return HttpMethodListener + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, HttpMethodListener::class); + } } diff --git a/src/Service/HttpRouteNotFoundStrategyFactory.php b/src/Service/HttpRouteNotFoundStrategyFactory.php index afb5b9d8a..a8d32941a 100644 --- a/src/Service/HttpRouteNotFoundStrategyFactory.php +++ b/src/Service/HttpRouteNotFoundStrategyFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\View\Http\RouteNotFoundStrategy; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class HttpRouteNotFoundStrategyFactory implements FactoryInterface { @@ -35,6 +36,19 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $strategy; } + /** + * Create and return RouteNotFoundStrategy instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return RouteNotFoundStrategy + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, RouteNotFoundStrategy::class); + } + /** * Inject strategy with configured display_exceptions flag. * diff --git a/src/Service/HttpRouterFactory.php b/src/Service/HttpRouterFactory.php index c2f288794..074bfee1c 100644 --- a/src/Service/HttpRouterFactory.php +++ b/src/Service/HttpRouterFactory.php @@ -10,7 +10,9 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\Mvc\Router\RouteStackInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class HttpRouterFactory implements FactoryInterface { @@ -26,7 +28,7 @@ class HttpRouterFactory implements FactoryInterface * @param ContainerInterface $container * @param string $name * @param null|array $options - * @return \Zend\Mvc\Router\RouteStackInterface + * @return RouteStackInterface */ public function __invoke(ContainerInterface $container, $name, array $options = null) { @@ -38,4 +40,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $this->createRouter($class, $config, $container); } + + /** + * Create and return RouteStackInterface instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return RouteStackInterface + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, RouteStackInterface::class); + } } diff --git a/src/Service/HttpViewManagerFactory.php b/src/Service/HttpViewManagerFactory.php index 8c68e726b..b439ba000 100644 --- a/src/Service/HttpViewManagerFactory.php +++ b/src/Service/HttpViewManagerFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\View\Http\ViewManager as HttpViewManager; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class HttpViewManagerFactory implements FactoryInterface { @@ -27,4 +28,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = { return new HttpViewManager(); } + + /** + * Create and return HttpViewManager instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return HttpViewManager + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, HttpViewManager::class); + } } diff --git a/src/Service/InjectTemplateListenerFactory.php b/src/Service/InjectTemplateListenerFactory.php index ef9ab8bd0..0e059b920 100644 --- a/src/Service/InjectTemplateListenerFactory.php +++ b/src/Service/InjectTemplateListenerFactory.php @@ -11,7 +11,8 @@ use Interop\Container\ContainerInterface; use Zend\Mvc\View\Http\InjectTemplateListener; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class InjectTemplateListenerFactory implements FactoryInterface { @@ -35,4 +36,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $listener; } + + /** + * Create and return InjectTemplateListener instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return InjectTemplateListener + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, InjectTemplateListener::class); + } } diff --git a/src/Service/ModuleManagerFactory.php b/src/Service/ModuleManagerFactory.php index a295bdd88..34e19abaf 100644 --- a/src/Service/ModuleManagerFactory.php +++ b/src/Service/ModuleManagerFactory.php @@ -14,7 +14,8 @@ use Zend\ModuleManager\Listener\ListenerOptions; use Zend\ModuleManager\ModuleEvent; use Zend\ModuleManager\ModuleManager; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class ModuleManagerFactory implements FactoryInterface { @@ -41,7 +42,8 @@ public function __invoke(ContainerInterface $container, $name, array $options = $defaultListeners = new DefaultListenerAggregate($listenerOptions); $serviceListener = $container->get('ServiceListener'); - $serviceListener->setApplicationServiceManager( + $serviceListener->addServiceManager( + $container, 'service_manager', 'Zend\ModuleManager\Feature\ServiceProviderInterface', 'getServiceConfig' @@ -138,4 +140,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $moduleManager; } + + /** + * Create and return ModuleManager instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return ModuleManager + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, ModuleManager::class); + } } diff --git a/src/Service/RequestFactory.php b/src/Service/RequestFactory.php index 88a0a5a4c..04f2b750f 100644 --- a/src/Service/RequestFactory.php +++ b/src/Service/RequestFactory.php @@ -13,7 +13,8 @@ use Zend\Console\Console; use Zend\Console\Request as ConsoleRequest; use Zend\Http\PhpEnvironment\Request as HttpRequest; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class RequestFactory implements FactoryInterface { @@ -33,4 +34,18 @@ public function __invoke(ContainerInterface $container, $name, array $options = return new HttpRequest(); } + + /** + * Create and return HttpRequest or ConsoleRequest instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return HttpRequest|ConsoleRequest + */ + public function createService(ServiceLocatorInterface $container) + { + $type = Console::isConsole() ? ConsoleRequest::class : HttpRequest::class; + return $this($container, $type); + } } diff --git a/src/Service/ResponseFactory.php b/src/Service/ResponseFactory.php index 9b0b24bad..7d1e6cf2b 100644 --- a/src/Service/ResponseFactory.php +++ b/src/Service/ResponseFactory.php @@ -13,7 +13,9 @@ use Zend\Console\Console; use Zend\Console\Response as ConsoleResponse; use Zend\Http\PhpEnvironment\Response as HttpResponse; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use Zend\Stdlib\MessageInterface; class ResponseFactory implements FactoryInterface { @@ -23,7 +25,7 @@ class ResponseFactory implements FactoryInterface * @param ContainerInterface $container * @param string $name * @param null|array $options - * @return \Zend\Stdlib\Message + * @return MessageInterface */ public function __invoke(ContainerInterface $container, $name, array $options = null) { @@ -33,4 +35,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return new HttpResponse(); } + + /** + * Create and return MessageInterface instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return MessageInterface + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, MessageInterface::class); + } } diff --git a/src/Service/RouterFactory.php b/src/Service/RouterFactory.php index 100df18de..9cd1ee7c2 100644 --- a/src/Service/RouterFactory.php +++ b/src/Service/RouterFactory.php @@ -11,7 +11,9 @@ use Interop\Container\ContainerInterface; use Zend\Console\Console; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\Mvc\Router\RouteStackInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class RouterFactory implements FactoryInterface { @@ -24,7 +26,7 @@ class RouterFactory implements FactoryInterface * @param ContainerInterface $container * @param string $name * @param null|array $options - * @return \Zend\Mvc\Router\RouteStackInterface + * @return RouteStackInterface */ public function __invoke(ContainerInterface $container, $name, array $options = null) { @@ -37,4 +39,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $container->get('HttpRouter'); } + + /** + * Create and return RouteStackInterface instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return RouteStackInterface + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, RouteStackInterface::class); + } } diff --git a/src/Service/ServiceListenerFactory.php b/src/Service/ServiceListenerFactory.php index f07e9fad6..21c4d51c9 100644 --- a/src/Service/ServiceListenerFactory.php +++ b/src/Service/ServiceListenerFactory.php @@ -14,8 +14,9 @@ use Zend\ModuleManager\Listener\ServiceListenerInterface; use Zend\Mvc\View; use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\Factory\InvokableFactory; +use Zend\ServiceManager\ServiceLocatorInterface; class ServiceListenerFactory implements FactoryInterface { @@ -36,14 +37,33 @@ class ServiceListenerFactory implements FactoryInterface * @var array */ protected $defaultServiceConfig = [ - 'invokables' => [ - 'MiddlewareListener' => 'Zend\Mvc\MiddlewareListener', - 'RouteListener' => 'Zend\Mvc\RouteListener', - 'SendResponseListener' => 'Zend\Mvc\SendResponseListener', - 'ViewJsonRenderer' => 'Zend\View\Renderer\JsonRenderer', - 'ViewFeedRenderer' => 'Zend\View\Renderer\FeedRenderer', + 'aliases' => [ + 'Configuration' => 'config', + 'configuration' => 'config', + 'Console' => 'ConsoleAdapter', + 'ConsoleDefaultRenderingStrategy' => View\Console\DefaultRenderingStrategy::class, + 'ControllerLoader' => 'ControllerManager', + 'HttpDefaultRenderingStrategy' => View\Http\DefaultRenderingStrategy::class, + 'MiddlewareListener' => 'Zend\Mvc\MiddlewareListener', + 'RouteListener' => 'Zend\Mvc\RouteListener', + 'SendResponseListener' => 'Zend\Mvc\SendResponseListener', + 'View' => 'Zend\View\View', + 'ViewFeedRenderer' => 'Zend\View\Renderer\FeedRenderer', + 'ViewJsonRenderer' => 'Zend\View\Renderer\JsonRenderer', + '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', ], - 'factories' => [ + 'invokables' => [], + 'factories' => [ 'Application' => 'Zend\Mvc\Service\ApplicationFactory', 'config' => 'Zend\Mvc\Service\ConfigFactory', 'ControllerManager' => 'Zend\Mvc\Service\ControllerManagerFactory', @@ -86,56 +106,40 @@ class ServiceListenerFactory implements FactoryInterface 'ViewTemplateMapResolver' => 'Zend\Mvc\Service\ViewTemplateMapResolverFactory', 'ViewTemplatePathStack' => 'Zend\Mvc\Service\ViewTemplatePathStackFactory', 'ViewPrefixPathStackResolver' => 'Zend\Mvc\Service\ViewPrefixPathStackResolverFactory', + 'Zend\Mvc\MiddlewareListener' => InvokableFactory::class, + 'Zend\Mvc\RouteListener' => InvokableFactory::class, + 'Zend\Mvc\SendResponseListener' => InvokableFactory::class, + 'Zend\View\Renderer\FeedRenderer' => InvokableFactory::class, + 'Zend\View\Renderer\JsonRenderer' => InvokableFactory::class, 'Zend\View\Renderer\PhpRenderer' => ViewPhpRendererFactory::class, 'Zend\View\Strategy\PhpRendererStrategy' => ViewPhpRendererStrategyFactory::class, 'Zend\View\View' => ViewFactory::class, ], - 'aliases' => [ - 'Config' => 'config', - 'Configuration' => 'config', - 'configuration' => 'config', - 'Console' => 'ConsoleAdapter', - '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', - ], - /* 'abstract_factories' => [ 'Zend\Form\FormAbstractServiceFactory', ], - */ ]; /** * Create the service listener service * * Tries to get a service named ServiceListenerInterface from the service - * locator, otherwise creates a Zend\ModuleManager\Listener\ServiceListener - * service, passing it the service locator instance and the default service - * configuration, which can be overridden by modules. + * locator, otherwise creates a ServiceListener instance, passing it the + * container instance and the default service configuration, which can be + * overridden by modules. * * It looks for the 'service_listener_options' key in the application - * config and tries to add service manager as configured. The value of - * 'service_listener_options' must be a list (array) which contains the + * config and tries to add service/plugin managers as configured. The value + * of 'service_listener_options' must be a list (array) which contains the * following keys: - * - service_manager: the name of the service manage to create as string - * - config_key: the name of the configuration key to search for as string - * - interface: the name of the interface that modules can implement as string - * - method: the name of the method that modules have to implement as string + * + * - service_manager: the name of the service manage to create as string + * - config_key: the name of the configuration key to search for as string + * - interface: the name of the interface that modules can implement as string + * - method: the name of the method that modules have to implement as string * * @param ServiceLocatorInterface $serviceLocator - * @return ServiceListener + * @return ServiceListenerInterface * @throws ServiceNotCreatedException for invalid ServiceListener service * @throws ServiceNotCreatedException For invalid configurations. */ @@ -145,15 +149,17 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o $serviceListener = $container->has('ServiceListenerInterface') ? $container->get('ServiceListenerInterface') - : new ServiceListener($container, $this->defaultServiceConfig); + : new ServiceListener($container); if (! $serviceListener instanceof ServiceListenerInterface) { throw new ServiceNotCreatedException( - 'The service named ServiceListenerInterface must implement ' . - 'Zend\ModuleManager\Listener\ServiceListenerInterface' + 'The service named ServiceListenerInterface must implement ' + . ServiceListenerInterface::class ); } + $serviceListener->setDefaultServiceConfig($this->defaultServiceConfig); + if (isset($configuration['service_listener_options'])) { $this->injectServiceListenerOptions($configuration['service_listener_options'], $serviceListener); } @@ -161,6 +167,17 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o return $serviceListener; } + /** + * Create and return the ServiceListener (v2) + * + * @param ServiceLocatorInterface $container + * @return ServiceListenerInterface + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, ServiceListener::class); + } + /** * Validate and inject plugin manager options into the service listener. * diff --git a/src/Service/ServiceManagerConfig.php b/src/Service/ServiceManagerConfig.php index f1c363b80..ee223200b 100644 --- a/src/Service/ServiceManagerConfig.php +++ b/src/Service/ServiceManagerConfig.php @@ -10,33 +10,52 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; +use Zend\EventManager\EventManager; use Zend\EventManager\EventManagerAwareInterface; use Zend\EventManager\EventManagerInterface; +use Zend\EventManager\SharedEventManager; use Zend\EventManager\SharedEventManagerInterface; +use Zend\ModuleManager\Listener\ServiceListener; +use Zend\ModuleManager\ModuleManager; use Zend\ServiceManager\Config; +use Zend\ServiceManager\ServiceLocatorAwareInterface; use Zend\ServiceManager\ServiceManager; +use Zend\ServiceManager\ServiceManagerAwareInterface; +use Zend\Stdlib\ArrayUtils; class ServiceManagerConfig extends Config { + + /** + * Default service configuration. + * + * In addition to these, the constructor registers several factories and + * initializers; see that method for details. + * + * @var array + */ protected $config = [ 'abstract_factories' => [], 'aliases' => [ - 'Zend\EventManager\EventManagerInterface' => 'EventManager', - 'Zend\ServiceManager\ServiceManager' => 'ServiceManager', + 'EventManagerInterface' => EventManager::class, + EventManagerInterface::class => 'EventManager', + ModuleManager::class => 'ModuleManager', + ServiceListener::class => 'ServiceListener', + SharedEventManager::class => 'SharedEventManager', + 'SharedEventManagerInterface' => 'SharedEventManager', + SharedEventManagerInterface::class => 'SharedEventManager', ], 'delegators' => [], 'factories' => [ - 'EventManager' => EventManagerFactory::class, - 'ModuleManager' => ModuleManagerFactory::class, - 'ServiceListener' => ServiceListenerFactory::class, + 'EventManager' => EventManagerFactory::class, + 'ModuleManager' => ModuleManagerFactory::class, + 'ServiceListener' => ServiceListenerFactory::class, ], 'lazy_services' => [], 'initializers' => [], - 'invokables' => [ - 'SharedEventManager' => 'Zend\EventManager\SharedEventManager', - ], - 'services' => [], - 'shared' => [ + 'invokables' => [], + 'services' => [], + 'shared' => [ 'EventManager' => false, ], ]; @@ -44,14 +63,32 @@ class ServiceManagerConfig extends Config /** * Constructor * - * Merges internal arrays with those passed via configuration + * Merges internal arrays with those passed via configuration, and also + * defines: + * + * - factory for the service 'SharedEventManager'. + * - initializer for EventManagerAwareInterface implementations + * - initializer for ServiceManagerAwareInterface implementations + * - initializer for ServiceLocatorAwareInterface implementations * - * @param array $configuration + * @param array $config */ - public function __construct(array $configuration = []) + public function __construct(array $config = []) { - $this->config['initializers'] = array_merge($this->config['initializers'], [ - 'EventManagerAwareInitializer' => function (ContainerInterface $container, $instance) { + $this->config['factories']['SharedEventManager'] = function () { + return new SharedEventManager(); + }; + + $this->config['initializers'] = ArrayUtils::merge($this->config['initializers'], [ + 'EventManagerAwareInitializer' => function ($first, $second) { + if ($first instanceof ContainerInterface) { + $container = $first; + $instance = $second; + } else { + $container = $second; + $instance = $first; + } + if (! $instance instanceof EventManagerAwareInterface) { return; } @@ -67,9 +104,116 @@ public function __construct(array $configuration = []) $instance->setEventManager($container->get('EventManager')); }, + 'ServiceManagerAwareInitializer' => function ($first, $second) { + if ($first instanceof ContainerInterface) { + $container = $first; + $instance = $second; + } else { + $container = $second; + $instance = $first; + } + + if ($container instanceof ServiceManager && $instance instanceof ServiceManagerAwareInterface) { + trigger_error(sprintf( + 'ServiceManagerAwareInterface is deprecated and will be removed in version 3.0, along ' + . 'with the ServiceManagerAwareInitializer. Please update your class %s to remove ' + . 'the implementation, and start injecting your dependencies via factory instead.', + get_class($instance) + ), E_USER_DEPRECATED); + $instance->setServiceManager($container); + } + }, + 'ServiceLocatorAwareInitializer' => function ($first, $second) { + if ($first instanceof ContainerInterface) { + $container = $first; + $instance = $second; + } else { + $container = $second; + $instance = $first; + } + + if ($instance instanceof ServiceLocatorAwareInterface) { + trigger_error(sprintf( + 'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along ' + . 'with the ServiceLocatorAwareInitializer. Please update your class %s to remove ' + . 'the implementation, and start injecting your dependencies via factory instead.', + get_class($instance) + ), E_USER_DEPRECATED); + $instance->setServiceLocator($container); + } + }, ]); + // In zend-servicemanager v2, incoming configuration is not merged + // with existing; it replaces. So we need to detect that and merge. + if (method_exists($this, 'getAllowOverride')) { + $config = ArrayUtils::merge($this->config, $config); + } - parent::__construct($configuration); + parent::__construct($config); + } + + /** + * Configure service container. + * + * Uses the configuration present in the instance to configure the provided + * service container. + * + * Before doing so, it adds a "service" entry for the ServiceManager class, + * pointing to the provided service container. + * + * @param ServiceManager $services + * @return ServiceManager + */ + public function configureServiceManager(ServiceManager $services) + { + $this->config['services'][ServiceManager::class] = $services; + + /* + printf("Configuration prior to configuring servicemanager:\n"); + foreach ($this->config as $type => $list) { + switch ($type) { + case 'aliases': + case 'delegators': + case 'factories': + case 'invokables': + case 'lazy_services': + case 'services': + case 'shared': + foreach (array_keys($list) as $name) { + printf(" %s (%s)\n", $name, $type); + } + break; + + case 'initializers': + case 'abstract_factories': + foreach ($list as $callable) { + printf(" %s (%s)\n", (is_object($callable) ? get_class($callable) : $callable), $type); + } + break; + + default: + break; + } + } + */ + + // This is invoked as part of the bootstrapping process, and requires + // the ability to override services. + $services->setAllowOverride(true); + parent::configureServiceManager($services); + $services->setAllowOverride(false); + + return $services; + } + + /** + * Return all service configuration (v3) + * + * @return array + */ + public function toArray() + { + return $this->config; } } diff --git a/src/Service/TranslatorServiceFactory.php b/src/Service/TranslatorServiceFactory.php index f2b444c22..1675b4b16 100644 --- a/src/Service/TranslatorServiceFactory.php +++ b/src/Service/TranslatorServiceFactory.php @@ -14,7 +14,8 @@ use Zend\I18n\Translator\Translator; use Zend\Mvc\I18n\DummyTranslator; use Zend\Mvc\I18n\Translator as MvcTranslator; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; /** * Overrides the translator factory from the i18n component in order to @@ -52,7 +53,7 @@ public function __invoke(ContainerInterface $container, $name, array $options = ) { $i18nTranslator = Translator::factory($config['translator']); $i18nTranslator->setPluginManager($container->get('TranslatorPluginManager')); - // $container->setService('Zend\I18n\Translator\TranslatorInterface', $i18nTranslator); + $container->setService('Zend\I18n\Translator\TranslatorInterface', $i18nTranslator); return new MvcTranslator($i18nTranslator); } } @@ -65,4 +66,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = // For BC purposes (pre-2.3.0), use the I18n Translator return new MvcTranslator(new Translator()); } + + /** + * Create and return MvcTranslator instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return MvcTranslator + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, MvcTranslator::class); + } } diff --git a/src/Service/ViewFactory.php b/src/Service/ViewFactory.php index dd9ce58e6..b8cc4bdcb 100644 --- a/src/Service/ViewFactory.php +++ b/src/Service/ViewFactory.php @@ -10,7 +10,8 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\Strategy\PhpRendererStrategy; use Zend\View\View; @@ -32,4 +33,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $view; } + + /** + * Create and return View instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return View + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, View::class); + } } diff --git a/src/Service/ViewFeedStrategyFactory.php b/src/Service/ViewFeedStrategyFactory.php index b5fc41885..274b90d14 100644 --- a/src/Service/ViewFeedStrategyFactory.php +++ b/src/Service/ViewFeedStrategyFactory.php @@ -10,7 +10,8 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\Strategy\FeedStrategy; class ViewFeedStrategyFactory implements FactoryInterface @@ -32,4 +33,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = { return new FeedStrategy($container->get('ViewFeedRenderer')); } + + /** + * Create and return FeedStrategy instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return FeedStrategy + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, FeedStrategy::class); + } } diff --git a/src/Service/ViewHelperManagerFactory.php b/src/Service/ViewHelperManagerFactory.php index c09f4e306..7515f6177 100644 --- a/src/Service/ViewHelperManagerFactory.php +++ b/src/Service/ViewHelperManagerFactory.php @@ -12,8 +12,8 @@ use Interop\Container\ContainerInterface; use Zend\Console\Console; use Zend\Mvc\Router\RouteMatch; +use Zend\ServiceManager\ConfigInterface; use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\Stdlib\ArrayUtils; use Zend\View\Helper as ViewHelper; use Zend\View\HelperPluginManager; @@ -30,11 +30,9 @@ class ViewHelperManagerFactory extends AbstractPluginManagerFactory * @var array */ protected $defaultHelperMapClasses = [ - /* 'Zend\Form\View\HelperConfig', 'Zend\I18n\View\HelperConfig', 'Zend\Navigation\View\HelperConfig', - */ ]; /** @@ -54,7 +52,7 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o $plugins = $this->configureHelpers($plugins); // Override plugin factories - $plugins = $this->injectOverrideFactories($plugins, $serviceLocator); + $plugins = $this->injectOverrideFactories($plugins, $container); return $plugins; } @@ -85,10 +83,9 @@ private function configureHelpers(HelperPluginManager $plugins) )); } - $options = ArrayUtils::merge($options, $config->toArray()); + $config->configureServiceManager($plugins); } - $plugins->configure($options); return $plugins; } @@ -113,7 +110,7 @@ private function injectOverrideFactories(HelperPluginManager $plugins, Container // Configure doctype view helper $doctypeFactory = $this->createDoctypeHelperFactory($services); - $plugins->setFactory(ViewHelper\doctype::class, $doctypeFactory); + $plugins->setFactory(ViewHelper\Doctype::class, $doctypeFactory); $plugins->setFactory('zendviewhelperdoctype', $doctypeFactory); return $plugins; @@ -132,6 +129,11 @@ private function injectOverrideFactories(HelperPluginManager $plugins, Container private function createUrlHelperFactory(ContainerInterface $services) { return function () use ($services) { + // zend-servicemanager v2: fetch parent locator + if (method_exists($services, 'getServiceLocator') && ! method_exists($services, 'configure')) { + $services = $services->getServiceLocator() ?: $services; + } + $helper = new ViewHelper\Url; $router = Console::isConsole() ? 'HttpRouter' : 'Router'; $helper->setRouter($services->get($router)); @@ -149,6 +151,7 @@ private function createUrlHelperFactory(ContainerInterface $services) }; } + /** * Create and return a factory for creating a BasePath helper. * * Uses configuration and request services to configure the helper. @@ -159,6 +162,11 @@ private function createUrlHelperFactory(ContainerInterface $services) private function createBasePathHelperFactory(ContainerInterface $services) { return function () use ($services) { + // zend-servicemanager v2: fetch parent locator + if (method_exists($services, 'getServiceLocator') && ! method_exists($services, 'configure')) { + $services = $services->getServiceLocator() ?: $services; + } + $config = $services->has('config') ? $services->get('config') : []; $helper = new ViewHelper\BasePath; @@ -196,6 +204,11 @@ private function createBasePathHelperFactory(ContainerInterface $services) private function createDoctypeHelperFactory(ContainerInterface $services) { return function () use ($services) { + // zend-servicemanager v2: fetch parent locator + if (method_exists($services, 'getServiceLocator') && ! method_exists($services, 'configure')) { + $services = $services->getServiceLocator() ?: $services; + } + $config = $services->has('config') ? $services->get('config') : []; $config = isset($config['view_manager']) ? $config['view_manager'] : []; $helper = new ViewHelper\Doctype; diff --git a/src/Service/ViewJsonStrategyFactory.php b/src/Service/ViewJsonStrategyFactory.php index 92337b299..7758dc46a 100644 --- a/src/Service/ViewJsonStrategyFactory.php +++ b/src/Service/ViewJsonStrategyFactory.php @@ -10,7 +10,8 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\Strategy\JsonStrategy; class ViewJsonStrategyFactory implements FactoryInterface @@ -34,4 +35,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = $jsonStrategy = new JsonStrategy($jsonRenderer); return $jsonStrategy; } + + /** + * Create and return JsonStrategy instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return JsonStrategy + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, JsonStrategy::class); + } } diff --git a/src/Service/ViewManagerFactory.php b/src/Service/ViewManagerFactory.php index a0a4c7c98..0a5e90954 100644 --- a/src/Service/ViewManagerFactory.php +++ b/src/Service/ViewManagerFactory.php @@ -13,7 +13,8 @@ use Zend\Console\Console; use Zend\Mvc\View\Console\ViewManager as ConsoleViewManager; use Zend\Mvc\View\Http\ViewManager as HttpViewManager; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class ViewManagerFactory implements FactoryInterface { @@ -33,4 +34,18 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $container->get('HttpViewManager'); } + + /** + * Create and return HttpViewManager or ConsoleViewManager instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return HttpViewManager|ConsoleViewManager + */ + public function createService(ServiceLocatorInterface $container) + { + $type = Console::isConsole() ? ConsoleViewManager::class : HttpViewManager::class; + return $this($container, $type); + } } diff --git a/src/Service/ViewPhpRendererFactory.php b/src/Service/ViewPhpRendererFactory.php index 770704d2c..4c4734dbd 100644 --- a/src/Service/ViewPhpRendererFactory.php +++ b/src/Service/ViewPhpRendererFactory.php @@ -10,7 +10,8 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\Renderer\PhpRenderer; class ViewPhpRendererFactory implements FactoryInterface @@ -29,4 +30,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $renderer; } + + /** + * Create and return PhpRenderer instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return PhpRenderer + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, PhpRenderer::class); + } } diff --git a/src/Service/ViewPhpRendererStrategyFactory.php b/src/Service/ViewPhpRendererStrategyFactory.php index 2d70aaf1d..ec0699e26 100644 --- a/src/Service/ViewPhpRendererStrategyFactory.php +++ b/src/Service/ViewPhpRendererStrategyFactory.php @@ -10,7 +10,8 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\Strategy\PhpRendererStrategy; use Zend\View\Renderer\PhpRenderer; @@ -26,4 +27,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = { return new PhpRendererStrategy($container->get(PhpRenderer::class)); } + + /** + * Create and return PhpRendererStrategy instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return PhpRendererStrategy + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, PhpRendererStrategy::class); + } } diff --git a/src/Service/ViewPrefixPathStackResolverFactory.php b/src/Service/ViewPrefixPathStackResolverFactory.php index 8eb85a6a2..354406b03 100644 --- a/src/Service/ViewPrefixPathStackResolverFactory.php +++ b/src/Service/ViewPrefixPathStackResolverFactory.php @@ -10,7 +10,8 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\Resolver\PrefixPathStackResolver; class ViewPrefixPathStackResolverFactory implements FactoryInterface @@ -37,4 +38,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return new PrefixPathStackResolver($prefixes); } + + /** + * Create and return PrefixPathStackResolver instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return PrefixPathStackResolver + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, PrefixPathStackResolver::class); + } } diff --git a/src/Service/ViewResolverFactory.php b/src/Service/ViewResolverFactory.php index 1b242e0f1..8efd286c4 100644 --- a/src/Service/ViewResolverFactory.php +++ b/src/Service/ViewResolverFactory.php @@ -10,7 +10,8 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\Resolver as ViewResolver; class ViewResolverFactory implements FactoryInterface @@ -47,4 +48,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $resolver; } + + /** + * Create and return ViewResolver\AggregateResolver instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return ViewResolver\AggregateResolver + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, ViewResolver\AggregateResolver::class); + } } diff --git a/src/Service/ViewTemplateMapResolverFactory.php b/src/Service/ViewTemplateMapResolverFactory.php index 64a911daf..883be735c 100644 --- a/src/Service/ViewTemplateMapResolverFactory.php +++ b/src/Service/ViewTemplateMapResolverFactory.php @@ -10,7 +10,8 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\Resolver as ViewResolver; class ViewTemplateMapResolverFactory implements FactoryInterface @@ -38,4 +39,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = } return new ViewResolver\TemplateMapResolver($map); } + + /** + * Create and return ViewResolver\TemplateMapResolver instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return ViewResolver\TemplateMapResolver + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, ViewResolver\TemplateMapResolver::class); + } } diff --git a/src/Service/ViewTemplatePathStackFactory.php b/src/Service/ViewTemplatePathStackFactory.php index c4267d7e9..9e251842c 100644 --- a/src/Service/ViewTemplatePathStackFactory.php +++ b/src/Service/ViewTemplatePathStackFactory.php @@ -10,7 +10,8 @@ namespace Zend\Mvc\Service; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\Resolver as ViewResolver; class ViewTemplatePathStackFactory implements FactoryInterface @@ -47,4 +48,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = return $templatePathStack; } + + /** + * Create and return ViewResolver\TemplatePathStack instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return ViewResolver\TemplatePathStack + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, ViewResolver\TemplatePathStack::class); + } } diff --git a/test/Application/BadControllerTrait.php b/test/Application/BadControllerTrait.php index f85660211..0f7c4e967 100644 --- a/test/Application/BadControllerTrait.php +++ b/test/Application/BadControllerTrait.php @@ -84,7 +84,8 @@ public function prepareApplication() ], ] ); - $services = new ServiceManager((new ServiceManagerConfig($serviceConfig))->toArray()); + $services = new ServiceManager(); + (new ServiceManagerConfig($serviceConfig))->configureServiceManager($services); $application = $services->get('Application'); $request = $services->get('Request'); diff --git a/test/Application/InvalidControllerTypeTrait.php b/test/Application/InvalidControllerTypeTrait.php index e45ed2626..42264f60e 100644 --- a/test/Application/InvalidControllerTypeTrait.php +++ b/test/Application/InvalidControllerTypeTrait.php @@ -51,12 +51,11 @@ public function prepareApplication() $serviceConfig, [ 'aliases' => [ - 'ControllerLoader' => ControllerManager::class, - 'ControllerManager' => ControllerManager::class, + 'ControllerLoader' => 'ControllerManager', 'Router' => 'HttpRouter', ], 'factories' => [ - ControllerManager::class => function ($services) { + 'ControllerManager' => function ($services) { return new ControllerManager($services, ['factories' => [ 'bad' => function () { return new stdClass(); @@ -84,7 +83,8 @@ public function prepareApplication() ], ] ); - $services = new ServiceManager((new ServiceManagerConfig($serviceConfig))->toArray()); + $services = new ServiceManager(); + (new ServiceManagerConfig($serviceConfig))->configureServiceManager($services); $application = $services->get('Application'); $request = $services->get('Request'); diff --git a/test/Application/MissingControllerTrait.php b/test/Application/MissingControllerTrait.php index 16ee04c86..f02c30a8b 100644 --- a/test/Application/MissingControllerTrait.php +++ b/test/Application/MissingControllerTrait.php @@ -71,7 +71,8 @@ public function prepareApplication() ], ] ); - $services = new ServiceManager((new ServiceManagerConfig($serviceConfig))->toArray()); + $services = new ServiceManager(); + (new ServiceManagerConfig($serviceConfig))->configureServiceManager($services); $application = $services->get('Application'); $request = $services->get('Request'); diff --git a/test/Application/PathControllerTrait.php b/test/Application/PathControllerTrait.php index 18376007d..73c6aa741 100644 --- a/test/Application/PathControllerTrait.php +++ b/test/Application/PathControllerTrait.php @@ -82,7 +82,8 @@ public function prepareApplication() ], ] ); - $services = new ServiceManager((new ServiceManagerConfig($serviceConfig))->toArray()); + $services = new ServiceManager(); + (new ServiceManagerConfig($serviceConfig))->configureServiceManager($services); $application = $services->get('Application'); $request = $services->get('Request'); diff --git a/test/ApplicationTest.php b/test/ApplicationTest.php index f706d0d4d..49f70a258 100644 --- a/test/ApplicationTest.php +++ b/test/ApplicationTest.php @@ -13,6 +13,8 @@ use ReflectionMethod; use ReflectionProperty; use stdClass; +use Zend\EventManager\SharedEventManager; +use Zend\EventManager\Test\EventListenerIntrospectionTrait; use Zend\Http\PhpEnvironment\Response; use Zend\ModuleManager\Listener\ConfigListener; use Zend\ModuleManager\ModuleEvent; @@ -28,7 +30,7 @@ class ApplicationTest extends TestCase { - use EventManagerIntrospectionTrait; + use EventListenerIntrospectionTrait; /** * @var ServiceManager @@ -73,25 +75,12 @@ public function setUp() ], ] ); - $this->serviceManager = new ServiceManager((new ServiceManagerConfig($serviceConfig))->toArray()); + $this->serviceManager = new ServiceManager(); + (new ServiceManagerConfig($serviceConfig))->configureServiceManager($this->serviceManager); + $this->serviceManager->setAllowOverride(true); $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'); @@ -160,6 +149,7 @@ public function testEventsAreEmptyAtFirst() $this->assertEquals([], $registeredEvents); $sharedEvents = $events->getSharedManager(); + $this->assertInstanceOf(SharedEventManager::class, $sharedEvents); $this->assertAttributeEquals([], 'identifiers', $sharedEvents); } @@ -257,31 +247,21 @@ public function setupPathController($addService = true) ], ]); $router->addRoute('path', $route); - $services = $this->serviceManager->withConfig([ - 'aliases' => [ - 'Router' => 'HttpRouter', - ], - 'services' => [ - 'HttpRouter' => $router, - ], - ]); + $this->serviceManager->setAlias('Router', 'HttpRouter'); + $this->serviceManager->setService('HttpRouter', $router); - $application = $this->setApplicationServiceManager($this->application, $services); if ($addService) { - $services = $services->withConfig(['factories' => [ - 'ControllerManager' => function ($services) { - return new ControllerManager($services, ['factories' => [ - 'path' => function () { - return new TestAsset\PathController; - }, - ]]); - }, - ]]); - $application = $this->setApplicationServiceManager($application, $services); + $this->services->addFactory('ControllerManager', function ($services) { + return new ControllerManager($services, ['factories' => [ + 'path' => function () { + return new TestAsset\PathController; + }, + ]]); + }); } - $application->bootstrap(); - return $application; + $this->application->bootstrap(); + return $this->application; } public function setupActionController() @@ -299,19 +279,16 @@ public function setupActionController() ]); $router->addRoute('sample', $route); - $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); + $this->serviceManager->setFactory('ControllerManager', function ($services) { + return new ControllerManager($services, ['factories' => [ + 'sample' => function () { + return new Controller\TestAsset\SampleController(); + }, + ]]); + }); - $application->bootstrap(); - return $application; + $this->application->bootstrap(); + return $this->application; } public function setupBadController($addService = true) @@ -329,22 +306,18 @@ public function setupBadController($addService = true) ]); $router->addRoute('bad', $route); - $application = $this->application; if ($addService) { - $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->serviceManager->setFactory('ControllerManager', function ($services) { + return new ControllerManager($services, ['factories' => [ + 'bad' => function () { + return new Controller\TestAsset\BadController(); + }, + ]]); + }); } - $application->bootstrap(); - return $application; + $this->application->bootstrap(); + return $this->application; } public function testFinishEventIsTriggeredAfterDispatching() diff --git a/test/Controller/ActionControllerTest.php b/test/Controller/ActionControllerTest.php index 5c51cc77a..3fc60f7a0 100644 --- a/test/Controller/ActionControllerTest.php +++ b/test/Controller/ActionControllerTest.php @@ -10,6 +10,7 @@ namespace ZendTest\Mvc\Controller; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionClass; use Zend\Console\Response as ConsoleResponse; use Zend\EventManager\EventManager; use Zend\EventManager\SharedEventManager; @@ -38,10 +39,29 @@ public function setUp() $this->controller->setEvent($this->event); $this->sharedEvents = new SharedEventManager(); - $this->events = new EventManager($this->sharedEvents); + $this->events = $this->createEventManager($this->sharedEvents); $this->controller->setEventManager($this->events); } + /** + * Create an event manager instance based on zend-eventmanager version + * + * @param SharedEventManager + * @return EventManager + */ + protected function createEventManager($sharedManager) + { + $r = new ReflectionClass(EventManager::class); + + if ($r->hasMethod('setSharedManager')) { + $events = new EventManager(); + $events->setSharedManager($sharedManager); + return $events; + } + + return new EventManager($sharedManager); + } + public function testDispatchInvokesNotFoundActionWhenNoActionPresentInRouteMatch() { $result = $this->controller->dispatch($this->request, $this->response); diff --git a/test/Controller/ControllerManagerTest.php b/test/Controller/ControllerManagerTest.php index d9336bdd1..dbdf76bc3 100644 --- a/test/Controller/ControllerManagerTest.php +++ b/test/Controller/ControllerManagerTest.php @@ -10,10 +10,12 @@ namespace ZendTest\Mvc\Controller; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionClass; use Zend\EventManager\EventManager; use Zend\EventManager\SharedEventManager; use Zend\Mvc\Controller\ControllerManager; use Zend\Mvc\Controller\PluginManager as ControllerPluginManager; +use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; use Zend\Console\Adapter\Virtual as ConsoleAdapter; @@ -22,10 +24,11 @@ class ControllerManagerTest extends TestCase public function setUp() { $this->sharedEvents = new SharedEventManager; - $this->events = new EventManager($this->sharedEvents); + $this->events = $this->createEventManager($this->sharedEvents); $this->consoleAdapter = new ConsoleAdapter(); - $this->services = new ServiceManager([ + $this->services = new ServiceManager(); + (new Config([ 'factories' => [ 'ControllerPluginManager' => function ($services) { return new ControllerPluginManager($services); @@ -36,15 +39,42 @@ public function setUp() 'EventManager' => $this->events, 'SharedEventManager' => $this->sharedEvents, ], - ]); + ]))->configureServiceManager($this->services); $this->controllers = new ControllerManager($this->services); } + /** + * Create an event manager instance based on zend-eventmanager version + * + * @param SharedEventManager + * @return EventManager + */ + protected function createEventManager($sharedManager) + { + $r = new ReflectionClass(EventManager::class); + + if ($r->hasMethod('setSharedManager')) { + $events = new EventManager(); + $events->setSharedManager($sharedManager); + return $events; + } + + return new EventManager($sharedManager); + } + public function testCanInjectEventManager() { $controller = new TestAsset\SampleController(); - $this->controllers->injectEventManager($this->services, $controller); + + // Vary injection based on zend-servicemanager version + if (method_exists($this->controllers, 'configure')) { + // v3 + $this->controllers->injectEventManager($this->services, $controller); + } else { + // v2 + $this->controllers->injectEventManager($controller, $this->controllers); + } // The default AbstractController implementation lazy instantiates an EM // instance, which means we need to check that that instance gets injected @@ -57,23 +87,50 @@ public function testCanInjectEventManager() public function testCanInjectConsoleAdapter() { $controller = new TestAsset\ConsoleController(); - $this->controllers->injectConsole($this->services, $controller); + + // Vary injection based on zend-servicemanager version + if (method_exists($this->controllers, 'configure')) { + // v3 + $this->controllers->injectConsole($this->services, $controller); + } else { + // v2 + $this->controllers->injectConsole($controller, $this->controllers); + } + $this->assertInstanceOf('Zend\Console\Adapter\AdapterInterface', $controller->getConsole()); } public function testCanInjectPluginManager() { $controller = new TestAsset\SampleController(); - $this->controllers->injectPluginManager($this->services, $controller); + + // Vary injection based on zend-servicemanager version + if (method_exists($this->controllers, 'configure')) { + // v3 + $this->controllers->injectPluginManager($this->services, $controller); + } else { + // v2 + $this->controllers->injectPluginManager($controller, $this->controllers); + } + $this->assertSame($this->services->get('ControllerPluginManager'), $controller->getPluginManager()); } public function testInjectEventManagerWillNotOverwriteExistingEventManagerIfItAlreadyHasASharedManager() { - $events = new EventManager($this->sharedEvents); + $events = $this->createEventManager($this->sharedEvents); $controller = new TestAsset\SampleController(); $controller->setEventManager($events); - $this->controllers->injectEventManager($this->services, $controller); + + // Vary injection based on zend-servicemanager version + if (method_exists($this->controllers, 'configure')) { + // v3 + $this->controllers->injectEventManager($this->services, $controller); + } else { + // v2 + $this->controllers->injectEventManager($controller, $this->controllers); + } + $this->assertSame($events, $controller->getEventManager()); $this->assertSame($this->sharedEvents, $events->getSharedManager()); } diff --git a/test/Controller/IntegrationTest.php b/test/Controller/IntegrationTest.php index 4c4bdfe75..baa045149 100644 --- a/test/Controller/IntegrationTest.php +++ b/test/Controller/IntegrationTest.php @@ -14,6 +14,7 @@ use Zend\EventManager\SharedEventManager; use Zend\Mvc\Controller\ControllerManager; use Zend\Mvc\Controller\PluginManager; +use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; class IntegrationTest extends TestCase @@ -22,7 +23,8 @@ public function setUp() { $this->sharedEvents = new SharedEventManager(); - $this->services = new ServiceManager([ + $this->services = new ServiceManager(); + (new Config([ 'services' => [ 'SharedEventManager' => $this->sharedEvents, ], @@ -37,7 +39,7 @@ public function setUp() 'shared' => [ 'EventManager' => false, ], - ]); + ]))->configureServiceManager($this->services); } public function testPluginReceivesCurrentController() diff --git a/test/Controller/Plugin/ForwardTest.php b/test/Controller/Plugin/ForwardTest.php index c4211acac..60a5a4610 100644 --- a/test/Controller/Plugin/ForwardTest.php +++ b/test/Controller/Plugin/ForwardTest.php @@ -10,6 +10,7 @@ namespace ZendTest\Mvc\Controller\Plugin; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionClass; use stdClass; use Zend\EventManager\EventManager; use Zend\EventManager\SharedEventManager; @@ -20,6 +21,7 @@ use Zend\Mvc\Controller\Plugin\Forward as ForwardPlugin; use Zend\Mvc\MvcEvent; use Zend\Mvc\Router\RouteMatch; +use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; use ZendTest\Mvc\Controller\TestAsset\ForwardController; use ZendTest\Mvc\Controller\TestAsset\SampleController; @@ -49,7 +51,7 @@ class ForwardTest extends TestCase public function setUp() { - $eventManager = new EventManager(new SharedEventManager()); + $eventManager = $this->createEventManager(new SharedEventManager()); $mockApplication = $this->getMock('Zend\Mvc\ApplicationInterface'); $mockApplication->expects($this->any())->method('getEventManager')->will($this->returnValue($eventManager)); @@ -62,13 +64,14 @@ public function setUp() $routeMatch->setMatchedRouteName('some-route'); $event->setRouteMatch($routeMatch); - $this->services = $services = new ServiceManager([ + $config = new Config([ '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(); @@ -81,7 +84,7 @@ public function setUp() return new PluginManager($services); }, 'EventManager' => function ($services, $name) { - return new EventManager($services->get('SharedEventManager')); + return $this->createEventManager($services->get('SharedEventManager')); }, 'SharedEventManager' => function ($services, $name) { return new SharedEventManager(); @@ -91,6 +94,8 @@ public function setUp() 'EventManager' => false, ], ]); + $this->services = $services = new ServiceManager(); + $config->configureServiceManager($services); $this->controllers = $services->get('ControllerManager'); @@ -102,6 +107,25 @@ public function setUp() $this->plugin = $plugins->get('forward'); } + /** + * Create an event manager instance based on zend-eventmanager version + * + * @param SharedEventManager + * @return EventManager + */ + protected function createEventManager($sharedManager) + { + $r = new ReflectionClass(EventManager::class); + + if ($r->hasMethod('setSharedManager')) { + $events = new EventManager(); + $events->setSharedManager($sharedManager); + return $events; + } + + return new EventManager($sharedManager); + } + public function testPluginWithoutEventAwareControllerRaisesDomainException() { $controller = new UneventfulController(); @@ -120,15 +144,18 @@ public function testPluginWithoutControllerLocatorRaisesServiceNotCreatedExcepti public function testDispatchRaisesDomainExceptionIfDiscoveredControllerIsNotDispatchable() { - $controllers = $this->controllers->withConfig(['factories' => [ - 'bogus' => function () { - return new stdClass; - }, - ]]); - $plugin = new ForwardPlugin($controllers); + $this->controllers->setFactory('bogus', function () { + return new stdClass; + }); + $plugin = new ForwardPlugin($this->controllers); $plugin->setController($this->controller); - $this->setExpectedException('Zend\ServiceManager\Exception\InvalidServiceException', 'DispatchableInterface'); + // Vary exception expected based on zend-servicemanager version + $expectedException = method_exists($this->controllers, 'configure') + ? 'Zend\ServiceManager\Exception\InvalidServiceException' // v3 + : 'Zend\Mvc\Exception\InvalidControllerException'; // v2 + + $this->setExpectedException($expectedException, 'DispatchableInterface'); $plugin->dispatch('bogus'); } @@ -136,7 +163,7 @@ public function testDispatchRaisesDomainExceptionIfCircular() { $event = $this->controller->getEvent(); - $services = new ServiceManager([ + $config = new Config([ 'aliases' => [ 'ControllerLoader' => 'ControllerManager', ], @@ -162,7 +189,7 @@ public function testDispatchRaisesDomainExceptionIfCircular() return new PluginManager($services); }, 'EventManager' => function ($services, $name) { - return new EventManager($services->get('SharedEventManager')); + return $this->createEventManager($services->get('SharedEventManager')); }, 'SharedEventManager' => function ($services, $name) { return new SharedEventManager(); @@ -172,6 +199,8 @@ public function testDispatchRaisesDomainExceptionIfCircular() 'EventManager' => false, ], ]); + $services = new ServiceManager(); + $config->configureServiceManager($services); $controllers = $services->get('ControllerManager'); @@ -202,7 +231,7 @@ public function testNonArrayListenerDoesNotRaiseErrorWhenPluginDispatchsRequeste function ($e) {} ])); // @codingStandardsIgnoreEnd - $events = new EventManager($sharedEvents); + $events = $this->createEventManager($sharedEvents); $application = $this->getMock('Zend\Mvc\ApplicationInterface'); $application->expects($this->any())->method('getEventManager')->will($this->returnValue($events)); $event = $this->controller->getEvent(); diff --git a/test/Controller/Plugin/TestAsset/SamplePluginFactory.php b/test/Controller/Plugin/TestAsset/SamplePluginFactory.php index a410b271a..993a844bf 100644 --- a/test/Controller/Plugin/TestAsset/SamplePluginFactory.php +++ b/test/Controller/Plugin/TestAsset/SamplePluginFactory.php @@ -10,7 +10,8 @@ namespace ZendTest\Mvc\Controller\Plugin\TestAsset; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class SamplePluginFactory implements FactoryInterface { @@ -18,4 +19,17 @@ public function __invoke(ContainerInterface $container, $name, array $options = { return new SamplePlugin(); } + + /** + * Create and return SamplePlugin instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return SamplePlugin + */ + public function createService(ServiceLocatorInterface $container) + { + return $this($container, SamplePlugin::class); + } } diff --git a/test/Controller/Plugin/TestAsset/SamplePluginWithConstructorFactory.php b/test/Controller/Plugin/TestAsset/SamplePluginWithConstructorFactory.php index 4e37df4e0..3e838357d 100644 --- a/test/Controller/Plugin/TestAsset/SamplePluginWithConstructorFactory.php +++ b/test/Controller/Plugin/TestAsset/SamplePluginWithConstructorFactory.php @@ -10,7 +10,8 @@ namespace ZendTest\Mvc\Controller\Plugin\TestAsset; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class SamplePluginWithConstructorFactory implements FactoryInterface { @@ -20,4 +21,23 @@ public function __invoke(ContainerInterface $container, $name, array $options = { return new SamplePluginWithConstructor($options); } + + /** + * Create and return SamplePluginWithConstructor instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * @param ServiceLocatorInterface $container + * @return SamplePluginWithConstructor + */ + public function createService(ServiceLocatorInterface $container) + { + $container = $container->getServiceLocator() ?: $container; + return $this($container, SamplePluginWithConstructor::class, $this->options); + } + + public function setCreationOptions(array $options) + { + $this->options = $options; + } } diff --git a/test/Controller/PluginManagerTest.php b/test/Controller/PluginManagerTest.php index 582e214d5..7f72f8dd0 100644 --- a/test/Controller/PluginManagerTest.php +++ b/test/Controller/PluginManagerTest.php @@ -12,6 +12,8 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\Authentication\AuthenticationService; use Zend\Mvc\Controller\PluginManager; +use Zend\ServiceManager\Config; +use Zend\ServiceManager\Factory\InvokableFactory; use Zend\ServiceManager\ServiceManager; use ZendTest\Mvc\Controller\TestAsset\SampleController; use ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin; @@ -22,7 +24,8 @@ public function testPluginManagerInjectsControllerInPlugin() { $controller = new SampleController; $pluginManager = new PluginManager(new ServiceManager(), [ - 'invokables' => ['samplePlugin' => SamplePlugin::class], + 'aliases' => ['samplePlugin' => SamplePlugin::class], + 'factories' => [SamplePlugin::class => InvokableFactory::class], ]); $pluginManager->setController($controller); @@ -34,7 +37,8 @@ public function testPluginManagerInjectsControllerForExistingPlugin() { $controller1 = new SampleController; $pluginManager = new PluginManager(new ServiceManager(), [ - 'invokables' => ['samplePlugin' => SamplePlugin::class], + 'aliases' => ['samplePlugin' => SamplePlugin::class], + 'factories' => [SamplePlugin::class => InvokableFactory::class], ]); $pluginManager->setController($controller1); @@ -51,7 +55,8 @@ public function testPluginManagerInjectsControllerForExistingPlugin() public function testGetWithConstructor() { $pluginManager = new PluginManager(new ServiceManager(), [ - 'invokables' => ['samplePlugin' => Plugin\TestAsset\SamplePluginWithConstructor::class], + 'aliases' => ['samplePlugin' => Plugin\TestAsset\SamplePluginWithConstructor::class], + 'factories' => [Plugin\TestAsset\SamplePluginWithConstructor::class => InvokableFactory::class], ]); $plugin = $pluginManager->get('samplePlugin'); $this->assertEquals($plugin->getBar(), 'baz'); @@ -60,7 +65,8 @@ public function testGetWithConstructor() public function testGetWithConstructorAndOptions() { $pluginManager = new PluginManager(new ServiceManager(), [ - 'invokables' => ['samplePlugin' => Plugin\TestAsset\SamplePluginWithConstructor::class], + 'aliases' => ['samplePlugin' => Plugin\TestAsset\SamplePluginWithConstructor::class], + 'factories' => [Plugin\TestAsset\SamplePluginWithConstructor::class => InvokableFactory::class], ]); $plugin = $pluginManager->get('samplePlugin', ['foo']); $this->assertEquals($plugin->getBar(), ['foo']); @@ -74,11 +80,12 @@ public function testDefinesFactoryForIdentityPlugin() public function testIdentityFactoryCanInjectAuthenticationServiceIfInParentServiceManager() { - $services = new ServiceManager([ - 'invokables' => [ - AuthenticationService::class => AuthenticationService::class, + $services = new ServiceManager(); + (new Config([ + 'factories' => [ + AuthenticationService::class => InvokableFactory::class, ], - ]); + ]))->configureServiceManager($services); $pluginManager = new PluginManager($services); $identity = $pluginManager->get('identity'); $expected = $services->get(AuthenticationService::class); diff --git a/test/Controller/RestfulControllerTest.php b/test/Controller/RestfulControllerTest.php index 99cc1efb7..ea38b083c 100644 --- a/test/Controller/RestfulControllerTest.php +++ b/test/Controller/RestfulControllerTest.php @@ -10,6 +10,7 @@ namespace ZendTest\Mvc\Controller; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionClass; use ReflectionObject; use stdClass; use Zend\EventManager\EventManager; @@ -40,10 +41,29 @@ public function setUp() $this->emptyController->setEvent($this->event); $this->sharedEvents = new SharedEventManager(); - $this->events = new EventManager($this->sharedEvents); + $this->events = $this->createEventManager($this->sharedEvents); $this->controller->setEventManager($this->events); } + /** + * Create an event manager instance based on zend-eventmanager version + * + * @param SharedEventManager + * @return EventManager + */ + protected function createEventManager($sharedManager) + { + $r = new ReflectionClass(EventManager::class); + + if ($r->hasMethod('setSharedManager')) { + $events = new EventManager(); + $events->setSharedManager($sharedManager); + return $events; + } + + return new EventManager($sharedManager); + } + public function testDispatchInvokesListWhenNoActionPresentAndNoIdentifierOnGet() { $entities = [ diff --git a/test/Controller/TestAsset/ControllerLoaderAbstractFactory.php b/test/Controller/TestAsset/ControllerLoaderAbstractFactory.php index 9dd3c3a82..59c0be54f 100644 --- a/test/Controller/TestAsset/ControllerLoaderAbstractFactory.php +++ b/test/Controller/TestAsset/ControllerLoaderAbstractFactory.php @@ -10,7 +10,8 @@ namespace ZendTest\Mvc\Controller\TestAsset; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\AbstractFactoryInterface; +use Zend\ServiceManager\AbstractFactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class ControllerLoaderAbstractFactory implements AbstractFactoryInterface { @@ -18,7 +19,7 @@ class ControllerLoaderAbstractFactory implements AbstractFactoryInterface 'path' => 'ZendTest\Mvc\TestAsset\PathController', ); - public function canCreateServiceWithName(ContainerInterface $container, $name) + public function canCreate(ContainerInterface $container, $name) { if (! isset($this->classmap[$name])) { return false; @@ -28,9 +29,28 @@ public function canCreateServiceWithName(ContainerInterface $container, $name) return class_exists($classname); } + public function canCreateServiceWithName(ServiceLocatorInterface $container, $normalizedName, $name) + { + return $this->canCreate($container, $name); + } + public function __invoke(ContainerInterface $container, $name, array $options = null) { $classname = $this->classmap[$name]; return new $classname; } + + /** + * Create and return DispatchableInterface instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * {@inheritDoc} + * + * @return DispatchableInterface + */ + public function createServiceWithName(ServiceLocatorInterface $container, $name, $requestedName) + { + return $this($container, $requestedName); + } } diff --git a/test/Controller/TestAsset/UnlocatableControllerLoaderAbstractFactory.php b/test/Controller/TestAsset/UnlocatableControllerLoaderAbstractFactory.php index 5ab69f451..b2e54e8bf 100644 --- a/test/Controller/TestAsset/UnlocatableControllerLoaderAbstractFactory.php +++ b/test/Controller/TestAsset/UnlocatableControllerLoaderAbstractFactory.php @@ -10,16 +10,31 @@ namespace ZendTest\Mvc\Controller\TestAsset; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\AbstractFactoryInterface; +use Zend\ServiceManager\AbstractFactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class UnlocatableControllerLoaderAbstractFactory implements AbstractFactoryInterface { - public function canCreateServiceWithName(ContainerInterface $container, $name) + public function canCreate(ContainerInterface $container, $name) { return false; } + /** + * {@inheritDoc} + * + * For use with zend-servicemanager v2; proxies to canCreate(). + */ + public function canCreateServiceWithName(ServiceLocatorInterface $container, $name, $requestedName) + { + return $this->canCreate($container, $requestedName); + } + public function __invoke(ContainerInterface $container, $name, array $options = null) { } + + public function createServiceWithName(ServiceLocatorInterface $container, $name, $requestedName) + { + } } diff --git a/test/EventManagerIntrospectionTrait.php b/test/EventManagerIntrospectionTrait.php deleted file mode 100644 index df814d6b5..000000000 --- a/test/EventManagerIntrospectionTrait.php +++ /dev/null @@ -1,136 +0,0 @@ -setAccessible(true); - $listeners = $r->getValue($events); - return array_keys($listeners); - } - - /** - * Retrieve an interable list of listeners for an event. - * - * Given an event and an event manager, returns an iterator with the - * listeners for that event, in priority order. - * - * If $withPriority is true, the key values will be the priority at which - * the given listener is attached. - * - * Do not pass $withPriority if you want to cast the iterator to an array, - * as many listeners will likely have the same priority, and thus casting - * will collapse to the last added. - * - * @param string $event - * @param EventManager $events - * @param bool $withPriority - * @return \Traversable - */ - private function getListenersForEvent($event, EventManager $events, $withPriority = false) - { - $r = new ReflectionProperty($events, 'events'); - $r->setAccessible(true); - $listeners = $r->getValue($events); - - if (! isset($listeners[$event])) { - return $this->traverseListeners([]); - } - - return $this->traverseListeners($listeners[$event], $withPriority); - } - - /** - * Assert that a given listener exists at the specified priority. - * - * @param callable $expectedListener - * @param int $expectedPriority - * @param string $event - * @param EventManager $events - * @param string $message Failure message to use, if any. - */ - private function assertListenerAtPriority( - callable $expectedListener, - $expectedPriority, - $event, - EventManager $events, - $message = '' - ) { - $message = $message ?: sprintf( - 'Listener not found for event "%s" and priority %d', - $event, - $expectedPriority - ); - $listeners = $this->getListenersForEvent($event, $events, true); - $found = false; - foreach ($listeners as $priority => $listener) { - if ($listener === $expectedListener - && $priority === $expectedPriority - ) { - $found = true; - break; - } - } - $this->assertTrue($found, $message); - } - - /** - * Returns an indexed array of listeners for an event. - * - * Returns an indexed array of listeners for an event, in priority order. - * Priority values will not be included; use this only for testing if - * specific listeners are present, or for a count of listeners. - * - * @param string $event - * @param EventManager $events - * @return callable[] - */ - private function getArrayOfListenersForEvent($event, EventManager $events) - { - return iterator_to_array($this->getListenersForEvent($event, $events)); - } - - /** - * Generator for traversing listeners in priority order. - * - * @param array $listeners - * @param bool $withPriority When true, yields priority as key. - */ - public function traverseListeners(array $queue, $withPriority = false) - { - krsort($queue, SORT_NUMERIC); - - foreach ($queue as $priority => $listeners) { - $priority = (int) $priority; - foreach ($listeners as $listener) { - if ($withPriority) { - yield $priority => $listener; - } else { - yield $listener; - } - } - } - } -} diff --git a/test/MiddlewareListenerTest.php b/test/MiddlewareListenerTest.php index 88be68ec4..5ee475fb2 100644 --- a/test/MiddlewareListenerTest.php +++ b/test/MiddlewareListenerTest.php @@ -40,7 +40,7 @@ public function createMvcEvent($middlewareMatched, $middleware = null) $eventManager = new EventManager(); $serviceManager = $this->prophesize(ContainerInterface::class); - $serviceManager->has($middlewareMatched, true)->willReturn(true); + $serviceManager->has($middlewareMatched)->willReturn(true); $serviceManager->get($middlewareMatched)->willReturn($middleware); $application = $this->prophesize(Application::class); @@ -61,7 +61,7 @@ public function createMvcEvent($middlewareMatched, $middleware = null) public function testSuccessfullyDispatchesMiddleware() { - $event = $this->createMvcEvent('path', function ($request, $response) { + $event = $this->createMvcEvent('path', function ($request, $response) { $this->assertInstanceOf(ServerRequestInterface::class, $request); $this->assertInstanceOf(ResponseInterface::class, $response); $response->getBody()->write('Test!'); @@ -119,12 +119,6 @@ public function testTriggersErrorForExceptionRaisedInMiddleware() /** * Ensure that the listener tests for services in abstract factories. - * - * has() omits abstract factories by default; you must pass an optional - * second parameter, a boolean flag, to indicate it should also search - * those. - * - * This test ensures that. */ public function testCanLoadFromAbstractFactory() { @@ -134,9 +128,8 @@ public function testCanLoadFromAbstractFactory() $eventManager = new EventManager(); - $serviceManager = new ServiceManager(['abstract_factories' => [ - TestAsset\MiddlewareAbstractFactory::class, - ]]); + $serviceManager = new ServiceManager(); + $serviceManager->addAbstractFactory(TestAsset\MiddlewareAbstractFactory::class); $application = $this->prophesize(Application::class); $application->getEventManager()->willReturn($eventManager); diff --git a/test/Router/Http/PartTest.php b/test/Router/Http/PartTest.php index 6aeaf7ba7..d7b0bbd1b 100644 --- a/test/Router/Http/PartTest.php +++ b/test/Router/Http/PartTest.php @@ -12,11 +12,12 @@ use ArrayObject; 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\Mvc\Router\RouteInvokableFactory; +use Zend\Mvc\Router\RoutePluginManager; use Zend\ServiceManager\ServiceManager; use Zend\Stdlib\Parameters; use Zend\Stdlib\Request as BaseRequest; @@ -28,16 +29,29 @@ public static function getRoutePlugins() { return new RoutePluginManager(new ServiceManager(), [ 'aliases' => [ - 'Literal' => 'literal', - 'Part' => 'part', - 'Segment' => 'segment', - 'Wildcard' => 'wildcard', - ], - 'invokables' => [ 'literal' => Literal::class, + 'Literal' => Literal::class, 'part' => Part::class, + 'Part' => Part::class, 'segment' => Segment::class, + 'Segment' => Segment::class, 'wildcard' => Wildcard::class, + 'Wildcard' => Wildcard::class, + 'wildCard' => Wildcard::class, + 'WildCard' => Wildcard::class, + ], + 'factories' => [ + Literal::class => RouteInvokableFactory::class, + Part::class => RouteInvokableFactory::class, + Segment::class => RouteInvokableFactory::class, + Wildcard::class => RouteInvokableFactory::class, + + // v2 normalized names + + 'zendmvcrouterhttpliteral' => RouteInvokableFactory::class, + 'zendmvcrouterhttppart' => RouteInvokableFactory::class, + 'zendmvcrouterhttpsegment' => RouteInvokableFactory::class, + 'zendmvcrouterhttpwildcard' => RouteInvokableFactory::class, ], ]); } diff --git a/test/Service/ControllerManagerFactoryTest.php b/test/Service/ControllerManagerFactoryTest.php index 2253ad7f0..5ffc53c58 100644 --- a/test/Service/ControllerManagerFactoryTest.php +++ b/test/Service/ControllerManagerFactoryTest.php @@ -15,7 +15,10 @@ use Zend\Mvc\Service\ControllerPluginManagerFactory; use Zend\Mvc\Service\EventManagerFactory; use Zend\ServiceManager\Config; +use Zend\ServiceManager\Factory\InvokableFactory; use Zend\ServiceManager\ServiceManager; +use ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin; +use ZendTest\Mvc\Controller\TestAsset\SampleController; class ControllerManagerFactoryTest extends TestCase { @@ -33,19 +36,21 @@ public function setUp() { $loaderFactory = new ControllerManagerFactory(); $this->defaultServiceConfig = [ - 'invokables' => [ + 'aliases' => [ 'SharedEventManager' => SharedEventManager::class, ], 'factories' => [ 'ControllerManager' => $loaderFactory, 'ControllerPluginManager' => ControllerPluginManagerFactory::class, 'EventManager' => EventManagerFactory::class, + SharedEventManager::class => InvokableFactory::class, ], 'services' => [ 'config' => [], ], ]; - $this->services = new ServiceManager($this->defaultServiceConfig); + $this->services = new ServiceManager(); + (new Config($this->defaultServiceConfig))->configureServiceManager($this->services); } public function testCannotLoadInvalidDispatchable() @@ -67,9 +72,10 @@ public function testCannotLoadInvalidDispatchable() public function testCannotLoadControllerFromPeer() { - $services = new ServiceManager(array_merge_recursive($this->defaultServiceConfig, ['services' => [ + $services = new ServiceManager(); + (new Config(array_merge_recursive($this->defaultServiceConfig, ['services' => [ 'foo' => $this, - ]])); + ]])))->configureServiceManager($services); $loader = $services->get('ControllerManager'); $this->setExpectedException('Zend\ServiceManager\Exception\ExceptionInterface'); @@ -79,9 +85,8 @@ public function testCannotLoadControllerFromPeer() public function testControllerLoadedCanBeInjectedWithValuesFromPeer() { $loader = $this->services->get('ControllerManager'); - $loader = $loader->withConfig(['invokables' => [ - 'ZendTest\Dispatchable' => TestAsset\Dispatchable::class, - ]]); + $loader->setAlias('ZendTest\Dispatchable', TestAsset\Dispatchable::class); + $loader->setFactory(TestAsset\Dispatchable::class, InvokableFactory::class); $controller = $loader->get('ZendTest\Dispatchable'); $this->assertInstanceOf(TestAsset\Dispatchable::class, $controller); @@ -92,19 +97,12 @@ public function testControllerLoadedCanBeInjectedWithValuesFromPeer() public function testCallPluginWithControllerPluginManager() { $controllerPluginManager = $this->services->get('ControllerPluginManager'); - $controllerPluginManager = $controllerPluginManager->withConfig([ - 'invokables' => [ - 'samplePlugin' => 'ZendTest\Mvc\Controller\Plugin\TestAsset\SamplePlugin', - ], - ]); + $controllerPluginManager->setAlias('samplePlugin', SamplePlugin::class); + $controllerPluginManager->setFactory(SamplePlugin::class, InvokableFactory::class); - $controller = new \ZendTest\Mvc\Controller\TestAsset\SampleController; + $controller = new 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 new file mode 100644 index 000000000..3a7cf65ac --- /dev/null +++ b/test/Service/DiFactoryTest.php @@ -0,0 +1,26 @@ +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 new file mode 100644 index 000000000..37535c54c --- /dev/null +++ b/test/Service/DiStrictAbstractServiceFactoryTest.php @@ -0,0 +1,84 @@ +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->prophesize(ServiceLocatorInterface::class); + $locator->willImplement(ContainerInterface::class); + + $this->assertTrue($instance->canCreateServiceWithName( + $locator->reveal(), + 'a-whitelisted-service-name', + 'a-whitelisted-service-name' + )); + $this->assertInstanceOf( + 'stdClass', + $instance->createServiceWithName( + $locator->reveal(), + 'a-whitelisted-service-name', + 'a-whitelisted-service-name' + ) + ); + + $this->assertFalse($instance->canCreateServiceWithName( + $locator->reveal(), + 'not-whitelisted', + 'not-whitelisted' + )); + + $this->setExpectedException('Zend\ServiceManager\Exception\InvalidServiceException'); + $instance->createServiceWithName($locator->reveal(), '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/HttpMethodListenerFactoryTest.php b/test/Service/HttpMethodListenerFactoryTest.php index 67daf78e5..95ccc5594 100644 --- a/test/Service/HttpMethodListenerFactoryTest.php +++ b/test/Service/HttpMethodListenerFactoryTest.php @@ -9,6 +9,7 @@ namespace ZendTest\Mvc\Service; +use Interop\Container\ContainerInterface; use PHPUnit_Framework_TestCase as TestCase; use PHPUnit_Framework_MockObject_MockObject as MockObject; use Zend\Mvc\Service\HttpMethodListenerFactory; @@ -26,13 +27,14 @@ class HttpMethodListenerFactoryTest extends TestCase public function setUp() { - $this->serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + $this->serviceLocator = $this->prophesize(ServiceLocatorInterface::class); + $this->serviceLocator->willImplement(ContainerInterface::class); } public function testCreateWithDefaults() { $factory = new HttpMethodListenerFactory(); - $listener = $factory($this->serviceLocator, 'HttpMethodListener'); + $listener = $factory($this->serviceLocator->reveal(), 'HttpMethodListener'); $this->assertTrue($listener->isEnabled()); $this->assertNotEmpty($listener->getAllowedMethods()); } @@ -44,13 +46,10 @@ public function testCreateWithConfig() 'allowed_methods' => ['FOO', 'BAR'] ]; - $this->serviceLocator->expects($this->atLeastOnce()) - ->method('get') - ->with('config') - ->willReturn($config); + $this->serviceLocator->get('config')->willReturn($config); $factory = new HttpMethodListenerFactory(); - $listener = $factory($this->serviceLocator, 'HttpMethodListener'); + $listener = $factory($this->serviceLocator->reveal(), 'HttpMethodListener'); $listenerConfig = $config['http_methods_listener']; diff --git a/test/Service/HydratorManagerFactoryTest.php b/test/Service/HydratorManagerFactoryTest.php index 256780d01..2dd8943a3 100644 --- a/test/Service/HydratorManagerFactoryTest.php +++ b/test/Service/HydratorManagerFactoryTest.php @@ -20,6 +20,7 @@ public function setUp() { $this->factory = new HydratorManagerFactory(); $this->services = $this->prophesize(ServiceLocatorInterface::class); + $this->services->willImplement(ContainerInterface::class); $this->services->get('config')->willReturn([]); } diff --git a/test/Service/InjectTemplateListenerFactoryTest.php b/test/Service/InjectTemplateListenerFactoryTest.php index 6b8aa560e..ea355cf94 100644 --- a/test/Service/InjectTemplateListenerFactoryTest.php +++ b/test/Service/InjectTemplateListenerFactoryTest.php @@ -10,8 +10,10 @@ namespace ZendTest\Mvc\Service; use ArrayObject; +use Interop\Container\ContainerInterface; use PHPUnit_Framework_TestCase as TestCase; use Zend\Mvc\Service\InjectTemplateListenerFactory; +use Zend\ServiceManager\ServiceLocatorInterface; /** * Tests for {@see \Zend\Mvc\Service\InjectTemplateListenerFactory} @@ -59,13 +61,13 @@ public function testFactoryCanSetControllerMapViaArrayAccessVM() */ private function buildInjectTemplateListenerWithConfig($config) { - /* @var $serviceLocator \Zend\ServiceManager\ServiceLocatorInterface|\PHPUnit_Framework_MockObject_MockObject */ - $serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + $serviceLocator = $this->prophesize(ServiceLocatorInterface::class); + $serviceLocator->willImplement(ContainerInterface::class); - $serviceLocator->expects($this->any())->method('get')->with('config')->will($this->returnValue($config)); + $serviceLocator->get('config')->willReturn($config); $factory = new InjectTemplateListenerFactory(); - $listener = $factory($serviceLocator, 'InjectTemplateListener'); + $listener = $factory($serviceLocator->reveal(), 'InjectTemplateListener'); $this->assertInstanceOf('Zend\Mvc\View\Http\InjectTemplateListener', $listener); diff --git a/test/Service/RouterFactoryTest.php b/test/Service/RouterFactoryTest.php index 8fe4485db..f5edfd4a2 100644 --- a/test/Service/RouterFactoryTest.php +++ b/test/Service/RouterFactoryTest.php @@ -14,6 +14,7 @@ use Zend\Mvc\Service\ConsoleRouterFactory; use Zend\Mvc\Service\HttpRouterFactory; use Zend\Mvc\Service\RouterFactory; +use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; class RouterFactoryTest extends TestCase @@ -24,7 +25,7 @@ public function setUp() 'factories' => [ 'ConsoleRouter' => ConsoleRouterFactory::class, 'HttpRouter' => HttpRouterFactory::class, - 'RoutePluginManager' => function ($services, $name, array $options = null) { + 'RoutePluginManager' => function ($services) { return new RoutePluginManager($services); }, ], @@ -35,7 +36,7 @@ public function setUp() public function testFactoryCanCreateRouterBasedOnConfiguredName() { - $services = new ServiceManager(array_merge_recursive($this->defaultServiceConfig, [ + $config = new Config(array_merge_recursive($this->defaultServiceConfig, [ 'services' => [ 'config' => [ 'router' => [ 'router_class' => 'ZendTest\Mvc\Service\TestAsset\Router', @@ -47,6 +48,8 @@ public function testFactoryCanCreateRouterBasedOnConfiguredName() ], ]], ])); + $services = new ServiceManager(); + $config->configureServiceManager($services); $router = $this->factory->__invoke($services, 'router'); $this->assertInstanceOf('ZendTest\Mvc\Service\TestAsset\Router', $router); @@ -54,13 +57,15 @@ public function testFactoryCanCreateRouterBasedOnConfiguredName() public function testFactoryCanCreateRouterWhenOnlyHttpRouterConfigPresent() { - $services = new ServiceManager(array_merge_recursive($this->defaultServiceConfig, [ + $config = new Config(array_merge_recursive($this->defaultServiceConfig, [ 'services' => [ 'config' => [ 'router' => [ 'router_class' => 'ZendTest\Mvc\Service\TestAsset\Router', ], ]], ])); + $services = new ServiceManager(); + $config->configureServiceManager($services); $router = $this->factory->__invoke($services, 'router'); $this->assertInstanceOf('Zend\Mvc\Router\Console\SimpleRouteStack', $router); diff --git a/test/Service/ServiceManagerConfigTest.php b/test/Service/ServiceManagerConfigTest.php index ef63793a4..938abed9b 100644 --- a/test/Service/ServiceManagerConfigTest.php +++ b/test/Service/ServiceManagerConfigTest.php @@ -10,6 +10,7 @@ namespace ZendTest\Mvc\Service; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionClass; use stdClass; use Zend\EventManager\EventManager; use Zend\Mvc\Service\ServiceManagerConfig; @@ -37,7 +38,27 @@ class ServiceManagerConfigTest extends TestCase protected function setUp() { $this->config = new ServiceManagerConfig(); - $this->services = $this->config->configureServiceManager(new ServiceManager()); + $this->services = new ServiceManager(); + $this->config->configureServiceManager($this->services); + } + + /** + * Create an event manager instance based on zend-eventmanager version + * + * @param null|\Zend\EventManager\SharedEventManagerInterface + * @return EventManager + */ + protected function createEventManager($sharedManager = null) + { + $r = new ReflectionClass(EventManager::class); + + if ($r->hasMethod('setSharedManager')) { + $events = new EventManager(); + $events->setSharedManager($sharedManager ?: $this->services->get('SharedEventManager')); + return $events; + } + + return new EventManager($sharedManager ?: $this->services->get('SharedEventManager')); } /** @@ -45,17 +66,16 @@ protected function setUp() */ public function testEventManagerAwareInterfaceIsNotInjectedIfPresentButSharedManagerIs() { - $events = new EventManager($this->services->get('SharedEventManager')); + $events = $this->createEventManager(); TestAsset\EventManagerAwareObject::$defaultEvents = $events; - $services = $this->services->withConfig(['invokables' => [ - 'EventManagerAwareObject' => TestAsset\EventManagerAwareObject::class, - ]]); + $this->services->setAlias('EventManagerAwareObject', TestAsset\EventManagerAwareObject::class); + $this->services->setFactory(TestAsset\EventManagerAwareObject::class, InvokableFactory::class); - $instance = $services->get('EventManagerAwareObject'); + $instance = $this->services->get('EventManagerAwareObject'); $this->assertInstanceOf(TestAsset\EventManagerAwareObject::class, $instance); $this->assertSame($events, $instance->getEventManager()); - $this->assertSame($services->get('SharedEventManager'), $events->getSharedManager()); + $this->assertSame($this->services->get('SharedEventManager'), $events->getSharedManager()); } /** @@ -74,8 +94,8 @@ public function testCanMergeCustomConfigWithDefaultConfig() ], ]; - $config = new ServiceManagerConfig($custom); - $sm = $config->configureServiceManager(new ServiceManager()); + $sm = new ServiceManager(); + (new ServiceManagerConfig($custom))->configureServiceManager($sm); $this->assertTrue($sm->has('foo')); $this->assertTrue($sm->has('bar')); @@ -98,8 +118,8 @@ public function testCanOverrideDefaultConfigWithCustomConfig() ], ]; - $config = new ServiceManagerConfig($custom); - $sm = $config->configureServiceManager(new ServiceManager()); + $sm = new ServiceManager(); + (new ServiceManagerConfig($custom))->configureServiceManager($sm); $this->assertTrue($sm->has('foo')); $this->assertTrue($sm->has('ModuleManager')); @@ -112,6 +132,29 @@ public function testCanOverrideDefaultConfigWithCustomConfig() */ public function testCanAddDelegators() { + /* + * Create delegator closure + * + * The signature for delegators differs between zend-servicemanager + * v2 and v3, so we must vary the closure used based on the version + * being used when testing. + */ + if (method_exists($this->services, 'configure')) { + // v3 + $delegator = function ($container, $name, $callback, array $options = null) { + $service = $callback(); + $service->bar = 'baz'; + return $service; + }; + } else { + // v2 + $delegator = function ($container, $name, $requestedName, $callback) { + $service = $callback(); + $service->bar = 'baz'; + return $service; + }; + } + $config = [ 'aliases' => [ 'foo' => stdClass::class, @@ -120,18 +163,13 @@ public function testCanAddDelegators() stdClass::class => InvokableFactory::class, ], 'delegators' => [ - stdClass::class => [ - function ($container, $name, $callback, array $options = null) { - $service = $callback(); - $service->bar = 'baz'; - - return $service; - }, - ], + stdClass::class => [ $delegator ], ], ]; - $sm = new ServiceManager((new ServiceManagerConfig($config))->toArray()); + $sm = new ServiceManager(); + (new ServiceManagerConfig($config))->configureServiceManager($sm); + $std = $sm->get('foo'); $this->assertInstanceOf(stdClass::class, $std); $this->assertEquals('baz', $std->bar); @@ -154,9 +192,21 @@ public function testEventManagerInitializerCanBeReplaced() }, ], ]); - $serviceManager = $config->configureServiceManager(new ServiceManager()); + $serviceManager = new ServiceManager(); + $config->configureServiceManager($serviceManager); + + /* + * Need to vary the order of arguments the initializer receives based on + * which zend-servicemanager version is being tested against. + */ + if (method_exists($this->services, 'configure')) { + // v3 + $initializer->expects($this->once())->method('__invoke')->with($serviceManager, $instance); + } else { + // v2 + $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'); diff --git a/test/Service/TranslatorServiceFactoryTest.php b/test/Service/TranslatorServiceFactoryTest.php index feb2a356b..5f0d18eec 100644 --- a/test/Service/TranslatorServiceFactoryTest.php +++ b/test/Service/TranslatorServiceFactoryTest.php @@ -21,22 +21,18 @@ 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(['services' => [ - 'TranslatorPluginManager' => $this->getMock(LoaderPluginManager::class), - ]]); + $this->services = new ServiceManager(); + $this->services->setService('TranslatorPluginManager', $this->prophesize(LoaderPluginManager::class)->reveal()); + $this->services->setAllowOverride(true); } public function testReturnsMvcTranslatorWithTranslatorInterfaceServiceComposedWhenPresent() { - $i18nTranslator = $this->getMock('Zend\I18n\Translator\TranslatorInterface'); - $services = $this->services->withConfig(['services' => [ - TranslatorInterface::class => $i18nTranslator, - ]]); + $i18nTranslator = $this->getMock(TranslatorInterface::class); + $this->services->setService(TranslatorInterface::class, $i18nTranslator); - $translator = $this->factory->__invoke($services); + $translator = $this->factory->__invoke($this->services, TranslatorInterface::class); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertSame($i18nTranslator, $translator->getTranslator()); } @@ -47,7 +43,7 @@ public function testReturnsMvcTranslatorWithDummyTranslatorComposedWhenExtIntlIs $this->markTestSkipped('This test will only run if ext/intl is not present'); } - $translator = $this->factory->__invoke($this->services); + $translator = $this->factory->__invoke($this->services, TranslatorInterface::class); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertInstanceOf('Zend\Mvc\I18n\DummyTranslator', $translator->getTranslator()); } @@ -58,7 +54,7 @@ public function testReturnsMvcTranslatorWithI18nTranslatorComposedWhenNoTranslat $this->markTestSkipped('This test will only run if ext/intl is present'); } - $translator = $this->factory->__invoke($this->services); + $translator = $this->factory->__invoke($this->services, TranslatorInterface::class); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertInstanceOf('Zend\I18n\Translator\Translator', $translator->getTranslator()); } @@ -68,17 +64,15 @@ public function testReturnsTranslatorBasedOnConfigurationWhenNoTranslatorInterfa $config = ['translator' => [ 'locale' => 'en_US', ]]; - $services = $this->services->withConfig(['services' => [ - 'config' => $config, - ]]); + (new ServiceManagerConfig(['services' => ['config' => $config]]))->configureServiceManager($this->services); - $translator = $this->factory->__invoke($services); + $translator = $this->factory->__invoke($this->services, TranslatorInterface::class); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertInstanceOf('Zend\I18n\Translator\Translator', $translator->getTranslator()); return [ 'translator' => $translator->getTranslator(), - 'services' => $services, + 'services' => $this->services, ]; } @@ -101,11 +95,12 @@ public function testSetsPluginManagerFromServiceLocatorBasedOnConfiguration() 'module_listener_options' => [], 'modules' => [], ]; - $config = new ServiceManagerConfig(); - $config = array_merge_recursive($config->toArray(), ['services' => [ + $config = new ServiceManagerConfig(['services' => [ 'ApplicationConfig' => $applicationConfig, ]]); - $serviceLocator = new ServiceManager($config); + $serviceLocator = new ServiceManager(); + $config->configureServiceManager($serviceLocator); + $serviceLocator->setAllowOverride(true); $serviceLocator->get('ModuleManager')->loadModules(); $serviceLocator->get('Application')->bootstrap(); @@ -116,14 +111,13 @@ public function testSetsPluginManagerFromServiceLocatorBasedOnConfiguration() ], ]; - $services = $serviceLocator->withConfig(['services' => [ - 'config' => $config, - ]]); + $serviceLocator->setService('config', $config); + $serviceLocator->setAllowOverride(false); - $translator = $this->factory->__invoke($services); + $translator = $this->factory->__invoke($serviceLocator, TranslatorInterface::class); $this->assertEquals( - $services->get('TranslatorPluginManager'), + $serviceLocator->get('TranslatorPluginManager'), $translator->getPluginManager() ); } @@ -139,10 +133,12 @@ public function testReturnsTranslatorBasedOnConfigurationWhenNoTranslatorInterfa 'module_listener_options' => [], 'modules' => [], ]; - $config = array_merge_recursive((new ServiceManagerConfig())->toArray(), ['services' => [ + $config = new ServiceManagerConfig(['services' => [ 'ApplicationConfig' => $applicationConfig, ]]); - $serviceLocator = new ServiceManager($config); + $serviceLocator = new ServiceManager(); + $config->configureServiceManager($serviceLocator); + $serviceLocator->setAllowOverride(true); $serviceLocator->get('ModuleManager')->loadModules(); $serviceLocator->get('Application')->bootstrap(); @@ -153,16 +149,15 @@ public function testReturnsTranslatorBasedOnConfigurationWhenNoTranslatorInterfa ], ]; - $services = $serviceLocator->withConfig(['services' => [ - 'config' => $config, - ]]); + $serviceLocator->setService('config', $config); + $serviceLocator->setAllowOverride(false); //#5959 //get any plugins with AbstractPluginManagerFactory $routePluginManagerFactory = new RoutePluginManagerFactory; - $routePluginManager = $routePluginManagerFactory($services, 'RoutePluginManager'); + $routePluginManager = $routePluginManagerFactory($serviceLocator, 'RoutePluginManager'); - $translator = $this->factory->__invoke($services); + $translator = $this->factory->__invoke($serviceLocator, TranslatorInterface::class); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertInstanceOf('Zend\I18n\Translator\Translator', $translator->getTranslator()); } @@ -172,7 +167,6 @@ 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')); @@ -184,13 +178,11 @@ public function testPrefersTranslatorInterfaceImplementationOverConfig() $config = ['translator' => [ 'locale' => 'en_US', ]]; - $i18nTranslator = $this->getMock('Zend\I18n\Translator\TranslatorInterface'); - $services = $this->services->withConfig(['services' => [ - 'config' => $config, - 'Zend\I18n\Translator\TranslatorInterface' => $i18nTranslator, - ]]); + $i18nTranslator = $this->getMock(TranslatorInterface::class); + $this->services->setService('config', $config); + $this->services->setService(TranslatorInterface::class, $i18nTranslator); - $translator = $this->factory->__invoke($services); + $translator = $this->factory->__invoke($this->services, TranslatorInterface::class); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertSame($i18nTranslator, $translator->getTranslator()); } @@ -198,10 +190,9 @@ public function testPrefersTranslatorInterfaceImplementationOverConfig() public function testReturnsDummyTranslatorWhenTranslatorConfigIsBooleanFalse() { $config = ['translator' => false]; - $services = $this->services->withConfig(['services' => [ - 'config' => $config, - ]]); - $translator = $this->factory->__invoke($services); + $this->services->setService('config', $config); + + $translator = $this->factory->__invoke($this->services, TranslatorInterface::class); $this->assertInstanceOf('Zend\Mvc\I18n\Translator', $translator); $this->assertInstanceOf('Zend\Mvc\I18n\DummyTranslator', $translator->getTranslator()); } diff --git a/test/Service/ViewHelperManagerFactoryTest.php b/test/Service/ViewHelperManagerFactoryTest.php index e5d105aab..7a6b51a73 100644 --- a/test/Service/ViewHelperManagerFactoryTest.php +++ b/test/Service/ViewHelperManagerFactoryTest.php @@ -9,7 +9,6 @@ namespace ZendTest\Mvc\Service; -use Interop\Container\ContainerInterface; use PHPUnit_Framework_TestCase as TestCase; use ReflectionProperty; use Zend\Console\Console; @@ -62,7 +61,7 @@ public function testConsoleRequestsResultInSilentFailure() $this->services->setService('config', []); $this->services->setService('Request', new ConsoleRequest()); - $manager = $this->factory->__invoke($services, 'ViewHelperManager'); + $manager = $this->factory->__invoke($this->services, 'ViewHelperManager'); $doctype = $manager->get('doctype'); $this->assertInstanceof('Zend\View\Helper\Doctype', $doctype); @@ -91,7 +90,7 @@ public function testConsoleRequestWithBasePathConsole() ] ]); - $manager = $this->factory->__invoke($services, 'ViewHelperManager'); + $manager = $this->factory->__invoke($this->services, 'ViewHelperManager'); $basePath = $manager->get('basepath'); $this->assertEquals('http://test.com', $basePath()); @@ -157,7 +156,7 @@ public function basePathConfiguration() 'request-base' => [[ 'config' => [], // fails creating plugin manager without this - 'request' => function () { + 'Request' => function () { $request = $this->prophesize(Request::class); $request->getBasePath()->willReturn('/foo/bat'); return $request->reveal(); diff --git a/test/Service/ViewPrefixPathStackResolverFactoryTest.php b/test/Service/ViewPrefixPathStackResolverFactoryTest.php index 87a5d251b..e339fef9a 100644 --- a/test/Service/ViewPrefixPathStackResolverFactoryTest.php +++ b/test/Service/ViewPrefixPathStackResolverFactoryTest.php @@ -9,28 +9,27 @@ namespace ZendTest\Mvc\Service; +use Interop\Container\ContainerInterface; use Zend\Mvc\Service\ViewPrefixPathStackResolverFactory; +use Zend\ServiceManager\ServiceLocatorInterface; class ViewPrefixPathStackResolverFactoryTest extends \PHPUnit_Framework_TestCase { public function testCreateService() { - /* @var $serviceLocator \Zend\ServiceManager\ServiceLocatorInterface|\PHPUnit_Framework_MockObject_MockObject */ - $serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + $serviceLocator = $this->prophesize(ServiceLocatorInterface::class); + $serviceLocator->willImplement(ContainerInterface::class); - $serviceLocator->expects($this->once()) - ->method('get') - ->with('config') - ->will($this->returnValue([ - 'view_manager' => [ - 'prefix_template_path_stack' => [ - 'album/' => [], - ], + $serviceLocator->get('config')->willReturn([ + 'view_manager' => [ + 'prefix_template_path_stack' => [ + 'album/' => [], ], - ])); + ], + ]); $factory = new ViewPrefixPathStackResolverFactory(); - $resolver = $factory($serviceLocator, 'ViewPrefixPathStackResolver'); + $resolver = $factory($serviceLocator->reveal(), 'ViewPrefixPathStackResolver'); $this->assertInstanceOf('Zend\View\Resolver\PrefixPathStackResolver', $resolver); } diff --git a/test/TestAsset/MiddlewareAbstractFactory.php b/test/TestAsset/MiddlewareAbstractFactory.php index 3f84d678b..63c5b9379 100644 --- a/test/TestAsset/MiddlewareAbstractFactory.php +++ b/test/TestAsset/MiddlewareAbstractFactory.php @@ -10,7 +10,8 @@ namespace ZendTest\Mvc\TestAsset; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\AbstractFactoryInterface; +use Zend\ServiceManager\AbstractFactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; class MiddlewareAbstractFactory implements AbstractFactoryInterface { @@ -18,7 +19,7 @@ class MiddlewareAbstractFactory implements AbstractFactoryInterface 'test' => 'ZendTest\Mvc\TestAsset\Middleware', ); - public function canCreateServiceWithName(ContainerInterface $container, $name) + public function canCreate(ContainerInterface $container, $name) { if (! isset($this->classmap[$name])) { return false; @@ -33,4 +34,28 @@ public function __invoke(ContainerInterface $container, $name, array $options = $classname = $this->classmap[$name]; return new $classname; } + + /** + * {@inheritDoc} + * + * For use with zend-servicemanager v2; proxies to canCreate(). + */ + public function canCreateServiceWithName(ServiceLocatorInterface $container, $name, $requestedName) + { + return $this->canCreate($container, $requestedName); + } + + /** + * Create and return callable instance + * + * For use with zend-servicemanager v2; proxies to __invoke(). + * + * {@inheritDoc} + * + * @return callable + */ + public function createServiceWithName(ServiceLocatorInterface $container, $name, $requestedName) + { + return $this($container, $requestedName); + } } diff --git a/test/View/Console/CreateViewModelListenerTest.php b/test/View/Console/CreateViewModelListenerTest.php index 61f09087d..9b8be496a 100644 --- a/test/View/Console/CreateViewModelListenerTest.php +++ b/test/View/Console/CreateViewModelListenerTest.php @@ -11,14 +11,14 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\EventManager\EventManager; +use Zend\EventManager\Test\EventListenerIntrospectionTrait; use Zend\Mvc\MvcEvent; use Zend\Mvc\View\Console\CreateViewModelListener; use Zend\View\Model\ConsoleModel; -use ZendTest\Mvc\EventManagerIntrospectionTrait; class CreateViewModelListenerTest extends TestCase { - use EventManagerIntrospectionTrait; + use EventListenerIntrospectionTrait; public function setUp() { diff --git a/test/View/Console/DefaultRenderingStrategyTest.php b/test/View/Console/DefaultRenderingStrategyTest.php index 25eea159c..999c9f8ce 100644 --- a/test/View/Console/DefaultRenderingStrategyTest.php +++ b/test/View/Console/DefaultRenderingStrategyTest.php @@ -12,17 +12,17 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\Console\Adapter\AbstractAdapter; use Zend\EventManager\EventManager; +use Zend\EventManager\Test\EventListenerIntrospectionTrait; use Zend\Mvc\ApplicationInterface; use Zend\Mvc\MvcEvent; use Zend\Mvc\View\Console\DefaultRenderingStrategy; use Zend\ServiceManager\ServiceManager; use Zend\Stdlib\Response; use Zend\View\Model; -use ZendTest\Mvc\EventManagerIntrospectionTrait; class DefaultRenderingStrategyTest extends TestCase { - use EventManagerIntrospectionTrait; + use EventListenerIntrospectionTrait; /** @var DefaultRenderingStrategy */ protected $strategy; @@ -67,9 +67,8 @@ public function testIgnoresNonConsoleModelNotContainingResultKeyWhenObtainingRes ->willReturnArgument(0); //Register console service - $sm = new ServiceManager(['services' => [ - 'console' => $console, - ]]); + $sm = new ServiceManager(); + $sm->setService('console', $console); /* @var \PHPUnit_Framework_MockObject_MockObject|ApplicationInterface $mockApplication */ $mockApplication = $this->getMock(ApplicationInterface::class); @@ -99,9 +98,8 @@ public function testIgnoresNonModel() ->willReturnArgument(0); //Register console service - $sm = new ServiceManager(['services' => [ - 'console' => $console, - ]]); + $sm = new ServiceManager(); + $sm->setService('console', $console); /* @var \PHPUnit_Framework_MockObject_MockObject|ApplicationInterface $mockApplication */ $mockApplication = $this->getMock(ApplicationInterface::class); diff --git a/test/View/Console/ExceptionStrategyTest.php b/test/View/Console/ExceptionStrategyTest.php index 814aac2a0..1233ce9ed 100644 --- a/test/View/Console/ExceptionStrategyTest.php +++ b/test/View/Console/ExceptionStrategyTest.php @@ -12,14 +12,14 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\Console\Response; use Zend\EventManager\EventManager; +use Zend\EventManager\Test\EventListenerIntrospectionTrait; use Zend\Mvc\Application; use Zend\Mvc\MvcEvent; use Zend\Mvc\View\Console\ExceptionStrategy; -use ZendTest\Mvc\EventManagerIntrospectionTrait; class ExceptionStrategyTest extends TestCase { - use EventManagerIntrospectionTrait; + use EventListenerIntrospectionTrait; protected $strategy; diff --git a/test/View/Console/ViewManagerTest.php b/test/View/Console/ViewManagerTest.php index 4bd7aea5d..64ec9b658 100644 --- a/test/View/Console/ViewManagerTest.php +++ b/test/View/Console/ViewManagerTest.php @@ -10,6 +10,7 @@ namespace ZendTest\Mvc\View\Console; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionClass; use ReflectionProperty; use Zend\Console\Request as ConsoleRequest; use Zend\Console\Response as ConsoleResponse; @@ -22,7 +23,6 @@ use Zend\Mvc\Service\ServiceManagerConfig; use Zend\Mvc\View\Console\ViewManager; use Zend\ServiceManager\ServiceManager; -use Zend\Stdlib\ArrayUtils; /** * Tests for {@see \Zend\Mvc\View\Console\ViewManager} @@ -48,10 +48,29 @@ class ViewManagerTest extends TestCase public function setUp() { - $this->services = new ServiceManager($this->prepareServiceManagerConfig()); + $this->services = new ServiceManager(); + $this->prepareServiceManagerConfig()->configureServiceManager($this->services); $this->factory = new ConsoleViewManagerFactory(); } + /** + * Create an event manager instance based on zend-eventmanager version + * + * @return EventManager + */ + protected function createEventManager() + { + $r = new ReflectionClass(EventManager::class); + + if ($r->hasMethod('setSharedManager')) { + $events = new EventManager(); + $events->setSharedManager(new SharedEventManager()); + return $events; + } + + return new EventManager(new SharedEventManager()); + } + private function prepareServiceManagerConfig() { $serviceListener = new ServiceListenerFactory(); @@ -59,7 +78,7 @@ private function prepareServiceManagerConfig() $r->setAccessible(true); $config = $r->getValue($serviceListener); - return ArrayUtils::merge((new ServiceManagerConfig())->toArray(), $config); + return new ServiceManagerConfig($config); } /** @@ -120,27 +139,27 @@ public function viewManagerConfiguration() */ public function testConsoleKeyWillOverrideDisplayExceptionAndExceptionMessage($config) { - $eventManager = new EventManager(new SharedEventManager()); + $eventManager = $this->createEventManager(); $request = new ConsoleRequest(); $response = new ConsoleResponse(); - $services = $this->services->withConfig(['services' => [ - 'config' => $config, - 'Request' => $request, - 'EventManager' => $eventManager, - 'Response' => $response, - ]]); + $this->services->setAllowOverride(true); + $this->services->setService('config', $config); + $this->services->setService('EventManager', $eventManager); + $this->services->setService('Request', $request); + $this->services->setService('Response', $response); + $this->services->setAllowOverride(false); - $manager = $this->factory->__invoke($services, 'ConsoleViewRenderer'); + $manager = $this->factory->__invoke($this->services, 'ConsoleViewRenderer'); - $application = new Application($config, $services, $eventManager, $request, $response); + $application = new Application($config, $this->services, $eventManager, $request, $response); $event = new MvcEvent(); $event->setApplication($application); $manager->onBootstrap($event); - $this->assertFalse($services->get('ConsoleExceptionStrategy')->displayExceptions()); - $this->assertFalse($services->get('ConsoleRouteNotFoundStrategy')->displayNotFoundReason()); + $this->assertFalse($this->services->get('ConsoleExceptionStrategy')->displayExceptions()); + $this->assertFalse($this->services->get('ConsoleRouteNotFoundStrategy')->displayNotFoundReason()); } /** @@ -148,31 +167,29 @@ public function testConsoleKeyWillOverrideDisplayExceptionAndExceptionMessage($c */ public function testConsoleDisplayExceptionIsTrue() { - $eventManager = new EventManager(new SharedEventManager()); + $eventManager = $this->createEventManager(); $request = new ConsoleRequest(); $response = new ConsoleResponse(); - $services = $this->services->withConfig([ - 'services' => [ - 'config' => [], - 'Request' => $request, - 'EventManager' => $eventManager, - 'Response' => $response, - ], - ]); + $this->services->setAllowOverride(true); + $this->services->setService('config', []); + $this->services->setService('EventManager', $eventManager); + $this->services->setService('Request', $request); + $this->services->setService('Response', $response); + $this->services->setAllowOverride(false); $manager = new ViewManager; - $application = new Application([], $services, $eventManager, $request, $response); + $application = new Application([], $this->services, $eventManager, $request, $response); $event = new MvcEvent(); $event->setApplication($application); $manager->onBootstrap($event); - $exceptionStrategy = $services->get('ConsoleExceptionStrategy'); + $exceptionStrategy = $this->services->get('ConsoleExceptionStrategy'); $this->assertInstanceOf('Zend\Mvc\View\Console\ExceptionStrategy', $exceptionStrategy); $this->assertTrue($exceptionStrategy->displayExceptions()); - $routeNotFoundStrategy = $services->get('ConsoleRouteNotFoundStrategy'); + $routeNotFoundStrategy = $this->services->get('ConsoleRouteNotFoundStrategy'); $this->assertInstanceOf('Zend\Mvc\View\Console\RouteNotFoundStrategy', $routeNotFoundStrategy); $this->assertTrue($routeNotFoundStrategy->displayNotFoundReason()); } diff --git a/test/View/CreateViewModelListenerTest.php b/test/View/CreateViewModelListenerTest.php index a77f318e4..3a390cfac 100644 --- a/test/View/CreateViewModelListenerTest.php +++ b/test/View/CreateViewModelListenerTest.php @@ -12,13 +12,13 @@ use PHPUnit_Framework_TestCase as TestCase; use stdClass; use Zend\EventManager\EventManager; +use Zend\EventManager\Test\EventListenerIntrospectionTrait; use Zend\Mvc\MvcEvent; use Zend\Mvc\View\Http\CreateViewModelListener; -use ZendTest\Mvc\EventManagerIntrospectionTrait; class CreateViewModelListenerTest extends TestCase { - use EventManagerIntrospectionTrait; + use EventListenerIntrospectionTrait; public function setUp() { diff --git a/test/View/DefaultRendereringStrategyTest.php b/test/View/DefaultRendereringStrategyTest.php index 87f242a78..b794b6379 100644 --- a/test/View/DefaultRendereringStrategyTest.php +++ b/test/View/DefaultRendereringStrategyTest.php @@ -12,22 +12,23 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\EventManager\Event; use Zend\EventManager\EventManager; +use Zend\EventManager\Test\EventListenerIntrospectionTrait; use Zend\Http\Request; use Zend\Http\Response; use Zend\Mvc\Application; use Zend\Mvc\MvcEvent; use Zend\Mvc\View\Http\DefaultRenderingStrategy; +use Zend\ServiceManager\Config; use Zend\ServiceManager\ServiceManager; use Zend\View\Renderer\PhpRenderer; use Zend\View\View; use Zend\View\Model\ViewModel; use Zend\View\Resolver\TemplateMapResolver; use Zend\View\Strategy\PhpRendererStrategy; -use ZendTest\Mvc\EventManagerIntrospectionTrait; class DefaultRendereringStrategyTest extends TestCase { - use EventManagerIntrospectionTrait; + use EventListenerIntrospectionTrait; protected $event; protected $request; @@ -134,12 +135,13 @@ public function testTriggersRenderErrorEventInCaseOfRenderingException() $model->setTemplate('exception'); $this->event->setViewModel($model); - $services = new ServiceManager([ + $services = new ServiceManager(); + (new Config([ 'invokables' => [ 'SharedEventManager' => 'Zend\EventManager\SharedEventManager', ], 'factories' => [ - 'EventManager' => function ($services, $name, array $options = null) { + 'EventManager' => function ($services) { $sharedEvents = $services->get('SharedEventManager'); $events = new EventManager($sharedEvents); return $events; @@ -152,7 +154,7 @@ public function testTriggersRenderErrorEventInCaseOfRenderingException() 'shared' => [ 'EventManager' => false, ], - ]); + ]))->configureServiceManager($services); $application = new Application([], $services, $services->get('EventManager'), $this->request, $this->response); $this->event->setApplication($application); diff --git a/test/View/ExceptionStrategyTest.php b/test/View/ExceptionStrategyTest.php index 7b8217f0b..1ebbf3648 100644 --- a/test/View/ExceptionStrategyTest.php +++ b/test/View/ExceptionStrategyTest.php @@ -11,15 +11,15 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\EventManager\EventManager; +use Zend\EventManager\Test\EventListenerIntrospectionTrait; use Zend\Http\Response; use Zend\Mvc\Application; use Zend\Mvc\MvcEvent; use Zend\Mvc\View\Http\ExceptionStrategy; -use ZendTest\Mvc\EventManagerIntrospectionTrait; class ExceptionStrategyTest extends TestCase { - use EventManagerIntrospectionTrait; + use EventListenerIntrospectionTrait; public function setUp() { diff --git a/test/View/InjectTemplateListenerTest.php b/test/View/InjectTemplateListenerTest.php index 926f0deb9..43ee4034e 100644 --- a/test/View/InjectTemplateListenerTest.php +++ b/test/View/InjectTemplateListenerTest.php @@ -11,16 +11,16 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\EventManager\EventManager; +use Zend\EventManager\Test\EventListenerIntrospectionTrait; use Zend\Mvc\ModuleRouteListener; use Zend\Mvc\MvcEvent; use Zend\Mvc\Router\RouteMatch; use Zend\Mvc\View\Http\InjectTemplateListener; use Zend\View\Model\ViewModel; -use ZendTest\Mvc\EventManagerIntrospectionTrait; class InjectTemplateListenerTest extends TestCase { - use EventManagerIntrospectionTrait; + use EventListenerIntrospectionTrait; public function setUp() { diff --git a/test/View/InjectViewModelListenerTest.php b/test/View/InjectViewModelListenerTest.php index 9a0830655..1ad2e612c 100644 --- a/test/View/InjectViewModelListenerTest.php +++ b/test/View/InjectViewModelListenerTest.php @@ -11,15 +11,15 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\EventManager\EventManager; +use Zend\EventManager\Test\EventListenerIntrospectionTrait; use Zend\Mvc\MvcEvent; use Zend\Mvc\Router\RouteMatch; use Zend\Mvc\View\Http\InjectViewModelListener; use Zend\View\Model\ViewModel; -use ZendTest\Mvc\EventManagerIntrospectionTrait; class InjectViewModelListenerTest extends TestCase { - use EventManagerIntrospectionTrait; + use EventListenerIntrospectionTrait; public function setUp() { diff --git a/test/View/RouteNotFoundStrategyTest.php b/test/View/RouteNotFoundStrategyTest.php index 8baa31fb6..17f00d26a 100644 --- a/test/View/RouteNotFoundStrategyTest.php +++ b/test/View/RouteNotFoundStrategyTest.php @@ -11,16 +11,16 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\EventManager\EventManager; +use Zend\EventManager\Test\EventListenerIntrospectionTrait; use Zend\Http\Response; use Zend\Mvc\Application; use Zend\Mvc\MvcEvent; use Zend\Mvc\View\Http\RouteNotFoundStrategy; use Zend\View\Model\ViewModel; -use ZendTest\Mvc\EventManagerIntrospectionTrait; class RouteNotFoundStrategyTest extends TestCase { - use EventManagerIntrospectionTrait; + use EventListenerIntrospectionTrait; public function setUp() {