Browse Source

First pass at building task autodetection.

mark_story 12 years ago
parent
commit
ace0cafcec
2 changed files with 105 additions and 0 deletions
  1. 75 0
      src/Console/Command/BakeShell.php
  2. 30 0
      tests/TestCase/Console/Command/BakeShellTest.php

+ 75 - 0
src/Console/Command/BakeShell.php

@@ -18,6 +18,7 @@ use Cake\Cache\Cache;
 use Cake\Console\Shell;
 use Cake\Core\App;
 use Cake\Core\Configure;
+use Cake\Core\Plugin;
 use Cake\Datasource\ConnectionManager;
 use Cake\Model\Model;
 use Cake\Utility\ConventionsTrait;
@@ -107,6 +108,80 @@ class BakeShell extends Shell {
 	}
 
 /**
+ * Locate the tasks bake will use.
+ *
+ * Scans the following paths for tasks that are subclasses of
+ * Cake\Console\Command\Task\BakeTask:
+ *
+ * - Cake/Console/Command/Task/
+ * - App/Console/Command/Task/
+ * - Console/Command/Task for each loaded plugin
+ *
+ * @return void
+ */
+	public function loadTasks() {
+		$tasks = [];
+		$tasks = $this->_findTasks($tasks, CAKE, 'Cake');
+		$tasks = $this->_findTasks($tasks, APP, Configure::read('App.namespace'));
+		foreach (Plugin::loaded() as $plugin) {
+			$tasks = $this->_findTasks(
+				$tasks,
+				Plugin::path($plugin),
+				Plugin::getNamespace($plugin),
+				$plugin
+			);
+		}
+		$this->tasks = array_values($tasks);
+		parent::loadTasks();
+	}
+
+/**
+ * Append matching tasks in $path to the $tasks array.
+ *
+ * @param array $tasks The task list to modify and return.
+ * @param string $path The base path to look in.
+ * @param string $namespace The base namespace.
+ * @param string $prefix The prefix to append.
+ * @return array Updated tasks.
+ */
+	protected function _findTasks($tasks, $path, $namespace, $prefix = false) {
+		$path .= 'Console/Command/Task';
+		if (!is_dir($path)) {
+			return $tasks;
+		}
+		$iterator = new \DirectoryIterator($path);
+		$candidates = [];
+		foreach ($iterator as $item) {
+			if ($item->isDot() || $item->isDir()) {
+				continue;
+			}
+			$name = $item->getBasename('.php');
+			$candidates[] = $namespace . '\Console\Command\Task\\' . $name;
+		}
+		$classes = [];
+		foreach ($candidates as $classname) {
+			if (!class_exists($classname)) {
+				continue;
+			}
+			$reflect = new \ReflectionClass($classname);
+			if (!$reflect->isInstantiable()) {
+				continue;
+			}
+			if (!$reflect->isSubclassOf('Cake\Console\Command\Task\BakeTask')) {
+				continue;
+			}
+			$classes[] = $classname;
+		}
+		foreach ($classes as $class) {
+			list($ns, $name) = namespaceSplit($class);
+			$name = substr($name, 0, -4);
+			$fullName = ($prefix ? $prefix . '.' : '') . $name;
+			$tasks[$name] = $fullName;
+		}
+		return $tasks;
+	}
+
+/**
  * Quickly bake the MVC
  *
  * @return void

+ 30 - 0
tests/TestCase/Console/Command/BakeShellTest.php

@@ -111,4 +111,34 @@ class BakeShellTest extends TestCase {
 		$this->Shell->main();
 	}
 
+/**
+ * Test loading tasks from core and app directories.
+ *
+ * @return void
+ */
+	public function testLoadTasks() {
+		$this->Shell->loadTasks();
+		$expected = [
+			'Behavior',
+			'Component',
+			'Controller',
+			'Fixture',
+			'Helper',
+			'Model',
+			'Plugin',
+			'Project',
+			'Test',
+			'View'
+		];
+		$this->assertEquals($expected, $this->Shell->tasks);
+	}
+
+/**
+ * Test loading tasks from plugins
+ *
+ * @return void
+ */
+	public function testLoadTasksPlugin() {
+	}
+
 }