Skip to content
This repository has been archived by the owner on Dec 7, 2019. It is now read-only.

Commit

Permalink
Merge pull request #28 from mtymek/container_aware_dispatcher_2
Browse files Browse the repository at this point in the history
Allow pulling commands from container
  • Loading branch information
weierophinney committed Jul 11, 2016
2 parents d999b4d + 02ce097 commit c275de7
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 7 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,31 @@ The `Route` instance contains several methods of interest:
- `getName()` will return the name of the route (which may be useful if you use the same callable
for multiple routes).

Pulling commands from container
-------------------------------

You can keep your commands in service container, compatible with `container-interop`. In order
to do so, inject your container into `Dispatcher` object upon creation:

```php
$serviceManager = new ServiceManager(/* ... */);

// use `zend-servicemanager` as container
$dispatcher = new Dispatcher($serviceManager);

$routes = [
[
'name' => 'hello',
'handler' => HelloCommand::class,
]
];

$application = new Application('App', 1.0, $routes, null, $dispatcher);
```

In this example, when `hello` route is matched, `Dispatcher` will try to pull `HelloCommand` from
container and then execute it.

Exception Handling
------------------

Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@
"phpunit/phpunit": "~4.7",
"squizlabs/php_codesniffer": "^2.3.1",
"zendframework/zend-filter": "~2.3",
"zendframework/zend-validator": "~2.3"
"zendframework/zend-validator": "~2.3",
"container-interop/container-interop": "^1.1"
},
"suggest": {
"zendframework/zend-filter": "~2.3; Useful for filtering/normalizing argument values",
"zendframework/zend-validator": "~2.3; Useful for providing more thorough argument validation logic"
"zendframework/zend-validator": "~2.3; Useful for providing more thorough argument validation logic",
"container-interop/container-interop": "^1.1; For ability to pull dispatched commands from container"
},
"autoload": {
"psr-4": {
Expand Down
28 changes: 23 additions & 5 deletions src/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

namespace ZF\Console;

use Interop\Container\ContainerInterface;
use InvalidArgumentException;
use RuntimeException;
use Zend\Console\Adapter\AdapterInterface as ConsoleAdapter;
Expand All @@ -15,6 +16,19 @@ class Dispatcher
{
protected $commandMap = [];

/**
* @var ContainerInterface
*/
protected $container;

/**
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container = null)
{
$this->container = $container;
}

public function map($command, $callable)
{
if (! is_string($command) || empty($command)) {
Expand Down Expand Up @@ -56,12 +70,16 @@ public function dispatch(Route $route, ConsoleAdapter $console)
$callable = $this->commandMap[$name];

if (! is_callable($callable) && is_string($callable)) {
$callable = new $callable();
if ($this->container && $this->container->has($callable)) {
$callable = $this->container->get($callable);
} else {
$callable = new $callable();
}

if (! is_callable($callable)) {
throw new RuntimeException(sprintf(
'Invalid command class specified for "%s"; class must be invokable',
$name
));
throw new RuntimeException(
sprintf('Invalid command class specified for "%s"; class must be invokable', $name)
);
}
$this->commandMap[$name] = $callable;
}
Expand Down
23 changes: 23 additions & 0 deletions test/DispatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@

namespace ZFTest\Console;

use Interop\Container\ContainerInterface;
use PHPUnit_Framework_TestCase as TestCase;
use Zend\Console\Adapter\AdapterInterface;
use ZF\Console\Dispatcher;
use ZF\Console\Route;
use ZFTest\Console\TestAsset\FooCommand;

class DispatcherTest extends TestCase
{
/**
* @var Dispatcher
*/
private $dispatcher;

public function setUp()
{
$this->route = $this->getMockBuilder('ZF\Console\Route')
Expand Down Expand Up @@ -91,4 +98,20 @@ public function testDispatchReturnsCallableReturnIntegerOnSuccess()
->will($this->returnValue('test'));
$this->assertEquals(2, $this->dispatcher->dispatch($this->route, $this->console));
}

public function testDispatchCanPullCommandFromContainer()
{
$container = $this->prophesize(ContainerInterface::class);
$container->has(FooCommand::class)->willReturn(true);
$container->get(FooCommand::class)->willReturn(new FooCommand());

$route = $this->prophesize(Route::class);
$route->getName()->willReturn('foobar');

$console = $this->prophesize(AdapterInterface::class);

$dispatcher = new Dispatcher($container->reveal());
$dispatcher->map('foobar', FooCommand::class);
$dispatcher->dispatch($route->reveal(), $console->reveal());
}
}
10 changes: 10 additions & 0 deletions test/TestAsset/FooCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace ZFTest\Console\TestAsset;

class FooCommand
{
public function __invoke()
{
}
}

0 comments on commit c275de7

Please sign in to comment.