Skip to content

Commit

Permalink
Allow associations inline with contain specify their own finder methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Conroy committed Sep 5, 2014
1 parent a2b1d4a commit 58c1f52
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 7 deletions.
5 changes: 3 additions & 2 deletions src/ORM/Association.php
Expand Up @@ -445,7 +445,8 @@ public function attachTo(Query $query, array $options = []) {
'conditions' => [],
'fields' => [],
'type' => empty($options['matching']) ? $this->joinType() : 'INNER',
'table' => $target->table()
'table' => $target->table(),
'finder' => null
];

if (!empty($options['foreignKey'])) {
Expand All @@ -455,7 +456,7 @@ public function attachTo(Query $query, array $options = []) {
}
}

$dummy = $this->find()->eagerLoaded(true);
$dummy = $this->find($options['finder'])->eagerLoaded(true);
if (!empty($options['queryBuilder'])) {
$dummy = $options['queryBuilder']($dummy);
if (!($dummy instanceof Query)) {
Expand Down
2 changes: 1 addition & 1 deletion src/ORM/Association/SelectableAssociationTrait.php
Expand Up @@ -86,7 +86,7 @@ protected function _buildQuery($options) {
}

$fetchQuery = $this
->find('all')
->find(isset($options['finder']) ? $options['finder'] : 'all')
->where($options['conditions'])
->eagerLoaded(true)
->hydrate($options['query']->hydrate());
Expand Down
3 changes: 2 additions & 1 deletion src/ORM/EagerLoader.php
Expand Up @@ -57,7 +57,8 @@ class EagerLoader {
'fields' => 1,
'sort' => 1,
'matching' => 1,
'queryBuilder' => 1
'queryBuilder' => 1,
'finder' => 1
];

/**
Expand Down
31 changes: 31 additions & 0 deletions src/ORM/Table.php
Expand Up @@ -1440,6 +1440,9 @@ protected function _processDelete($entity, $options) {
* @throws \BadMethodCallException
*/
public function callFinder($type, Query $query, array $options = []) {
if (is_array($type)) {
list($type, $options) = $this->_inferFinderTypeAndOptions($type, $options);
}
$query->applyOptions($options);
$options = $query->getOptions();
$finder = 'find' . ucfirst($type);
Expand Down Expand Up @@ -1934,4 +1937,32 @@ public function __debugInfo() {
];
}

/**
* Helper method to infer the requested finder and its options.
*
* Returns the inferred options from the finder $type.
*
* @return array
*/
protected function _inferFinderTypeAndOptions(array $type) {
$options = [];
if (count($type)) {
$v = array_values($type)[0];
$k = array_keys($type)[0];
if (is_array($v)) {
$type = $k;
$options = $v;
} elseif (is_string($v) && !$k) {
$type = $v;
} elseif (is_string($v)) {
$type = $k;
$options = [$v];
}
}
return [
$type,
$options
];
}

}
Expand Up @@ -150,13 +150,12 @@ public function testPaginateCustomFinderOptions() {
$this->loadFixtures('Post');
$settings = [
'PaginatorPosts' => [
'finder' => 'author',
'author_id' => 1
'finder' => ['author' => ['author_id' => 1]]
]
];
$table = TableRegistry::get('PaginatorPosts');

$expected = $table->find('author', ['conditions' => ['PaginatorPosts.author_id' => $settings['PaginatorPosts']['author_id']]])
$expected = $table->find('author', ['conditions' => ['PaginatorPosts.author_id' => $settings['PaginatorPosts']['finder']['author']['author_id']]])
->count();
$result = $this->Paginator->paginate($table, $settings)->count();

Expand Down
33 changes: 33 additions & 0 deletions tests/TestCase/ORM/QueryTest.php
Expand Up @@ -2111,4 +2111,37 @@ public function testCleanCopy() {
$this->assertNull($copy->clause('order'));
}

/**
* Test that finder options sent through via contain are sent to custom finder.
*
* @return void
*/
public function testContainFinderCanSpecifyOptions() {
$table = TableRegistry::get('Articles');
$table->belongsTo(
'Authors',
['className' => 'TestApp\Model\Table\AuthorsTable']
);
$authorId = 1;

$resultWithoutAuthor = $table->find('all')
->where(['Articles.author_id' => $authorId])
->contain([
'Authors' => [
'finder' => ['byAuthor' => ['author_id' => 2]]
]
]);

$resultWithAuthor = $table->find('all')
->where(['Articles.author_id' => $authorId])
->contain([
'Authors' => [
'finder' => ['byAuthor' => ['author_id' => $authorId]]
]
]);

$this->assertEmpty($resultWithoutAuthor->first()['author']);
$this->assertEquals($authorId, $resultWithAuthor->first()['author']['id']);
}

}
8 changes: 8 additions & 0 deletions tests/test_app/TestApp/Model/Table/AuthorsTable.php
Expand Up @@ -12,6 +12,7 @@
namespace TestApp\Model\Table;

use Cake\ORM\Table;
use Cake\ORM\Query;

/**
* Author table class
Expand All @@ -23,4 +24,11 @@ public function initialize(array $config) {
$this->hasMany('articles');
}

public function findByAuthor(Query $query, array $options = []) {
if (isset($options['author_id'])) {
$query->where(['Articles.id' => $options['author_id']]);
}
return $query;
}

}

0 comments on commit 58c1f52

Please sign in to comment.