Skip to content
Permalink
Browse files

Add Command factory support.

Makes it easier to use a custom factory, for example with DIC support.
  • Loading branch information...
robertpustulka committed Feb 22, 2018
1 parent 4047bb1 commit 7ebc6af1ed457b3f78447e5d305f00de4c70995a
@@ -0,0 +1,39 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Console;
use InvalidArgumentException;
class CommandFactory implements CommandFactoryInterface
{
/**
* {@inheritDoc}
*/
public function create($className, ConsoleIo $io)
{
if (is_subclass_of($className, Shell::class)) {
return new $className($io);
}
// Command class
$command = new $className();
if (!$command instanceof Command) {
$valid = implode('` or `', [Shell::class, Command::class]);
$message = sprintf('Class `%s` must be an instance of `%s`.', $className, $valid);
throw new InvalidArgumentException($message);
}
return $command;
}
}
@@ -0,0 +1,28 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Console;
/**
* An interface for abstracting creation of command and shell instances.
*/
interface CommandFactoryInterface
{
/**
* The factory method for creating Command and Shell instances.
*
* @param string $className Command/Shell class name.
* @param \Cake\Console\ConsoleIo $io The IO wrapper for the created shell class.
* @return \Cake\Console\Shell|\Cake\Console\Command
*/
public function create($className, ConsoleIo $io);
}
@@ -42,6 +42,13 @@ class CommandRunner implements EventDispatcherInterface
*/
protected $app;
/**
* The application console commands are being run for.
*
* @var \Cake\Console\CommandFactoryInterface
*/
protected $factory;
/**
* The root command name. Defaults to `cake`.
*
@@ -61,11 +68,13 @@ class CommandRunner implements EventDispatcherInterface
*
* @param \Cake\Core\ConsoleApplicationInterface $app The application to run CLI commands for.
* @param string $root The root command name to be removed from argv.
* @param \Cake\Console\CommandFactoryInterface $factory Command factory instance.
*/
public function __construct(ConsoleApplicationInterface $app, $root = 'cake')
public function __construct(ConsoleApplicationInterface $app, $root = 'cake', CommandFactoryInterface $factory = null)
{
$this->setApp($app);
$this->root = $root;
$this->factory = $factory ?: new CommandFactory();
$this->aliases = [
'--version' => 'version',
'--help' => 'help',
@@ -276,11 +285,6 @@ protected function runShell(Shell $shell, array $argv)
*/
protected function createShell($className, ConsoleIo $io)
{
if (is_subclass_of($className, Shell::class)) {
return new $className($io);
}
// Command class
return new $className();
return $this->factory->create($className, $io);
}
}
@@ -0,0 +1,52 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Test\TestCase\Console;
use Cake\Console\CommandFactory;
use Cake\Console\ConsoleIo;
use Cake\TestSuite\TestCase;
use InvalidArgumentException;
use TestApp\Command\DemoCommand;
use TestApp\Shell\SampleShell;
class CommandFactoryTest extends TestCase
{
public function testCreateCommand()
{
$factory = new CommandFactory();
$command = $factory->create(DemoCommand::class, new ConsoleIo());
$this->assertInstanceOf(DemoCommand::class, $command);
}
public function testCreateShell()
{
$factory = new CommandFactory();
$io = new ConsoleIo();
$shell = $factory->create(SampleShell::class, $io);
$this->assertInstanceOf(SampleShell::class, $shell);
$this->assertSame($io, $shell->getIo());
}
public function testInvalid()
{
$factory = new CommandFactory();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Class `Cake\Test\TestCase\Console\CommandFactoryTest` must be an instance of `Cake\Console\Shell` or `Cake\Console\Command`.');
$factory->create(static::class, new ConsoleIo());
}
}
@@ -15,6 +15,7 @@
namespace Cake\Test\Console;
use Cake\Console\CommandCollection;
use Cake\Console\CommandFactoryInterface;
use Cake\Console\CommandRunner;
use Cake\Console\ConsoleIo;
use Cake\Console\Shell;
@@ -319,6 +320,31 @@ public function testRunValidCommandClass()
$this->assertContains('Demo Command!', $messages);
}
/**
* Test using a custom factory
*
* @return void
*/
public function testRunWithCustomFactory()
{
$output = new ConsoleOutput();
$io = $this->getMockIo($output);
$factory = $this->createMock(CommandFactoryInterface::class);
$factory->expects($this->once())
->method('create')
->with(DemoCommand::class, $io)
->willReturn(new DemoCommand());
$app = $this->makeAppWithCommands(['ex' => DemoCommand::class]);
$runner = new CommandRunner($app, 'cake', $factory);
$result = $runner->run(['cake', 'ex'], $io);
$this->assertSame(Shell::CODE_SUCCESS, $result);
$messages = implode("\n", $output->messages());
$this->assertContains('Demo Command!', $messages);
}
/**
* Test running a valid command
*

0 comments on commit 7ebc6af

Please sign in to comment.
You can’t perform that action at this time.