Skip to content

Commit

Permalink
Making Tasks lazy load.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
markstory committed Oct 14, 2010
1 parent 4d199cf commit fbcc9c1
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 19 deletions.
36 changes: 32 additions & 4 deletions cake/console/libs/shell.php
Expand Up @@ -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.
*
Expand Down Expand Up @@ -132,6 +139,13 @@ class Shell extends Object {
*/
public $Tasks;

/**
* Normalized map of tasks.
*
* @var string
*/
protected $_taskMap = array();

/**
* stdout object.
*
Expand Down Expand Up @@ -177,7 +191,7 @@ function __construct(&$dispatch, $stdout = null, $stderr = null, $stdin = null)
}

$this->Dispatch =& $dispatch;
$this->Tasks = new TaskCollection($this);
$this->Tasks = new TaskCollection($this, $dispatch);

$this->stdout = $stdout;
$this->stderr = $stderr;
Expand Down Expand Up @@ -272,14 +286,28 @@ public function loadTasks() {
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.
*
Expand Down
6 changes: 4 additions & 2 deletions cake/console/libs/task_collection.php
Expand Up @@ -25,15 +25,17 @@ class TaskCollection extends ObjectCollection {
* @var array
*/
protected $_Shell;
protected $_Dispatch;

/**
* Constructor
*
* @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.
Expand Down Expand Up @@ -61,7 +63,7 @@ public function load($task, $settings = array(), $enable = true) {
}

$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;
Expand Down
13 changes: 2 additions & 11 deletions cake/console/shell_dispatcher.php
Expand Up @@ -184,9 +184,7 @@ protected function _initEnvironment() {
*/
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);
Expand Down Expand Up @@ -272,17 +270,10 @@ public function dispatch() {

$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)) {
Expand Down
7 changes: 5 additions & 2 deletions cake/tests/cases/console/libs/task_collection.test.php
Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -86,10 +87,12 @@ function testLoadMissingTaskFile() {
* @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.');
Expand Down

0 comments on commit fbcc9c1

Please sign in to comment.