Browse Source

Add autoMethod parameter to runCommand()

This argument allows tasks to be shielded from the RAD feature that
allows shells to have any public method invoked. Tasks, will need to
have their subcommands explictly defined.
mark_story 12 years ago
parent
commit
3f036e61bb
3 changed files with 27 additions and 6 deletions
  1. 5 3
      src/Console/Shell.php
  2. 1 1
      src/Console/ShellDispatcher.php
  3. 21 2
      tests/TestCase/Console/ShellTest.php

+ 5 - 3
src/Console/Shell.php

@@ -335,10 +335,12 @@ class Shell {
  * @param string $command The command name to run on this shell. If this argument is empty,
  *   and the shell has a `main()` method, that will be called instead.
  * @param array $argv Array of arguments to run the shell with. This array should be missing the shell name.
+ * @param boolean $autoMethod Set to true to allow any public method to be called even if it
+ *   was not defined as a subcommand. This is used by ShellDispatcher to make building simple shells easy.
  * @return void
  * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::runCommand
  */
-	public function runCommand($argv) {
+	public function runCommand($argv, $autoMethod = false) {
 		$command = isset($argv[0]) ? $argv[0] : null;
 		$this->OptionParser = $this->getOptionParser();
 		try {
@@ -367,7 +369,7 @@ class Shell {
 		$subcommands = $this->OptionParser->subcommands();
 		$isMethod = $this->hasMethod($command);
 
-		if ($isMethod && count($subcommands) === 0) {
+		if ($isMethod && $autoMethod && count($subcommands) === 0) {
 			array_shift($this->args);
 			$this->startup();
 			return call_user_func_array([$this, $command], $this->args);
@@ -382,7 +384,7 @@ class Shell {
 			$this->startup();
 			$command = Inflector::camelize($command);
 			array_shift($argv);
-			return $this->{$command}->runCommand($argv);
+			return $this->{$command}->runCommand($argv, false);
 		}
 
 		if ($this->hasMethod('main')) {

+ 1 - 1
src/Console/ShellDispatcher.php

@@ -160,7 +160,7 @@ class ShellDispatcher {
 		$Shell = $this->findShell($shell);
 
 		$Shell->initialize();
-		return $Shell->runCommand($this->args);
+		return $Shell->runCommand($this->args, true);
 	}
 
 /**

+ 21 - 2
tests/TestCase/Console/ShellTest.php

@@ -548,11 +548,30 @@ class ShellTest extends TestCase {
 		$shell->expects($this->once())->method('hit_me')
 			->with('cakes')
 			->will($this->returnValue(true));
-		$result = $shell->runCommand(['hit_me', 'cakes', '--verbose']);
+		$result = $shell->runCommand(['hit_me', 'cakes', '--verbose'], true);
 		$this->assertTrue($result);
 	}
 
 /**
+ * Test that runCommand() doesn't call public methods when the second arg is false.
+ *
+ * @return void
+ */
+	public function testRunCommandAutoMethodOff() {
+		$io = $this->getMock('Cake\Console\ConsoleIo');
+		$shell = $this->getMock('Cake\Console\Shell', ['hit_me', 'startup'], [$io]);
+
+		$shell->expects($this->never())->method('startup');
+		$shell->expects($this->never())->method('hit_me');
+
+		$result = $shell->runCommand(['hit_me', 'baseball'], false);
+		$this->assertFalse($result);
+
+		$result = $shell->runCommand(['hit_me', 'baseball']);
+		$this->assertFalse($result, 'Default value of runCommand() should be false');
+	}
+
+/**
  * test run command calling a real method with mismatching subcommands defined.
  *
  * @return void
@@ -718,7 +737,7 @@ class ShellTest extends TestCase {
 		$task = $this->getMock('Cake\Console\Shell', ['main', 'runCommand'], [], '', false);
 		$task->expects($this->once())
 			->method('runCommand')
-			->with(['one']);
+			->with(['one'], false);
 
 		$shell->expects($this->once())->method('getOptionParser')
 			->will($this->returnValue($parser));