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

Ensure console (and controller!) usage works for v2 applications #81

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
27 changes: 27 additions & 0 deletions src/Controller/AbstractController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Zend\Http\Request as HttpRequest;
use Zend\Mvc\InjectApplicationEventInterface;
use Zend\Mvc\MvcEvent;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\Stdlib\DispatchableInterface as Dispatchable;
use Zend\Stdlib\RequestInterface as Request;
Expand Down Expand Up @@ -62,6 +63,11 @@ abstract class AbstractController implements
*/
protected $response;

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

/**
* @var Event
*/
Expand Down Expand Up @@ -224,6 +230,27 @@ 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 Down
52 changes: 52 additions & 0 deletions src/Controller/ControllerManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Zend\ServiceManager\AbstractPluginManager;
use Zend\ServiceManager\ConfigInterface;
use Zend\ServiceManager\Exception\InvalidServiceException;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\Stdlib\DispatchableInterface;

/**
Expand Down Expand Up @@ -54,6 +55,10 @@ public function __construct($configOrContainerInstance, array $v3config = [])
$this->addInitializer([$this, 'injectConsole']);
$this->addInitializer([$this, 'injectPluginManager']);
parent::__construct($configOrContainerInstance, $v3config);

// Added after parent construction, as v2 abstract plugin managers add
// one during construction.
$this->addInitializer([$this, 'injectServiceLocator']);
}

/**
Expand Down Expand Up @@ -191,4 +196,51 @@ public function injectPluginManager($first, $second)

$controller->setPluginManager($container->get('ControllerPluginManager'));
}

/**
* Initializer: inject service locator
*
* @param ContainerInterface|DispatchableInterface $first Container when
* using zend-servicemanager v3; controller under v2.
* @param DispatchableInterface|ContainerInterface $second Controller when
* using zend-servicemanager v3; container under v2.
*/
public function injectServiceLocator($first, $second)
{
printf("In %s\n", __METHOD__);
if ($first instanceof ContainerInterface) {
$container = $first;
$controller = $second;
} else {
$container = $second;
$controller = $first;
}

// For v2, we need to pull the parent service locator
if (! method_exists($container, 'configure')) {
$container = $container->getServiceLocator() ?: $container;
}

if (! $controller instanceof ServiceLocatorAwareInterface
&& method_exists($controller, 'setServiceLocator')
) {
trigger_error(sprintf(
'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along '
. 'with the ServiceLocatorAwareInitializer. Please update your class %s to remove '
. 'the implementation, and start injecting your dependencies via factory instead.',
get_class($controller)
), E_USER_DEPRECATED);
$controller->setServiceLocator($container);
}

if ($controller instanceof ServiceLocatorAwareInterface) {
trigger_error(sprintf(
'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along '
. 'with the ServiceLocatorAwareInitializer. Please update your class %s to remove '
. 'the implementation, and start injecting your dependencies via factory instead.',
get_class($controller)
), E_USER_DEPRECATED);
$controller->setServiceLocator($container);
}
}
}
14 changes: 8 additions & 6 deletions src/Router/Console/SimpleRouteStack.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ protected function init()
Simple::class => RouteInvokableFactory::class,

// v2 normalized names
'zendmvcrouterconsoleCatchall' => RouteInvokableFactory::class,
'zendmvcrouterconsoleSimple' => RouteInvokableFactory::class,
'zendmvcrouterconsolecatchall' => RouteInvokableFactory::class,
'zendmvcrouterconsolesimple' => RouteInvokableFactory::class,
],
]))->configureServiceManager($this->routePluginManager);
}
Expand Down Expand Up @@ -79,19 +79,21 @@ 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');
}

// default to 'simple' console route
if (!isset($specs['type'])) {
$specs['type'] = 'simple';
if (! isset($specs['type'])) {
$specs['type'] = Simple::class;
}

// build route object
$route = parent::routeFromArray($specs);

if (!$route instanceof RouteInterface) {
if (! $route instanceof RouteInterface) {
throw new Exception\RuntimeException('Given route does not implement Console route interface');
}

Expand Down
10 changes: 8 additions & 2 deletions src/Service/RouterFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,16 @@ public function __invoke(ContainerInterface $container, $name, array $options =
* For use with zend-servicemanager v2; proxies to __invoke().
*
* @param ServiceLocatorInterface $container
* @param null|string $normalizedName
* @param null|string $requestedName
* @return RouteStackInterface
*/
public function createService(ServiceLocatorInterface $container)
public function createService(ServiceLocatorInterface $container, $normalizedName = null, $requestedName = null)
{
return $this($container, RouteStackInterface::class);
if ($normalizedName === 'router' && Console::isConsole()) {
$requestedName = 'ConsoleRouter';
}

return $this($container, $requestedName);
}
}
1 change: 1 addition & 0 deletions src/Service/ServiceListenerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class ServiceListenerFactory implements FactoryInterface
'aliases' => [
'Configuration' => 'config',
'configuration' => 'config',
'console' => 'ConsoleAdapter',
'Console' => 'ConsoleAdapter',
'ConsoleDefaultRenderingStrategy' => View\Console\DefaultRenderingStrategy::class,
'ControllerLoader' => 'ControllerManager',
Expand Down
12 changes: 12 additions & 0 deletions src/Service/ServiceManagerConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,18 @@ public function __construct(array $config = [])
), E_USER_DEPRECATED);
$instance->setServiceLocator($container);
}

if (! $instance instanceof ServiceLocatorAwareInterface
&& method_exists($instance, 'setServiceLocator')
) {
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);
}
},
]);

Expand Down
7 changes: 7 additions & 0 deletions test/Application/AllowsReturningEarlyFromRoutingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace ZendTest\Mvc\Application;

use PHPUnit_Framework_Error_Deprecated;
use PHPUnit_Framework_TestCase as TestCase;
use Zend\Http\PhpEnvironment\Response;
use Zend\Mvc\MvcEvent;
Expand All @@ -17,6 +18,12 @@ class AllowsReturningEarlyFromRoutingTest extends TestCase
{
use PathControllerTrait;

public function setUp()
{
// Ignore deprecation errors
PHPUnit_Framework_Error_Deprecated::$enabled = false;
}

public function testAllowsReturningEarlyFromRouting()
{
$application = $this->prepareApplication();
Expand Down
7 changes: 7 additions & 0 deletions test/Application/ControllerIsDispatchedTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@

namespace ZendTest\Mvc\Application;

use PHPUnit_Framework_Error_Deprecated;
use PHPUnit_Framework_TestCase as TestCase;
use Zend\Mvc\MvcEvent;

class ControllerIsDispatchedTest extends TestCase
{
use PathControllerTrait;

public function setUp()
{
// Ignore deprecation errors
PHPUnit_Framework_Error_Deprecated::$enabled = false;
}

public function testControllerIsDispatchedDuringRun()
{
$application = $this->prepareApplication();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@

namespace ZendTest\Mvc\Application;

use PHPUnit_Framework_Error_Deprecated;
use PHPUnit_Framework_TestCase as TestCase;
use Zend\Mvc\MvcEvent;

class ExceptionsRaisedInDispatchableShouldRaiseDispatchErrorEventTest extends TestCase
{
use BadControllerTrait;

public function setUp()
{
// Ignore deprecation errors
PHPUnit_Framework_Error_Deprecated::$enabled = false;
}

/**
* @group error-handling
*/
Expand Down
15 changes: 15 additions & 0 deletions test/Controller/ControllerManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,26 @@

namespace ZendTest\Mvc\Controller;

use PHPUnit_Framework_Error_Deprecated;
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\Factory\InvokableFactory;
use Zend\ServiceManager\ServiceManager;
use Zend\Console\Adapter\Virtual as ConsoleAdapter;
use ZendTest\Mvc\Service\TestAsset\DuckTypedServiceLocatorAwareController;

class ControllerManagerTest extends TestCase
{
public function setUp()
{
// Disable deprecation notices
PHPUnit_Framework_Error_Deprecated::$enabled = false;

$this->sharedEvents = new SharedEventManager;
$this->events = $this->createEventManager($this->sharedEvents);
$this->consoleAdapter = new ConsoleAdapter();
Expand Down Expand Up @@ -145,4 +151,13 @@ public function testDoNotUsePeeringServiceManagers()
$this->setExpectedException('Zend\ServiceManager\Exception\ServiceNotFoundException');
$this->controllers->get('EventManager');
}

public function testServiceLocatorAwareInitializerInjectsDuckTypedImplementations()
{
$this->controllers->setFactory(DuckTypedServiceLocatorAwareController::class, InvokableFactory::class);

$controller = $this->controllers->get(DuckTypedServiceLocatorAwareController::class);
$this->assertInstanceOf(DuckTypedServiceLocatorAwareController::class, $controller);
$this->assertSame($this->services, $controller->getServiceLocator());
}
}
4 changes: 4 additions & 0 deletions test/Controller/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace ZendTest\Mvc\Controller;

use PHPUnit_Framework_Error_Deprecated;
use PHPUnit_Framework_TestCase as TestCase;
use Zend\EventManager\EventManager;
use Zend\EventManager\SharedEventManager;
Expand All @@ -21,6 +22,9 @@ class IntegrationTest extends TestCase
{
public function setUp()
{
// Ignore deprecation errors
PHPUnit_Framework_Error_Deprecated::$enabled = false;

$this->sharedEvents = new SharedEventManager();

$this->services = new ServiceManager();
Expand Down
4 changes: 4 additions & 0 deletions test/Controller/Plugin/ForwardTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace ZendTest\Mvc\Controller\Plugin;

use PHPUnit_Framework_Error_Deprecated;
use PHPUnit_Framework_TestCase as TestCase;
use ReflectionClass;
use stdClass;
Expand Down Expand Up @@ -51,6 +52,9 @@ class ForwardTest extends TestCase

public function setUp()
{
// Ignore deprecation errors
PHPUnit_Framework_Error_Deprecated::$enabled = false;

$eventManager = $this->createEventManager(new SharedEventManager());
$mockApplication = $this->getMock('Zend\Mvc\ApplicationInterface');
$mockApplication->expects($this->any())->method('getEventManager')->will($this->returnValue($eventManager));
Expand Down
46 changes: 46 additions & 0 deletions test/Router/Console/SimpleRouteStackTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zend-mvc for the canonical source repository
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace ZendTest\Mvc\Router\Console;

use PHPUnit_Framework_TestCase as TestCase;
use Zend\Mvc\Router\Console\Catchall;
use Zend\Mvc\Router\Console\Simple;
use Zend\Mvc\Router\Console\SimpleRouteStack;

class SimpleRouteStackTest extends TestCase
{
public function routeTypeProvider()
{
$catchallOpts = ['defaults' => []];
$simpleOpts = ['route' => 'test'];

return [
'catchall' => ['catchall', $catchallOpts, Catchall::class],
'catchAll' => ['catchAll', $catchallOpts, Catchall::class],
'Catchall' => ['Catchall', $catchallOpts, Catchall::class],
'CatchAll' => ['CatchAll', $catchallOpts, Catchall::class],
'simple' => ['simple', $simpleOpts, Simple::class],
'Simple' => ['Simple', $simpleOpts, Simple::class],

Catchall::class => [Catchall::class, $catchallOpts, Catchall::class],
Simple::class => [Simple::class, $simpleOpts, Simple::class],
];
}

/**
* @dataProvider routeTypeProvider
*/
public function testExpectedAliasesAndFactoriesResolve($serviceName, array $options, $expected)
{
$router = new SimpleRouteStack();
$routes = $router->getRoutePluginManager();
$this->assertInstanceOf($expected, $routes->get($serviceName, $options));
}
}
Loading