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

Commit

Permalink
Refactored to work with zend-servicemanager v3
Browse files Browse the repository at this point in the history
- All factories implementing `FactoryInterface` and/or
  `AbstractFactoryInterface` were updated to the new interface signatures.

- All plugin managers were updated to the new `AbstractPluginManager` changes.
  Whenever possible, they were rewritten to remove invokables and instead define
  factories and/or aliases.

- Added the `RouteInvokableFactory`, which acts both as a specialized invokable
  factory for route implementations (as they use a `::factory()` method for
  initialization vs a constructor), and an abstract factory for handling FQCN
  route names. The `RoutePluginManager` composes this abstract factory by
  default.

- `Application::init` was updated to pull the fully configured service manager
  from the `ServiceListener` after loading modules.

- The `DispatchListener` now receives its controller manager instance during
  instantiation.

- Separated router factory into 3:

  - `ConsoleRouterFactory` will create a console router
  - `HttpRouterFactory` will create an HTTP router
  - `RouterFactory` delegates to the above two, based on status of
    `Console::isConsole()`

  The above makes it possible to specify the specific router type you want to
  use via configuration, making testing possible.

- Refactored the ViewManager implementations. Previously, the view managers
  were adding services and aliases to the service manager duing their bootstrap
  listeners; with the SM now immutable, that does not make sense, and, in fact,
  leads to errors.

  In all cases where object creation was occuring, the code was moved to new
  factories, which the view manager implementations can now pull specifically.
  Aliases for these were added where appropriate. However, I stopped short of
  adding factories for general services such as `DefaultRenderingStrategy` as
  the implementations differ enough that having such a factory mutate based on
  the selected view manager would require type-hinting to consume the services
  regardless.

- New integration tests for `Application` were written to ensure the SM is in
  correct state for `bootstrap()` and `run()`, and that the service listener <->
  service manager dance is correctly managed.
  • Loading branch information
weierophinney committed Oct 8, 2015
1 parent c6b02a9 commit a46be7d
Show file tree
Hide file tree
Showing 141 changed files with 3,979 additions and 2,529 deletions.
4 changes: 2 additions & 2 deletions 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 All @@ -39,7 +39,7 @@
"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-view": "dev-develop#82c537d8f as 2.6.0",
"fabpot/php-cs-fixer": "1.7.*",
"phpunit/PHPUnit": "~4.0"
},
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
18 changes: 5 additions & 13 deletions src/Controller/Plugin/Service/ForwardFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@

namespace Zend\Mvc\Controller\Plugin\Service;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\Mvc\Controller\Plugin\Forward;

class ForwardFactory implements FactoryInterface
Expand All @@ -22,24 +22,16 @@ class ForwardFactory implements FactoryInterface
* @return Forward
* @throws ServiceNotCreatedException if Controllermanager service is not found in application service locator
*/
public function createService(ServiceLocatorInterface $plugins)
public function __invoke(ContainerInterface $container, $name, array $options = null)
{
$services = $plugins->getServiceLocator();
if (!$services instanceof ServiceLocatorInterface) {
throw new ServiceNotCreatedException(sprintf(
'%s requires that the application service manager has been injected; none found',
__CLASS__
));
}

if (!$services->has('ControllerManager')) {
if (! $container->has('ControllerManager')) {
throw new ServiceNotCreatedException(sprintf(
'%s requires that the application service manager contains a "%s" service; none found',
__CLASS__,
'ControllerManager'
));
}
$controllers = $services->get('ControllerManager');
$controllers = $container->get('ControllerManager');

return new Forward($controllers);
}
Expand Down
12 changes: 6 additions & 6 deletions src/Controller/Plugin/Service/IdentityFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@

namespace Zend\Mvc\Controller\Plugin\Service;

use Interop\Container\ContainerInterface;
use Zend\Authentication\AuthenticationService;
use Zend\Mvc\Controller\Plugin\Identity;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\Factory\FactoryInterface;

class IdentityFactory implements FactoryInterface
{
Expand All @@ -20,12 +21,11 @@ class IdentityFactory implements FactoryInterface
*
* @return \Zend\Mvc\Controller\Plugin\Identity
*/
public function createService(ServiceLocatorInterface $serviceLocator)
public function __invoke(ContainerInterface $container, $name, array $options = null)
{
$services = $serviceLocator->getServiceLocator();
$helper = new Identity();
if ($services->has('Zend\Authentication\AuthenticationService')) {
$helper->setAuthenticationService($services->get('Zend\Authentication\AuthenticationService'));
if ($container->has(AuthenticationService::class)) {
$helper->setAuthenticationService($container->get(AuthenticationService::class));
}
return $helper;
}
Expand Down
Loading

0 comments on commit a46be7d

Please sign in to comment.