Making Tasks lazy load.

This allows task initialization to be moved out of ShellDispatcher where it does not belong, as tasks are similar to components.  Updating parts of TaskCollection, as the Dispatcher is still required to be passed around.
This commit is contained in:
mark_story 2010-10-09 20:55:00 -04:00
parent 4d199cf8a8
commit fbcc9c1fc1
4 changed files with 43 additions and 19 deletions

View file

@ -61,6 +61,13 @@ class Shell extends Object {
*/ */
public $args = array(); public $args = array();
/**
* Shell paths
*
* @var string
*/
public $shellPaths = array();
/** /**
* The file name of the shell that was invoked. * The file name of the shell that was invoked.
* *
@ -132,6 +139,13 @@ class Shell extends Object {
*/ */
public $Tasks; public $Tasks;
/**
* Normalized map of tasks.
*
* @var string
*/
protected $_taskMap = array();
/** /**
* stdout object. * stdout object.
* *
@ -177,7 +191,7 @@ class Shell extends Object {
} }
$this->Dispatch =& $dispatch; $this->Dispatch =& $dispatch;
$this->Tasks = new TaskCollection($this); $this->Tasks = new TaskCollection($this, $dispatch);
$this->stdout = $stdout; $this->stdout = $stdout;
$this->stderr = $stderr; $this->stderr = $stderr;
@ -272,14 +286,28 @@ class Shell extends Object {
if ($this->tasks === true || empty($this->tasks) || empty($this->Tasks)) { if ($this->tasks === true || empty($this->tasks) || empty($this->Tasks)) {
return true; return true;
} }
$tasks = TaskCollection::normalizeObjectArray((array)$this->tasks); $this->_taskMap = TaskCollection::normalizeObjectArray((array)$this->tasks);
foreach ($tasks as $task => $properties) { foreach ($this->_taskMap as $task => $properties) {
$this->{$task} = $this->Tasks->load($properties['class'], $properties['settings']);
$this->taskNames[] = $task; $this->taskNames[] = $task;
} }
return true; return true;
} }
/**
* Overload get for lazy building of tasks
*
* @return void
*/
public function __get($name) {
if (empty($this->{$name}) && in_array($name, $this->taskNames)) {
$properties = $this->_taskMap[$name];
$this->{$name} = $this->Tasks->load($properties['class'], $properties['settings']);
$this->{$name}->initialize();
$this->{$name}->loadTasks();
}
return $this->{$name};
}
/** /**
* Prompts the user for input, and returns it. * Prompts the user for input, and returns it.
* *

View file

@ -25,6 +25,7 @@ class TaskCollection extends ObjectCollection {
* @var array * @var array
*/ */
protected $_Shell; protected $_Shell;
protected $_Dispatch;
/** /**
* Constructor * Constructor
@ -32,8 +33,9 @@ class TaskCollection extends ObjectCollection {
* @param array $paths Array of paths to search for tasks on . * @param array $paths Array of paths to search for tasks on .
* @return void * @return void
*/ */
public function __construct(Shell $Shell) { public function __construct(Shell $Shell, ShellDispatcher $dispatcher) {
$this->_Shell = $Shell; $this->_Shell = $Shell;
$this->_Dispatch = $dispatcher;
} }
/** /**
* Loads/constructs a task. Will return the instance in the registry if it already exists. * Loads/constructs a task. Will return the instance in the registry if it already exists.
@ -61,7 +63,7 @@ class TaskCollection extends ObjectCollection {
} }
$this->_loaded[$name] = new $taskClass( $this->_loaded[$name] = new $taskClass(
$this->_Shell, $this->_Shell->stdout, $this->_Shell->stderr, $this->_Shell->stdin $this->_Dispatch, $this->_Shell->stdout, $this->_Shell->stderr, $this->_Shell->stdin
); );
if ($enable === true) { if ($enable === true) {
$this->_enabled[] = $name; $this->_enabled[] = $name;

View file

@ -184,9 +184,7 @@ class ShellDispatcher {
*/ */
function __buildPaths() { function __buildPaths() {
$paths = array(); $paths = array();
if (!class_exists('Folder')) {
require LIBS . 'folder.php';
}
$plugins = App::objects('plugin', null, false); $plugins = App::objects('plugin', null, false);
foreach ((array)$plugins as $plugin) { foreach ((array)$plugins as $plugin) {
$pluginPath = App::pluginPath($plugin); $pluginPath = App::pluginPath($plugin);
@ -272,17 +270,10 @@ class ShellDispatcher {
$methods = array(); $methods = array();
if ($Shell instanceof Shell) { if ($Shell instanceof Shell) {
$Shell->initialize(); $Shell->initialize();
$Shell->loadTasks(); $Shell->loadTasks();
foreach ($Shell->taskNames as $task) {
if (is_a($Shell->{$task}, 'Shell')) {
$Shell->{$task}->initialize();
$Shell->{$task}->loadTasks();
}
}
$task = Inflector::camelize($arg); $task = Inflector::camelize($arg);
if (in_array($task, $Shell->taskNames)) { if (in_array($task, $Shell->taskNames)) {

View file

@ -30,7 +30,8 @@ class TaskCollectionTest extends CakeTestCase {
function setup() { function setup() {
$shell = $this->getMock('Shell', array(), array(), '', false); $shell = $this->getMock('Shell', array(), array(), '', false);
$shell->shellPaths = App::path('shells'); $shell->shellPaths = App::path('shells');
$this->Tasks = new TaskCollection($shell); $dispatcher = $this->getMock('ShellDispatcher', array(), array(), '', false);
$this->Tasks = new TaskCollection($shell, $dispatcher);
} }
/** /**
@ -86,10 +87,12 @@ class TaskCollectionTest extends CakeTestCase {
* @return void * @return void
*/ */
function testLoadPluginTask() { function testLoadPluginTask() {
$dispatcher = $this->getMock('ShellDispatcher', array(), array(), '', false);
$shell = $this->getMock('Shell', array(), array(), '', false); $shell = $this->getMock('Shell', array(), array(), '', false);
$shell->shellPaths = App::path('shells'); $shell->shellPaths = App::path('shells');
$shell->shellPaths[] = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'plugins' . DS . 'test_plugin' . DS . 'vendors' . DS . 'shells' . DS; $shell->shellPaths[] = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'plugins' . DS . 'test_plugin' . DS . 'vendors' . DS . 'shells' . DS;
$this->Tasks = new TaskCollection($shell); $dispatcher->shellPaths = $shell->shellPaths;
$this->Tasks = new TaskCollection($shell, $dispatcher);
$result = $this->Tasks->load('TestPlugin.OtherTask'); $result = $this->Tasks->load('TestPlugin.OtherTask');
$this->assertType('OtherTaskTask', $result, 'Task class is wrong.'); $this->assertType('OtherTaskTask', $result, 'Task class is wrong.');