Skip to content

Commit

Permalink
Small refactor and finally testing that results are groupped correctly
Browse files Browse the repository at this point in the history
for contained tables
  • Loading branch information
lorenzo committed May 4, 2013
1 parent efb395f commit d511793
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 18 deletions.
9 changes: 7 additions & 2 deletions lib/Cake/ORM/Query.php
Expand Up @@ -13,6 +13,8 @@ class Query extends DatabaseQuery {

protected $_hasFields;

protected $_aliasMap = [];

public function repository(Table $table = null) {
if ($table === null) {
return $this->_table;
Expand Down Expand Up @@ -43,8 +45,8 @@ public function toArray() {
return $this->execute()->toArray();
}

public function aliasedTable() {
return $this->repository();
public function aliasedTable($alias) {
return $this->_aliasMap[$alias];
}

public function aliasField($field, $alias = null) {
Expand Down Expand Up @@ -72,6 +74,8 @@ protected function _transformQuery() {
return parent::_transformQuery();
}

$this->from([$this->_table->alias() => $this->_table->table()]);
$this->_aliasMap[$this->_table->alias()] = $this->_table;
$this->_addDefaultFields();
$this->_addContainments();
return parent::_transformQuery();
Expand Down Expand Up @@ -107,6 +111,7 @@ protected function _normalizeContain(Table $parent, $alias, $options) {
'fields' => 1
];
$table = Table::build($alias);
$this->_aliasMap[$alias] = $table;

if (is_string($options)) {
//TODO: finish extracting
Expand Down
28 changes: 20 additions & 8 deletions lib/Cake/ORM/Table.php
Expand Up @@ -24,6 +24,8 @@ class Table {

protected static $_tablesMap = [];

protected static $_aliasMap = [];

protected $_table;

protected $_alias;
Expand Down Expand Up @@ -55,6 +57,11 @@ public static function build($alias, array $options = []) {
if (isset(static::$_instances[$alias])) {
return static::$_instances[$alias];
}

if (isset(static::$_aliasMap[$alias])) {
$options += ['table' => static::$_aliasMap[$alias]];
}

if (!empty($options['table']) && isset(static::$_tablesMap[$options['table']])) {
$options = array_merge(static::$_tablesMap[$options['table']], $options);
}
Expand All @@ -69,28 +76,34 @@ public static function build($alias, array $options = []) {
$options['className'] = get_called_class();
}

static::map($alias, $options['table']);

return static::$_instances[$alias] = new $options['className']($options);
}

public static function map($alias, $table) {
static::$_aliasMap[$alias] = $table;
}

public static function instance($alias, self $object = null) {
if ($object === null) {
return isset(static::$_instances[$alias]) ? static::$_instances[$alias] : null;
}
return static::$_instances[$alias] = $object;
}

public static function map($alias = null, array $options = null) {
if ($alias === null) {
public static function config($table = null, array $options = null) {
if ($table === null) {
return static::$_tablesMap;
}
if (!is_string($alias)) {
static::$_tablesMap = $alias;
if (!is_string($table)) {
static::$_tablesMap = $table;
return;
}
if ($options === null) {
return isset(static::$_tablesMap[$alias]) ? static::$_tablesMap[$alias] : null;
return isset(static::$_tablesMap[$table]) ? static::$_tablesMap[$table] : null;
}
static::$_tablesMap[$alias] = $options;
static::$_tablesMap[$table] = $options;
}

public static function clearRegistry() {
Expand Down Expand Up @@ -146,8 +159,7 @@ protected function buildQuery() {
$query = new Query($this->connection());
return $query
->repository($this)
->select()
->from([$this->_alias => $this->_table]);
->select();
}

}
94 changes: 94 additions & 0 deletions lib/Cake/Test/TestCase/ORM/QueryTest.php
Expand Up @@ -32,9 +32,59 @@ public function setUp() {
}

public function tearDown() {
$this->connection->execute('DROP TABLE IF EXISTS articles');
$this->connection->execute('DROP TABLE IF EXISTS authors');
Table::clearRegistry();
}


/**
* Test helper for creating tables.
*
* @return void
*/
protected function _createAuthorsAndArticles() {
$table = 'CREATE TEMPORARY TABLE authors(id int, name varchar(50))';
$this->connection->execute($table);

$table = 'CREATE TEMPORARY TABLE articles(id int, title varchar(20), body varchar(50), author_id int)';
$this->connection->execute($table);

Table::config('authors', ['connection' => $this->connection]);
Table::config('articles', ['connection' => $this->connection]);
}

/**
* Auxiliary function to insert a couple rows in a newly created table
*
* @return void
*/
protected function _insertTwoRecords() {
$this->_createAuthorsAndArticles();

$data = ['id' => '1', 'name' => 'Chuck Norris'];
$result = $this->connection->insert('authors', $data, ['id' => 'integer', 'name' => 'string']);

$result->bindValue(1, '2', 'integer');
$result->bindValue(2, 'Bruce Lee');
$result->execute();

$data = ['id' => '1', 'title' => 'a title', 'body' => 'a body', 'author_id' => 1];
$result = $this->connection->insert(
'articles',
$data,
['id' => 'integer', 'title' => 'string', 'body' => 'string', 'author_id' => 'integer']
);

$result->bindValue(1, '2', 'integer');
$result->bindValue(2, 'another title');
$result->bindValue(3, 'another body');
$result->bindValue(4, 2);
$result->execute();

return $result;
}

/**
* Tests that fully defined belongsTo and hasOne relationships are joined correctly
*
Expand Down Expand Up @@ -223,4 +273,48 @@ public function testContainToFieldsDefault() {
];
$this->assertEquals($expected, $select);
}

/**
* Tests that results are grouped correctly when using contain()
*
* @return void
**/
public function testContainResultFetchingOneLevel() {
$this->_insertTwoRecords();
Table::map('author', 'authors');

$query = new Query($this->connection);
$contain = ['author' => ['associationType' => 'belongsTo']];

$table = Table::build('article', ['table' => 'articles']);
$results = $query->repository($table)->select()->contain($contain)->toArray();
$expected = [
[
'article' => [
'id' => (int) 1,
'title' => 'a title',
'body' => 'a body',
'author_id' => (int) 1
],
'author' => [
'id' => (int) 1,
'name' => 'Chuck Norris'
]
],
[
'article' => [
'id' => (int) 2,
'title' => 'another title',
'body' => 'another body',
'author_id' => (int) 2
],
'author' => [
'id' => (int) 2,
'name' => 'Bruce Lee'
]
]
];
$this->assertSame($expected, $results);
}

}
16 changes: 8 additions & 8 deletions lib/Cake/Test/TestCase/ORM/TableTest.php
Expand Up @@ -105,19 +105,19 @@ protected function _createDatesTable() {
*
* @return void
*/
public function testMapAndBuild() {
$map = Table::map();
public function testConfigAndBuild() {
$map = Table::config();
$this->assertEquals([], $map);

$options = ['connection' => $this->connection];
Table::map('things', $options);
$map = Table::map();
Table::config('things', $options);
$map = Table::config();
$this->assertEquals(['things' => $options], $map);
$this->assertEquals($options, Table::map('things'));
$this->assertEquals($options, Table::config'things'));

$schema = ['id' => ['rubbish']];
$options += ['schema' => $schema];
Table::map('things', $options);
Table::config('things', $options);

$table = Table::build('foo', ['table' => 'things']);
$this->assertInstanceOf('Cake\ORM\Table', $table);
Expand All @@ -127,10 +127,10 @@ public function testMapAndBuild() {
$this->assertEquals($schema, $table->schema());

Table::clearRegistry();
$this->assertEmpty(Table::map());
$this->assertEmpty(Table::config());

$options['className'] = __NAMESPACE__ . '\DatesTable';
Table::map('dates', $options);
Table::config('dates', $options);
$table = Table::build('foo', ['table' => 'dates']);
$this->assertInstanceOf(__NAMESPACE__ . '\DatesTable', $table);
$this->assertEquals('dates', $table->table());
Expand Down

0 comments on commit d511793

Please sign in to comment.