Browse Source

Add support for Commands to autodiscovery.

Expand autodiscovery in CommandCollection to include Commands.
Also exclude files that dont have the right suffix to prevent #11326 in
the future.

Refs #11326
Refs #11137
Mark Story 8 years ago
parent
commit
1eb3dcbdac
2 changed files with 39 additions and 15 deletions
  1. 35 15
      src/Console/CommandScanner.php
  2. 4 0
      tests/TestCase/Console/CommandCollectionTest.php

+ 35 - 15
src/Console/CommandScanner.php

@@ -36,30 +36,46 @@ class CommandScanner
     public function scanAll()
     {
         $shellList = [];
-
         $appNamespace = Configure::read('App.namespace');
-        $shellList['app'] = $this->scanDir(
+
+        $coreShells = $this->scanDir(
+            dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Shell' . DIRECTORY_SEPARATOR,
+            'Cake\Shell\\',
+            '',
+            ['command_list']
+        );
+        $coreCommands = $this->scanDir(
+            dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Command' . DIRECTORY_SEPARATOR,
+            'Cake\Command\\',
+            '',
+            ['command_list']
+        );
+        $shellList['CORE'] = array_merge($coreShells, $coreCommands);
+
+        $appShells = $this->scanDir(
             App::path('Shell')[0],
             $appNamespace . '\Shell\\',
             '',
             ['app']
         );
-
-        $shellList['CORE'] = $this->scanDir(
-            dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Shell' . DIRECTORY_SEPARATOR,
-            'Cake\Shell\\',
+        $appCommands = $this->scanDir(
+            App::path('Command')[0],
+            $appNamespace . '\Command\\',
             '',
-            ['command_list']
+            ['app']
         );
+        $shellList['app'] = array_merge($appShells, $appCommands);
 
         $plugins = [];
         foreach (Plugin::loaded() as $plugin) {
-            $plugins[$plugin] = $this->scanDir(
-                Plugin::classPath($plugin) . 'Shell',
-                str_replace('/', '\\', $plugin) . '\Shell\\',
-                Inflector::underscore($plugin) . '.',
-                []
-            );
+            $path = Plugin::classPath($plugin);
+            $namespace = str_replace('/', '\\', $plugin);
+            $prefix = Inflector::underscore($plugin) . '.';
+
+            $commands = $this->scanDir($path . 'Command', $namespace . '\Command\\', $prefix, []);
+            $shells = $this->scanDir($path . 'Shell', $namespace . '\Shell\\', $prefix, []);
+
+            $plugins[$plugin] = array_merge($shells, $commands);
         }
         $shellList['plugins'] = $plugins;
 
@@ -84,14 +100,18 @@ class CommandScanner
             return [];
         }
 
+        $classPattern = '/(Shell|Command)$/';
         $shells = [];
         foreach ($contents[1] as $file) {
             if (substr($file, -4) !== '.php') {
                 continue;
             }
-
             $shell = substr($file, 0, -4);
-            $name = Inflector::underscore(str_replace('Shell', '', $shell));
+            if (!preg_match($classPattern, $shell)) {
+                continue;
+            }
+
+            $name = Inflector::underscore(preg_replace($classPattern, '', $shell));
             if (in_array($name, $hide, true)) {
                 continue;
             }

+ 4 - 0
tests/TestCase/Console/CommandCollectionTest.php

@@ -203,10 +203,12 @@ class CommandCollectionTest extends TestCase
         $collection = new CommandCollection();
         $collection->addMany($collection->autoDiscover());
 
+        $this->assertTrue($collection->has('demo'));
         $this->assertTrue($collection->has('i18m'));
         $this->assertTrue($collection->has('sample'));
         $this->assertTrue($collection->has('testing_dispatch'));
 
+        $this->assertSame('TestApp\Command\DemoCommand', $collection->get('demo'));
         $this->assertSame('TestApp\Shell\I18mShell', $collection->get('i18m'));
         $this->assertSame('TestApp\Shell\SampleShell', $collection->get('sample'));
     }
@@ -221,6 +223,7 @@ class CommandCollectionTest extends TestCase
         $collection = new CommandCollection();
         $collection->addMany($collection->autoDiscover());
 
+        $this->assertTrue($collection->has('version'));
         $this->assertTrue($collection->has('routes'));
         $this->assertTrue($collection->has('i18n'));
         $this->assertTrue($collection->has('orm_cache'));
@@ -231,6 +234,7 @@ class CommandCollectionTest extends TestCase
         // These have to be strings as ::class uses the local namespace.
         $this->assertSame('Cake\Shell\RoutesShell', $collection->get('routes'));
         $this->assertSame('Cake\Shell\I18nShell', $collection->get('i18n'));
+        $this->assertSame('Cake\Command\VersionCommand', $collection->get('version'));
     }
 
     /**