Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Refactored to work with zend-servicemanager v3 #36

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,57 @@ All notable changes to this project will be documented in this file, in reverse
- [#31](https://github.com/zendframework/zend-mvc/pull/31) adds three required
arguments to the `Zend\Mvc\Application` constructor: an EventManager
instance, a Request instance, and a Response instance.
- [#36](https://github.com/zendframework/zend-mvc/pull/36) adds more than a
dozen service factories, primarily to separate conditional factories into
discrete factories.

### Deprecated

- Nothing.

### Removed

- Nothing.
- [#36](https://github.com/zendframework/zend-mvc/pull/36) removes
`Zend\Mvc\Service\ConfigFactory`, as the functionality is now incorporated
into `Zend\ModuleManager\Listener\ServiceListener`.
- [#36](https://github.com/zendframework/zend-mvc/pull/36) removes
the `ServiceLocatorAware` intializer, as zend-servicemanager v3 no longer
defines the interface.
- [#36](https://github.com/zendframework/zend-mvc/pull/36) removes
`Zend\Mvc\Service\ControllerLoaderFactory` and replaces it with
`Zend\Mvc\Service\ControllerManagerFactory`.
- [#36](https://github.com/zendframework/zend-mvc/pull/36) removes
`Zend\Mvc\Service\DiFactory`, `Zend\Mvc\Service\DiAbstractServiceFactory`,
`Zend\Mvc\Service\DiStrictAbstractServiceFactory`,
`Zend\Mvc\Service\DiStrictAbstractServiceFactoryFactory`,
and `Zend\Mvc\Service\DiServiceInitializerFactory`, as zend-servicemanager v3
removes `Zend\Di` integration.

### Fixed

- [#31](https://github.com/zendframework/zend-mvc/pull/31) updates the component
to use zend-eventmanager v3.
- [#36](https://github.com/zendframework/zend-mvc/pull/36) updates the component
to use zend-servicemanager v3, and zend-modulemanager v3. This involves:
- Updating all factories implementing either `FactoryInterface` or
`AbstractFactoryInterface` to the new signatures of those interfaces.
- Updating all plugin managers to the updates to `AbstractPluginManager`.
- Updating how plugin manager factories work (they're now passed the container
instance in their constructor arguments, as well as any build options).
- Added a `RouteInvokableFactory`, which can act as either a
`FactoryInterface` or `AbstractFactoryInterface` for loading invokable route
classes, including by fully qualified class name. This is registered as an
abstract factory by default with the `RoutePluginManager`.
- The `DispatchListener` now receives the controller manager instance at
instantiation.
- The `ViewManager` implementations were updated, and most functionality
within separated into discrete factories. (Previously these instances
injected services and aliases into the service manager instance, which is no
longer possible or desirable with the zend-servicemanager v3 changes.)
- `Application::init()` now pulls the configured service manager from the
`Zend\ModuleManager\Listener\ServiceListener` instance before retrieving and
bootstrapping the `Application` instance; this ensure it is fully
configured at that time.

## 2.6.1 - TBD

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"require": {
"php": ">=5.5",
"zendframework/zend-eventmanager": "dev-develop as 2.7.0",
"zendframework/zend-servicemanager": "~2.5",
"zendframework/zend-servicemanager": "dev-develop as 2.6.0",
"zendframework/zend-hydrator": "~1.0",
"zendframework/zend-form": "~2.6",
"zendframework/zend-stdlib": "~2.7",
Expand Down
26 changes: 21 additions & 5 deletions src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public function __construct(
*/
public function getConfig()
{
return $this->serviceManager->get('Config');
return $this->serviceManager->get('config');
}

/**
Expand All @@ -140,9 +140,10 @@ public function getConfig()
*/
public function bootstrap(array $listeners = [])
{
$serviceManager = $this->serviceManager;
$events = $this->events;
$serviceManager = $this->serviceManager;

// Setup default listeners
$listeners = array_unique(array_merge($this->defaultListeners, $listeners));

foreach ($listeners as $listener) {
Expand All @@ -160,6 +161,7 @@ public function bootstrap(array $listeners = [])

// Trigger bootstrap events
$events->triggerEvent($event);

return $this;
}

Expand Down Expand Up @@ -252,13 +254,27 @@ public function getEventManager()
*/
public static function init($configuration = [])
{
// Prepare the service manager
$smConfig = isset($configuration['service_manager']) ? $configuration['service_manager'] : [];
$serviceManager = new ServiceManager(new Service\ServiceManagerConfig($smConfig));
$serviceManager->setService('ApplicationConfig', $configuration);
$smConfig = new Service\ServiceManagerConfig($smConfig);

$serviceManager = new ServiceManager($smConfig->toArray());
$serviceManager = $serviceManager->withConfig(['services' => [
'ApplicationConfig' => $configuration,
]]);

// Load modules
$serviceManager->get('ModuleManager')->loadModules();

// Get the configured SM if necessary.
if ($serviceManager->has('ServiceListener')) {
$serviceListener = $serviceManager->get('ServiceListener');
$serviceManager = $serviceListener->getConfiguredServiceManager();
}

// Prepare list of listeners to bootstrap
$listenersFromAppConfig = isset($configuration['listeners']) ? $configuration['listeners'] : [];
$config = $serviceManager->get('Config');
$config = $serviceManager->get('config');
$listenersFromConfigService = isset($config['listeners']) ? $config['listeners'] : [];

$listeners = array_unique(array_merge($listenersFromConfigService, $listenersFromAppConfig));
Expand Down
34 changes: 3 additions & 31 deletions src/Controller/AbstractController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
use Zend\Http\Request as HttpRequest;
use Zend\Mvc\InjectApplicationEventInterface;
use Zend\Mvc\MvcEvent;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\Stdlib\DispatchableInterface as Dispatchable;
use Zend\Stdlib\RequestInterface as Request;
use Zend\Stdlib\ResponseInterface as Response;
Expand Down Expand Up @@ -46,8 +45,7 @@
abstract class AbstractController implements
Dispatchable,
EventManagerAwareInterface,
InjectApplicationEventInterface,
ServiceLocatorAwareInterface
InjectApplicationEventInterface
{
/**
* @var PluginManager
Expand All @@ -74,11 +72,6 @@ abstract class AbstractController implements
*/
protected $events;

/**
* @var ServiceLocatorInterface
*/
protected $serviceLocator;

/**
* @var null|string|string[]
*/
Expand Down Expand Up @@ -231,27 +224,6 @@ public function getEvent()
return $this->event;
}

/**
* Set serviceManager instance
*
* @param ServiceLocatorInterface $serviceLocator
* @return void
*/
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}

/**
* Retrieve serviceManager instance
*
* @return ServiceLocatorInterface
*/
public function getServiceLocator()
{
return $this->serviceLocator;
}

/**
* Get plugin manager
*
Expand All @@ -260,7 +232,7 @@ public function getServiceLocator()
public function getPluginManager()
{
if (!$this->plugins) {
$this->setPluginManager(new PluginManager());
$this->setPluginManager(new PluginManager(new ServiceManager()));
}

$this->plugins->setController($this);
Expand Down
119 changes: 40 additions & 79 deletions src/Controller/ControllerManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@

namespace Zend\Mvc\Controller;

use Interop\Container\ContainerInterface;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\SharedEventManagerInterface;
use Zend\Mvc\Exception;
use Zend\ServiceManager\AbstractPluginManager;
use Zend\ServiceManager\ConfigInterface;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Stdlib\DispatchableInterface;

/**
Expand All @@ -25,113 +22,77 @@
*/
class ControllerManager extends AbstractPluginManager
{
/**
* We do not want arbitrary classes instantiated as controllers.
*
* @var bool
*/
protected $autoAddInvokableClass = false;
protected $instanceOf = DispatchableInterface::class;

/**
* Constructor
*
* After invoking parent constructor, add an initializer to inject the
* service manager, event manager, and plugin manager
* Injects an initializer for injecting controllers with an
* event manager and plugin manager.
*
* @param null|ConfigInterface $configuration
* @param ContainerInterface $container
* @param array $configuration
*/
public function __construct(ConfigInterface $configuration = null)
public function __construct(ContainerInterface $container, array $configuration = [])
{
parent::__construct($configuration);
// Pushing to bottom of stack to ensure this is done last
$this->addInitializer([$this, 'injectControllerDependencies'], false);
$this->initializers[] = [$this, 'injectEventManager'];
$this->initializers[] = [$this, 'injectConsole'];
$this->initializers[] = [$this, 'injectPluginManager'];
parent::__construct($container, $configuration);
}

/**
* Inject required dependencies into the controller.
* Initializer: inject EventManager instance
*
* If we have an event manager composed already, make sure it gets injected
* with the shared event manager.
*
* The AbstractController lazy-instantiates an EM instance, which is why
* the shared EM injection needs to happen; the conditional will always
* pass.
*
* @param DispatchableInterface $controller
* @param ServiceLocatorInterface $serviceLocator
* @return void
* @param ContainerInterface $container
* @param DispatchableInterface $controller
*/
public function injectControllerDependencies($controller, ServiceLocatorInterface $serviceLocator)
public function injectEventManager(ContainerInterface $container, $controller)
{
if (!$controller instanceof DispatchableInterface) {
if (! $controller instanceof EventManagerAwareInterface) {
return;
}

$parentLocator = $serviceLocator->getServiceLocator();

if ($controller instanceof ServiceLocatorAwareInterface) {
$controller->setServiceLocator($parentLocator->get('Zend\ServiceManager\ServiceLocatorInterface'));
}

if ($controller instanceof EventManagerAwareInterface) {
// If we have an event manager composed already, make sure it gets
// injected with the shared event manager.
// The AbstractController lazy-instantiates an EM instance, which
// is why the shared EM injection needs to happen; the conditional
// will always pass.
$events = $controller->getEventManager();
if (! $events || ! $events->getSharedManager() instanceof SharedEventManagerInterface) {
$controller->setEventManager($parentLocator->get('EventManager'));
}
}

if ($controller instanceof AbstractConsoleController) {
$controller->setConsole($parentLocator->get('Console'));
}

if (method_exists($controller, 'setPluginManager')) {
$controller->setPluginManager($parentLocator->get('ControllerPluginManager'));
$events = $controller->getEventManager();
if (! $events || ! $events->getSharedManager() instanceof SharedEventManagerInterface) {
$controller->setEventManager($container->get('EventManager'));
}
}

/**
* Validate the plugin
*
* Ensure we have a dispatchable.
* Initializer: inject Console adapter instance
*
* @param mixed $plugin
* @return true
* @throws Exception\InvalidControllerException
* @param ContainerInterface $container
* @param DispatchableInterface $controller
*/
public function validatePlugin($plugin)
public function injectConsole(ContainerInterface $container, $controller)
{
if ($plugin instanceof DispatchableInterface) {
// we're okay
if (! $controller instanceof AbstractConsoleController) {
return;
}

throw new Exception\InvalidControllerException(sprintf(
'Controller of type %s is invalid; must implement Zend\Stdlib\DispatchableInterface',
(is_object($plugin) ? get_class($plugin) : gettype($plugin))
));
$controller->setConsole($container->get('Console'));
}

/**
* Override: do not use peering service managers
* Initializer: inject plugin manager
*
* @param string|array $name
* @param bool $checkAbstractFactories
* @param bool $usePeeringServiceManagers
* @return bool
* @param ContainerInterface $container
* @param DispatchableInterface $controller
*/
public function has($name, $checkAbstractFactories = true, $usePeeringServiceManagers = false)
public function injectPluginManager(ContainerInterface $container, $controller)
{
return parent::has($name, $checkAbstractFactories, $usePeeringServiceManagers);
}
if (! method_exists($controller, 'setPluginManager')) {
return;
}

/**
* Override: do not use peering service managers
*
* @param string $name
* @param array $options
* @param bool $usePeeringServiceManagers
* @return mixed
*/
public function get($name, $options = [], $usePeeringServiceManagers = false)
{
return parent::get($name, $options, $usePeeringServiceManagers);
$controller->setPluginManager($container->get('ControllerPluginManager'));
}
}
5 changes: 4 additions & 1 deletion src/Controller/Plugin/Forward.php
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,10 @@ protected function getEvent()

$controller = $this->getController();
if (!$controller instanceof InjectApplicationEventInterface) {
throw new Exception\DomainException('Forward plugin requires a controller that implements InjectApplicationEventInterface');
throw new Exception\DomainException(sprintf(
'Forward plugin requires a controller that implements InjectApplicationEventInterface; received %s',
(is_object($controller) ? get_class($controller) : var_export($controller, 1))
));
}

$event = $controller->getEvent();
Expand Down
Loading