Browse Source

Handle StopException in ShellDispatcher.

The ShellDispatcher should drop exception messages, and use the
exception code as the exit code. Also add a default error code of
1 which will be non-zero making shell environments behave correctly.
Mark Story 10 years ago
parent
commit
a723f6b1ba

+ 1 - 1
src/Console/Shell.php

@@ -723,7 +723,7 @@ class Shell
      * @return void
      * @link http://book.cakephp.org/3.0/en/console-and-shells.html#styling-output
      */
-    public function abort($message, $exitCode)
+    public function abort($message, $exitCode = self::CODE_ERROR)
     {
         $this->_io->err('<error>' . $message . '</error>');
         throw new StopException($message, $exitCode);

+ 6 - 1
src/Console/ShellDispatcher.php

@@ -15,6 +15,7 @@
 namespace Cake\Console;
 
 use Cake\Console\Exception\MissingShellException;
+use Cake\Console\Exception\StopException;
 use Cake\Core\App;
 use Cake\Core\Configure;
 use Cake\Core\Exception\Exception;
@@ -176,7 +177,11 @@ class ShellDispatcher
      */
     public function dispatch($extra = [])
     {
-        $result = $this->_dispatch($extra);
+        try {
+            $result = $this->_dispatch($extra);
+        } catch (StopException $e) {
+            return $e->getCode();
+        }
         if ($result === null || $result === true) {
             return 0;
         }

+ 26 - 0
tests/TestCase/Console/ShellDispatcherTest.php

@@ -149,6 +149,32 @@ class ShellDispatcherTest extends TestCase
     }
 
     /**
+     * Verify dispatch handling stop errors
+     *
+     * @return void
+     */
+    public function testDispatchShellWithAbort()
+    {
+        $io = $this->getMock('Cake\Console\ConsoleIo');
+        $shell = $this->getMock('Cake\Console\Shell', ['main'], [$io]);
+        $shell->expects($this->once())
+            ->method('main')
+            ->will($this->returnCallback(function () use ($shell) {
+                $shell->abort('Bad things', 99);
+            }));
+
+        $dispatcher = $this->getMock('Cake\Console\ShellDispatcher', ['findShell']);
+        $dispatcher->expects($this->any())
+            ->method('findShell')
+            ->with('aborter')
+            ->will($this->returnValue($shell));
+
+        $dispatcher->args = ['aborter'];
+        $result = $dispatcher->dispatch();
+        $this->assertSame(99, $result, 'Should return the exception error code.');
+    }
+
+    /**
      * Verify correct dispatch of Shell subclasses with a main method
      *
      * @return void