Lazy load models in shells.

This commit is contained in:
Kyle Robinson Young 2012-03-19 23:52:01 -07:00
parent 00edc594bf
commit 85862bbb9f
2 changed files with 84 additions and 17 deletions

View file

@ -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.
*
@ -177,7 +184,7 @@ class Shell extends Object {
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);
}
}
@ -223,32 +230,66 @@ class Shell extends Object {
}
/**
* 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);
}
App::uses('ClassRegistry', 'Utility');
$uses = is_array($this->uses) ? $this->uses : array($this->uses);
$modelClassName = $uses[0];
if (strpos($uses[0], '.') !== false) {
list($plugin, $modelClassName) = explode('.', $uses[0]);
}
$this->modelClass = $modelClassName;
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);
}
}
}
}
/**
* 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;
}
$this->uses = ($this->uses) ? (array)$this->uses : array();
if (!in_array($modelClass, $this->uses)) {
$this->uses[] = $modelClass;
}
foreach ($uses as $modelClass) {
list($plugin, $modelClass) = pluginSplit($modelClass, true);
$this->{$modelClass} = ClassRegistry::init($plugin . $modelClass);
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;
}

View file

@ -212,6 +212,32 @@ class ShellTest extends CakeTestCase {
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
*