Skip to content

Commit

Permalink
Lazy load models in shells.
Browse files Browse the repository at this point in the history
  • Loading branch information
shama committed Mar 1, 2013
1 parent 00edc59 commit 85862bb
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 16 deletions.
73 changes: 57 additions & 16 deletions lib/Cake/Console/Shell.php
Expand Up @@ -119,6 +119,13 @@ class Shell extends Object {
*/
public $uses = array();

/**
* This shell's primary model class name, the first model in the $uses property
*
* @var string
*/
public $modelClass = null;

/**
* Task Collection for the command, used to create Tasks.
*
Expand Down Expand Up @@ -177,7 +184,7 @@ public function __construct($stdout = null, $stderr = null, $stdin = null) {
if ($this->tasks !== null && $this->tasks !== false) {
$this->_mergeVars(array('tasks'), $parent, true);
}
if ($this->uses !== null && $this->uses !== false) {
if (!empty($this->uses)) {
$this->_mergeVars(array('uses'), $parent, false);
}
}
Expand Down Expand Up @@ -223,32 +230,66 @@ protected function _welcome() {
}

/**
* If $uses = true
* Loads AppModel file and constructs AppModel class
* makes $this->AppModel available to subclasses
* If public $uses is an array of models will load those models
* If $uses is an array load each of the models in the array
*
* @return boolean
*/
protected function _loadModels() {
if (empty($this->uses)) {
return false;
if (is_array($this->uses)) {
list(, $this->modelClass) = pluginSplit(current($this->uses));
foreach ($this->uses as $modelClass) {
$this->loadModel($modelClass);
}
}
return true;
}

/**
* Lazy loads models using the loadModel() method if declared in $uses
*
* @param string $name
* @return void
*/
public function __isset($name) {
if (is_array($this->uses)) {
foreach ($this->uses as $modelClass) {
list(, $class) = pluginSplit($modelClass);
if ($name === $class) {
return $this->loadModel($modelClass);
}
}
}
App::uses('ClassRegistry', 'Utility');
}

$uses = is_array($this->uses) ? $this->uses : array($this->uses);
/**
* Loads and instantiates models required by this shell.
*
* @param string $modelClass Name of model class to load
* @param mixed $id Initial ID the instanced model class should have
* @return mixed true when single model found and instance created, error returned if model not found.
* @throws MissingModelException if the model class cannot be found.
*/
public function loadModel($modelClass = null, $id = null) {
if ($modelClass === null) {
$modelClass = $this->modelClass;
}

$modelClassName = $uses[0];
if (strpos($uses[0], '.') !== false) {
list($plugin, $modelClassName) = explode('.', $uses[0]);
$this->uses = ($this->uses) ? (array)$this->uses : array();
if (!in_array($modelClass, $this->uses)) {
$this->uses[] = $modelClass;
}
$this->modelClass = $modelClassName;

foreach ($uses as $modelClass) {
list($plugin, $modelClass) = pluginSplit($modelClass, true);
$this->{$modelClass} = ClassRegistry::init($plugin . $modelClass);
list($plugin, $modelClass) = pluginSplit($modelClass, true);
if (!isset($this->modelClass)) {
$this->modelClass = $modelClass;
}

$this->{$modelClass} = ClassRegistry::init(array(
'class' => $plugin . $modelClass, 'alias' => $modelClass, 'id' => $id
));
if (!$this->{$modelClass}) {
throw new MissingModelException($modelClass);
}
return true;
}

Expand Down
26 changes: 26 additions & 0 deletions lib/Cake/Test/Case/Console/ShellTest.php
Expand Up @@ -212,6 +212,32 @@ public function testInitialize() {
App::build();
}

/**
* testLoadModel method
*
* @return void
*/
public function testLoadModel() {
App::build(array(
'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS),
'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS)
), App::RESET);

$Shell = new TestMergeShell();
$this->assertEquals('Comment', $Shell->Comment->alias);
$this->assertInstanceOf('Comment', $Shell->Comment);
$this->assertEquals('Comment', $Shell->modelClass);

CakePlugin::load('TestPlugin');
$this->Shell->loadModel('TestPlugin.TestPluginPost');
$this->assertTrue(isset($this->Shell->TestPluginPost));
$this->assertInstanceOf('TestPluginPost', $this->Shell->TestPluginPost);
$this->assertEquals('TestPluginPost', $this->Shell->modelClass);
CakePlugin::unload('TestPlugin');

App::build();
}

/**
* testIn method
*
Expand Down

0 comments on commit 85862bb

Please sign in to comment.