Skip to content

Commit

Permalink
Load routing in console environments.
Browse files Browse the repository at this point in the history
Ensure that the CommandRunner framework uses the application routes()
hook to load routes. This enables the routes shell and other
commands/shells to generate URLs properly.

Refs #12030
  • Loading branch information
markstory committed May 1, 2018
1 parent 0cb6d51 commit 933151f
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 11 deletions.
19 changes: 19 additions & 0 deletions src/Console/CommandRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Cake\Event\EventDispatcherInterface;
use Cake\Event\EventDispatcherTrait;
use Cake\Event\EventManager;
use Cake\Routing\Router;
use Cake\Utility\Inflector;
use InvalidArgumentException;
use RuntimeException;
Expand Down Expand Up @@ -145,6 +146,7 @@ public function run(array $argv, ConsoleIo $io = null)
}
$this->checkCollection($commands, 'pluginConsole');
$this->dispatchEvent('Console.buildCommands', ['commands' => $commands]);
$this->loadRoutes();

if (empty($argv)) {
throw new RuntimeException("Cannot run any commands. No arguments received.");
Expand Down Expand Up @@ -358,4 +360,21 @@ protected function createShell($className, ConsoleIo $io)

return $shell;
}

/**
* Ensure that the application's routes are loaded.
*
* Console commands and shells often need to generate URLs.
*
* @return void
*/
protected function loadRoutes()
{
$builder = Router::createRouteBuilder('/');

$this->app->routes($builder);
if ($this->app instanceof PluginApplicationInterface) {
$this->app->pluginRoutes($builder);
}
}
}
46 changes: 35 additions & 11 deletions tests/TestCase/Console/CommandRunnerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use Cake\Event\EventList;
use Cake\Event\EventManager;
use Cake\Http\BaseApplication;
use Cake\Routing\Router;
use Cake\TestSuite\Stub\ConsoleOutput;
use Cake\TestSuite\TestCase;
use InvalidArgumentException;
Expand Down Expand Up @@ -160,7 +161,7 @@ public function testRunMissingRootCommand()
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Cannot run any commands. No arguments received.');
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap'])
->setMethods(['middleware', 'bootstrap', 'routes'])
->setConstructorArgs([$this->config])
->getMock();

Expand All @@ -178,7 +179,7 @@ public function testRunInvalidCommand()
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Unknown command `cake nope`. Run `cake --help` to get the list of valid commands.');
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap'])
->setMethods(['middleware', 'bootstrap', 'routes'])
->setConstructorArgs([$this->config])
->getMock();

Expand All @@ -194,7 +195,7 @@ public function testRunInvalidCommand()
public function testRunHelpLongOption()
{
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap'])
->setMethods(['middleware', 'bootstrap', 'routes'])
->setConstructorArgs([$this->config])
->getMock();

Expand All @@ -216,7 +217,7 @@ public function testRunHelpLongOption()
public function testRunHelpShortOption()
{
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap'])
->setMethods(['middleware', 'bootstrap', 'routes'])
->setConstructorArgs([$this->config])
->getMock();

Expand All @@ -237,7 +238,7 @@ public function testRunHelpShortOption()
public function testRunNoCommand()
{
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap'])
->setMethods(['middleware', 'bootstrap', 'routes'])
->setConstructorArgs([$this->config])
->getMock();

Expand All @@ -260,7 +261,7 @@ public function testRunNoCommand()
public function testRunVersionAlias()
{
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap'])
->setMethods(['middleware', 'bootstrap', 'routes'])
->setConstructorArgs([$this->config])
->getMock();

Expand All @@ -278,7 +279,7 @@ public function testRunVersionAlias()
public function testRunValidCommand()
{
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap'])
->setMethods(['middleware', 'bootstrap', 'routes'])
->setConstructorArgs([$this->config])
->getMock();

Expand All @@ -301,7 +302,7 @@ public function testRunValidCommand()
public function testRunValidCommandInflection()
{
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap'])
->setMethods(['middleware', 'bootstrap', 'routes'])
->setConstructorArgs([$this->config])
->getMock();

Expand Down Expand Up @@ -432,7 +433,7 @@ public function testRunValidCommandClassHelp()
public function testRunTriggersBuildCommandsEvent()
{
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap'])
->setMethods(['middleware', 'bootstrap', 'routes'])
->setConstructorArgs([$this->config])
->getMock();

Expand All @@ -454,7 +455,10 @@ public function testRunTriggersBuildCommandsEvent()
public function testRunCallsPluginHookMethods()
{
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap', 'pluginBootstrap', 'pluginEvents', 'pluginConsole'])
->setMethods([
'middleware', 'bootstrap', 'routes',
'pluginBootstrap', 'pluginConsole', 'pluginRoutes'
])
->setConstructorArgs([$this->config])
->getMock();

Expand All @@ -468,17 +472,37 @@ public function testRunCallsPluginHookMethods()
->will($this->returnCallback(function ($commands) {
return $commands;
}));
$app->expects($this->at(3))->method('routes');
$app->expects($this->at(4))->method('pluginRoutes');

$output = new ConsoleOutput();
$runner = new CommandRunner($app, 'cake');
$result = $runner->run(['cake', '--version'], $this->getMockIo($output));
$this->assertContains(Configure::version(), $output->messages()[0]);
}

/**
* Test that run() loads routing.
*
* @return void
*/
public function testRunLoadsRoutes()
{
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap'])
->setConstructorArgs([TEST_APP . 'config' . DS])
->getMock();

$output = new ConsoleOutput();
$runner = new CommandRunner($app, 'cake');
$runner->run(['cake', '--version'], $this->getMockIo($output));
$this->assertGreaterThan(2, count(Router::getRouteCollection()->routes()));
}

protected function makeAppWithCommands($commands)
{
$app = $this->getMockBuilder(BaseApplication::class)
->setMethods(['middleware', 'bootstrap', 'console'])
->setMethods(['middleware', 'bootstrap', 'console', 'routes'])
->setConstructorArgs([$this->config])
->getMock();
$collection = new CommandCollection($commands);
Expand Down

0 comments on commit 933151f

Please sign in to comment.