Skip to content

Commit

Permalink
Merge pull request #652 from jails/pr44
Browse files Browse the repository at this point in the history
Refactoring lazy initialization for model metadata
  • Loading branch information
nateabele committed Sep 21, 2012
2 parents f4c5bd2 + 26d2307 commit f2b556e
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 25 deletions.
48 changes: 23 additions & 25 deletions data/Model.php
Expand Up @@ -309,7 +309,14 @@ class Model extends \lithium\core\StaticObject {
* @see lithium\data\Model::config()
* @var array
*/
protected static $_autoConfig = array('meta', 'finders', 'query', 'schema', 'classes');
protected static $_autoConfig = array(
'meta',
'finders',
'query',
'schema',
'classes',
'initializers'
);

/**
* Configures the model for use. This method will set the `Model::$_schema`, `Model::$_meta`,
Expand Down Expand Up @@ -367,6 +374,7 @@ protected static function _init($class) {
$schema = array();
$source = array();
$classes = static::$_classes;
$initializers = array();

foreach (static::_parents() as $parent) {
$parentConfig = get_class_vars($parent);
Expand All @@ -390,26 +398,25 @@ protected static function _init($class) {
$source = (($conn) ? $conn->configureClass($class) : array()) + $source;
}
static::$_classes = $classes;
$name = static::_name();

$local = compact('class', 'name') + $self->_meta;
$local = compact('class') + $self->_meta;
$self->_meta = ($local + $source['meta'] + $meta);
$meta =& $self->_meta;

if (is_object($schema)) {
$schema = $schema->fields();
}
$self->_initializers += array(
'source' => function() use (&$meta) {
return Inflector::tableize($meta['name']);
'name' => function($self) {
return basename(str_replace('\\', '/', $self));
},
'source' => function($self) {
return Inflector::tableize($self::meta('name'));
},
'title' => function() use (&$meta) {
'title' => function($self) {
$titleKeys = array('title', 'name');

if (isset($meta['key'])) {
$titleKeys = array_merge($titleKeys, (array) $meta['key']);
}
return $meta['class']::hasField($titleKeys);
$titleKeys = array_merge($titleKeys, (array) $self::meta('key'));
return $self::hasField($titleKeys);
}
);

Expand Down Expand Up @@ -594,14 +601,15 @@ protected function _getMetaKey($key = null) {
if (!$key) {
$all = array_keys($this->_initializers);
$call = array(&$this, '_getMetaKey');
return array_combine($all, array_map($call, $all)) + $this->_meta;
return $all ? array_combine($all, array_map($call, $all)) + $this->_meta : $this->_meta;
}

if (isset($this->_meta[$key])) {
return $this->_meta[$key];
}
if (isset($this->_initializers[$key]) && $initializer = $this->_initializers[$key]) {
return ($this->_meta[$key] = $initializer($this->_meta, $this->_schema));
unset($this->_initializers[$key]);
return ($this->_meta[$key] = $initializer(get_called_class()));
}
}

Expand Down Expand Up @@ -753,10 +761,10 @@ public static function bind($type, $name, array $config = array()) {
*/
public static function schema($field = null) {
$self = static::_object();
$source = $self::meta('source');

if (!is_object($self->_schema)) {
$self->_schema = static::connection()->describe($source, $self->_schema, $self->_meta);
$source = $self::meta('source');
$self->_schema = static::connection()->describe($source, $self->_schema, static::meta());

if (!is_object($self->_schema)) {
$class = get_called_class();
Expand Down Expand Up @@ -1137,16 +1145,6 @@ public static function &connection() {
throw new ConfigException("The data connection `{$name}` is not configured.");
}

/**
* Gets just the class name portion of a fully-name-spaced class name, i.e.
* `app\models\Posts::_name()` returns `'Posts'`.
*
* @return string
*/
protected static function _name() {
return basename(str_replace('\\', '/', get_called_class()));
}

/**
* Wraps `StaticObject::applyFilter()` to account for object instances.
*
Expand Down
71 changes: 71 additions & 0 deletions tests/cases/data/ModelTest.php
Expand Up @@ -9,6 +9,7 @@
namespace lithium\tests\cases\data;

use stdClass;
use lithium\util\Inflector;
use lithium\data\Model;
use lithium\data\Entity;
use lithium\data\Schema;
Expand Down Expand Up @@ -801,6 +802,76 @@ public function testLazyLoad() {
$this->expectException($exception);
MockPost::relations('Unexisting');
}

public function testLazyMetadataInit() {
MockPost::config(array(
'schema' => new Schema(array(
'fields' => array(
'id' => array('type' => 'integer'),
'name' => array('type' => 'string'),
'label' => array('type' => 'string')
)
))
));

$this->assertIdentical('mock_posts', MockPost::meta('source'));
$this->assertIdentical('name', MockPost::meta('title'));
$this->assertIdentical(null, MockPost::meta('unexisting'));

$config = array(
'schema' => new Schema(array(
'fields' => array(
'id' => array('type' => 'integer'),
'name' => array('type' => 'string'),
'label' => array('type' => 'string')
)
)
),
'initializers' => array(
'source' => function($self) {
return Inflector::tableize($self::meta('name'));
},
'name' => function($self) {
return Inflector::singularize('CoolPosts');
},
'title' => function($self) {
static $i = 1;
return 'label' . $i++;
}
)
);
MockPost::reset();
MockPost::config($config);
$this->assertIdentical('cool_posts', MockPost::meta('source'));
$this->assertIdentical('label1', MockPost::meta('title'));
$this->assertFalse('label2' == MockPost::meta('title'));
$this->assertIdentical('label1', MockPost::meta('title'));
$meta = MockPost::meta();
$this->assertIdentical('label1', $meta['title']);
$this->assertIdentical('CoolPost', MockPost::meta('name'));

MockPost::reset();
unset($config['initializers']['title']);
$config['initializers']['source'] = function($self) {
return Inflector::underscore($self::meta('name'));
};
MockPost::config($config);
$this->assertIdentical('cool_post', MockPost::meta('source'));
$this->assertIdentical('name', MockPost::meta('title'));
$this->assertIdentical('CoolPost', MockPost::meta('name'));

MockPost::reset();
MockPost::config($config);
$expected = array (
'class' => 'lithium\\tests\\mocks\\data\\MockPost',
'connection' => false,
'key' => 'id',
'name' => 'CoolPost',
'title' => 'name',
'source' => 'cool_post'
);
$this->assertEqual($expected, MockPost::meta());
}
}

?>

0 comments on commit f2b556e

Please sign in to comment.