From fbcc9c1fc1f88ddf46e30488d6f66ac6310139f2 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 9 Oct 2010 20:55:00 -0400 Subject: [PATCH] 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. --- cake/console/libs/shell.php | 36 ++++++++++++++++--- cake/console/libs/task_collection.php | 6 ++-- cake/console/shell_dispatcher.php | 13 ++----- .../console/libs/task_collection.test.php | 7 ++-- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/cake/console/libs/shell.php b/cake/console/libs/shell.php index 720cfcc7e..a15da2e50 100644 --- a/cake/console/libs/shell.php +++ b/cake/console/libs/shell.php @@ -61,6 +61,13 @@ class Shell extends Object { */ public $args = array(); +/** + * Shell paths + * + * @var string + */ + public $shellPaths = array(); + /** * The file name of the shell that was invoked. * @@ -132,6 +139,13 @@ class Shell extends Object { */ public $Tasks; +/** + * Normalized map of tasks. + * + * @var string + */ + protected $_taskMap = array(); + /** * stdout object. * @@ -177,7 +191,7 @@ class Shell extends Object { } $this->Dispatch =& $dispatch; - $this->Tasks = new TaskCollection($this); + $this->Tasks = new TaskCollection($this, $dispatch); $this->stdout = $stdout; $this->stderr = $stderr; @@ -272,14 +286,28 @@ class Shell extends Object { if ($this->tasks === true || empty($this->tasks) || empty($this->Tasks)) { return true; } - $tasks = TaskCollection::normalizeObjectArray((array)$this->tasks); - foreach ($tasks as $task => $properties) { - $this->{$task} = $this->Tasks->load($properties['class'], $properties['settings']); + $this->_taskMap = TaskCollection::normalizeObjectArray((array)$this->tasks); + foreach ($this->_taskMap as $task => $properties) { $this->taskNames[] = $task; } 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. * diff --git a/cake/console/libs/task_collection.php b/cake/console/libs/task_collection.php index a3b162166..eecd3f578 100644 --- a/cake/console/libs/task_collection.php +++ b/cake/console/libs/task_collection.php @@ -25,6 +25,7 @@ class TaskCollection extends ObjectCollection { * @var array */ protected $_Shell; + protected $_Dispatch; /** * Constructor @@ -32,8 +33,9 @@ class TaskCollection extends ObjectCollection { * @param array $paths Array of paths to search for tasks on . * @return void */ - public function __construct(Shell $Shell) { + public function __construct(Shell $Shell, ShellDispatcher $dispatcher) { $this->_Shell = $Shell; + $this->_Dispatch = $dispatcher; } /** * 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->_Shell, $this->_Shell->stdout, $this->_Shell->stderr, $this->_Shell->stdin + $this->_Dispatch, $this->_Shell->stdout, $this->_Shell->stderr, $this->_Shell->stdin ); if ($enable === true) { $this->_enabled[] = $name; diff --git a/cake/console/shell_dispatcher.php b/cake/console/shell_dispatcher.php index 04e9904a3..267cf4cb4 100644 --- a/cake/console/shell_dispatcher.php +++ b/cake/console/shell_dispatcher.php @@ -184,9 +184,7 @@ class ShellDispatcher { */ function __buildPaths() { $paths = array(); - if (!class_exists('Folder')) { - require LIBS . 'folder.php'; - } + $plugins = App::objects('plugin', null, false); foreach ((array)$plugins as $plugin) { $pluginPath = App::pluginPath($plugin); @@ -272,17 +270,10 @@ class ShellDispatcher { $methods = array(); - if ($Shell instanceof Shell) { + if ($Shell instanceof Shell) { $Shell->initialize(); $Shell->loadTasks(); - foreach ($Shell->taskNames as $task) { - if (is_a($Shell->{$task}, 'Shell')) { - $Shell->{$task}->initialize(); - $Shell->{$task}->loadTasks(); - } - } - $task = Inflector::camelize($arg); if (in_array($task, $Shell->taskNames)) { diff --git a/cake/tests/cases/console/libs/task_collection.test.php b/cake/tests/cases/console/libs/task_collection.test.php index 94935106b..b277c6c60 100644 --- a/cake/tests/cases/console/libs/task_collection.test.php +++ b/cake/tests/cases/console/libs/task_collection.test.php @@ -30,7 +30,8 @@ class TaskCollectionTest extends CakeTestCase { function setup() { $shell = $this->getMock('Shell', array(), array(), '', false); $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 */ function testLoadPluginTask() { + $dispatcher = $this->getMock('ShellDispatcher', array(), array(), '', false); $shell = $this->getMock('Shell', array(), array(), '', false); $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; - $this->Tasks = new TaskCollection($shell); + $dispatcher->shellPaths = $shell->shellPaths; + $this->Tasks = new TaskCollection($shell, $dispatcher); $result = $this->Tasks->load('TestPlugin.OtherTask'); $this->assertType('OtherTaskTask', $result, 'Task class is wrong.');