Fix afterFind() called twice with belongsTo and hasOne relationships

Refs #2268
This commit is contained in:
chinpei215 2014-08-06 06:49:04 +09:00
parent fa2cba6dff
commit 1fe943d6f1
2 changed files with 50 additions and 1 deletions

View file

@ -1316,6 +1316,7 @@ class DboSource extends DataSource {
foreach ($resultSet as &$row) { foreach ($resultSet as &$row) {
if ($type === 'hasOne' || $type === 'belongsTo' || $type === 'hasMany') { if ($type === 'hasOne' || $type === 'belongsTo' || $type === 'hasMany') {
$assocResultSet = array(); $assocResultSet = array();
$prefetched = false;
if ( if (
($type === 'hasOne' || $type === 'belongsTo') && ($type === 'hasOne' || $type === 'belongsTo') &&
@ -1326,6 +1327,7 @@ class DboSource extends DataSource {
if (!empty($joinedData)) { if (!empty($joinedData)) {
$assocResultSet[0] = array($LinkModel->alias => $row[$LinkModel->alias]); $assocResultSet[0] = array($LinkModel->alias => $row[$LinkModel->alias]);
} }
$prefetched = true;
} else { } else {
$query = $this->insertQueryData($queryTemplate, $row, $association, $Model, $stack); $query = $this->insertQueryData($queryTemplate, $row, $association, $Model, $stack);
if ($query !== false) { if ($query !== false) {
@ -1376,7 +1378,7 @@ class DboSource extends DataSource {
$this->_mergeAssociation($row, $assocResultSet, $association, $type, $selfJoin); $this->_mergeAssociation($row, $assocResultSet, $association, $type, $selfJoin);
} }
if ($type !== 'hasAndBelongsToMany' && isset($row[$association])) { if ($type !== 'hasAndBelongsToMany' && isset($row[$association]) && !$prefetched) {
$row[$association] = $LinkModel->afterFind($row[$association], false); $row[$association] = $LinkModel->afterFind($row[$association], false);
} }

View file

@ -1456,4 +1456,51 @@ class DboSourceTest extends CakeTestCase {
$result = $db->defaultConditions($Article, null); $result = $db->defaultConditions($Article, null);
$this->assertFalse($result); $this->assertFalse($result);
} }
/**
* Test that count how many times is afterFind called
*
* @return void
*/
public function testCountAfterFindCalls() {
$this->loadFixtures('Article', 'User', 'Comment', 'Attachment', 'Tag', 'ArticlesTag');
// Use alias to make testing "primary = true" easy
$Primary = $this->getMock('Comment', array('afterFind'), array(array('alias' => 'Primary')), '', true);
$Primary->expects($this->any())->method('afterFind')->will($this->returnArgument(0));
$Article = $this->getMock('Article', array('afterFind'), array(), '', true);
$User = $this->getMock('User', array('afterFind'), array(), '', true);
$Comment = $this->getMock('Comment', array('afterFind'), array(), '', true);
$Tag = $this->getMock('Tag', array('afterFind'), array(), '', true);
$Attachment = $this->getMock('Attachment', array('afterFind'), array(), '', true);
$Primary->Article = $Article;
$Primary->Article->User = $User;
$Primary->Article->Tag = $Tag;
$Primary->Article->Comment = $Comment;
$Primary->Attachment = $Attachment;
$Primary->Attachment->Comment = $Comment;
$Primary->User = $User;
// primary = true
$Primary->expects($this->once())
->method('afterFind')->with($this->anything(), $this->isTrue())->will($this->returnArgument(0));
// primary = false
$Article->expects($this->once()) // Primary belongs to 1 Article
->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
$User->expects($this->exactly(2)) // Article belongs to 1 User and Primary belongs to 1 User
->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
$Tag->expects($this->exactly(2)) // Article has 2 Tags
->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
$Comment->expects($this->exactly(3)) // Article has 2 Comments and Attachment belongs to 1 Comment
->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
$Attachment->expects($this->once()) // Primary has 1 Attachment
->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
$result = $Primary->find('first', array('conditions' => array('Primary.id' => 5), 'recursive' => 2));
$this->assertCount(2, $result['Article']['Tag']);
$this->assertCount(2, $result['Article']['Comment']);
}
} }