mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 03:18:26 +00:00
Fix afterFind() called twice with hasMany relationship
It occurs when a model and the children models are related to a same model. For example, such as the following: * User hasMany Comment * User hasMany Article * Article hasMany Comment
This commit is contained in:
parent
cb45821c43
commit
c227c14bf2
2 changed files with 57 additions and 4 deletions
|
@ -1205,6 +1205,30 @@ class DboSource extends DataSource {
|
|||
return $filtering;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes association results through afterFind filters of the corresponding model.
|
||||
*
|
||||
* Similar to DboSource::_filterResults(), but this filters only specified models.
|
||||
* The primary model can not be specified, because this call DboSource::_filterResults() internally.
|
||||
*
|
||||
* @param array &$resultSet Reference of resultset to be filtered.
|
||||
* @param Model $Model Instance of model to operate against.
|
||||
* @param array $toBeFiltered List of classes to be filtered.
|
||||
* @return array Array of results that have been filtered through $Model->afterFind.
|
||||
*/
|
||||
protected function _filterResultsInclusive(&$resultSet, Model $Model, $toBeFiltered = array()) {
|
||||
$exclude = array();
|
||||
|
||||
if (is_array($resultSet)) {
|
||||
$current = reset($resultSet);
|
||||
if (is_array($current)) {
|
||||
$exclude = array_diff(array_keys($current), $toBeFiltered);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_filterResults($resultSet, $Model, $exclude);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries associations.
|
||||
*
|
||||
|
@ -1276,7 +1300,7 @@ class DboSource extends DataSource {
|
|||
|
||||
// Filter
|
||||
if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') {
|
||||
$this->_filterResults($assocResultSet, $Model);
|
||||
$this->_filterResultsInclusive($assocResultSet, $Model, array($association));
|
||||
}
|
||||
|
||||
// Merge
|
||||
|
@ -1305,7 +1329,7 @@ class DboSource extends DataSource {
|
|||
|
||||
// Filter
|
||||
if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') {
|
||||
$this->_filterResults($assocResultSet, $Model);
|
||||
$this->_filterResultsInclusive($assocResultSet, $Model, array($association, $with));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1463,7 +1463,7 @@ class DboSourceTest extends CakeTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test that count how many times is afterFind called
|
||||
* Test that count how many times afterFind is called
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
@ -1472,7 +1472,6 @@ class DboSourceTest extends CakeTestCase {
|
|||
|
||||
// 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);
|
||||
|
@ -1507,5 +1506,35 @@ class DboSourceTest extends CakeTestCase {
|
|||
$result = $Primary->find('first', array('conditions' => array('Primary.id' => 5), 'recursive' => 2));
|
||||
$this->assertCount(2, $result['Article']['Tag']);
|
||||
$this->assertCount(2, $result['Article']['Comment']);
|
||||
|
||||
// hasMany special case
|
||||
// Both User and Article has many Comments
|
||||
$User = $this->getMock('User', array('afterFind'), array(), '', true);
|
||||
$Article = $this->getMock('Article', array('afterFind'), array(), '', true);
|
||||
$Comment = $this->getMock('Comment', array('afterFind'), array(), '', true);
|
||||
|
||||
$User->bindModel(array('hasMany' => array('Comment', 'Article')));
|
||||
$Article->unbindModel(array('belongsTo' => array('User'), 'hasAndBelongsToMany' => array('Tag')));
|
||||
$Comment->unbindModel(array('belongsTo' => array('User', 'Article'), 'hasOne' => 'Attachment'));
|
||||
|
||||
$User->Comment = $Comment;
|
||||
$User->Article = $Article;
|
||||
$User->Article->Comment = $Comment;
|
||||
|
||||
// primary = true
|
||||
$User->expects($this->once())
|
||||
->method('afterFind')->with($this->anything(), $this->isTrue())->will($this->returnArgument(0));
|
||||
|
||||
$Article->expects($this->exactly(2)) // User has 2 Articles
|
||||
->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
|
||||
|
||||
$Comment->expects($this->exactly(7)) // User1 has 3 Comments, Article[id=1] has 4 Comments and Article[id=3] has 0 Comments
|
||||
->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
|
||||
|
||||
$result = $User->find('first', array('conditions' => array('User.id' => 1), 'recursive' => 2));
|
||||
$this->assertCount(3, $result['Comment']);
|
||||
$this->assertCount(2, $result['Article']);
|
||||
$this->assertCount(4, $result['Article'][0]['Comment']);
|
||||
$this->assertCount(0, $result['Article'][1]['Comment']);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue