mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 03:18:26 +00:00
Merge pull request #4223 from chinpei215/2.6-issue2529-fix
Fix different format of $results in afterFind
This commit is contained in:
commit
b5bfbfcf15
4 changed files with 153 additions and 7 deletions
|
@ -1200,6 +1200,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.
|
||||
*
|
||||
|
@ -1271,7 +1295,7 @@ class DboSource extends DataSource {
|
|||
|
||||
// Filter
|
||||
if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') {
|
||||
$this->_filterResults($assocResultSet, $Model);
|
||||
$this->_filterResultsInclusive($assocResultSet, $Model, array($association));
|
||||
}
|
||||
|
||||
// Merge
|
||||
|
@ -1300,7 +1324,7 @@ class DboSource extends DataSource {
|
|||
|
||||
// Filter
|
||||
if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') {
|
||||
$this->_filterResults($assocResultSet, $Model);
|
||||
$this->_filterResultsInclusive($assocResultSet, $Model, array($association, $with));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1370,10 +1394,15 @@ class DboSource extends DataSource {
|
|||
$this->_mergeAssociation($row, $merge, $association, $type);
|
||||
}
|
||||
} else {
|
||||
if (!$prefetched && $LinkModel->useConsistentAfterFind) {
|
||||
if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') {
|
||||
$this->_filterResultsInclusive($assocResultSet, $Model, array($association));
|
||||
}
|
||||
}
|
||||
$this->_mergeAssociation($row, $assocResultSet, $association, $type, $selfJoin);
|
||||
}
|
||||
|
||||
if ($type !== 'hasAndBelongsToMany' && isset($row[$association]) && !$prefetched) {
|
||||
if ($type !== 'hasAndBelongsToMany' && isset($row[$association]) && !$prefetched && !$LinkModel->useConsistentAfterFind) {
|
||||
$row[$association] = $LinkModel->afterFind($row[$association], false);
|
||||
}
|
||||
|
||||
|
|
|
@ -603,6 +603,25 @@ class Model extends Object implements CakeEventListener {
|
|||
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
/**
|
||||
* If true, afterFind will be passed consistent formatted $results in case of $primary is false.
|
||||
* The format will be such as the following.
|
||||
*
|
||||
* {{{
|
||||
* $results = array(
|
||||
* 0 => array(
|
||||
* 'ModelName' => array(
|
||||
* 'field1' => 'value1',
|
||||
* 'field2' => 'value2'
|
||||
* )
|
||||
* )
|
||||
* );
|
||||
* }}}
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $useConsistentAfterFind = true;
|
||||
|
||||
/**
|
||||
* The ID of the model record that was last inserted.
|
||||
*
|
||||
|
|
|
@ -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,6 +1506,99 @@ 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']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test format of $results in afterFind
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUseConsistentAfterFind() {
|
||||
$this->loadFixtures('Author', 'Post');
|
||||
|
||||
$expected = array(
|
||||
'Author' => array(
|
||||
'id' => '1',
|
||||
'user' => 'mariano',
|
||||
'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
|
||||
'created' => '2007-03-17 01:16:23',
|
||||
'updated' => '2007-03-17 01:18:31',
|
||||
'test' => 'working',
|
||||
),
|
||||
'Post' => array(
|
||||
array(
|
||||
'id' => '1',
|
||||
'author_id' => '1',
|
||||
'title' => 'First Post',
|
||||
'body' => 'First Post Body',
|
||||
'published' => 'Y',
|
||||
'created' => '2007-03-18 10:39:23',
|
||||
'updated' => '2007-03-18 10:41:31',
|
||||
),
|
||||
array(
|
||||
'id' => '3',
|
||||
'author_id' => '1',
|
||||
'title' => 'Third Post',
|
||||
'body' => 'Third Post Body',
|
||||
'published' => 'Y',
|
||||
'created' => '2007-03-18 10:43:23',
|
||||
'updated' => '2007-03-18 10:45:31',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$Author = new Author();
|
||||
$Post = $this->getMock('Post', array('afterFind'), array(), '', true);
|
||||
$Post->expects($this->at(0))->method('afterFind')->with(array(array('Post' => $expected['Post'][0])), $this->isFalse())->will($this->returnArgument(0));
|
||||
$Post->expects($this->at(1))->method('afterFind')->with(array(array('Post' => $expected['Post'][1])), $this->isFalse())->will($this->returnArgument(0));
|
||||
|
||||
$Author->bindModel(array('hasMany' => array('Post' => array('limit' => 2, 'order' => 'Post.id'))));
|
||||
$Author->Post = $Post;
|
||||
|
||||
$result = $Author->find('first', array('conditions' => array('Author.id' => 1), 'recursive' => 1));
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
// Backward compatiblity
|
||||
$Author = new Author();
|
||||
$Post = $this->getMock('Post', array('afterFind'), array(), '', true);
|
||||
$Post->expects($this->once())->method('afterFind')->with($expected['Post'], $this->isFalse())->will($this->returnArgument(0));
|
||||
$Post->useConsistentAfterFind = false;
|
||||
|
||||
$Author->bindModel(array('hasMany' => array('Post' => array('limit' => 2, 'order' => 'Post.id'))));
|
||||
$Author->Post = $Post;
|
||||
|
||||
$result = $Author->find('first', array('conditions' => array('Author.id' => 1), 'recursive' => 1));
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -732,8 +732,14 @@ class ModifiedAttachment extends CakeTestModel {
|
|||
* @return void
|
||||
*/
|
||||
public function afterFind($results, $primary = false) {
|
||||
if (isset($results['id'])) {
|
||||
$results['callback'] = 'Fired';
|
||||
if ($this->useConsistentAfterFind) {
|
||||
if (isset($results[0][$this->alias]['id'])) {
|
||||
$results[0][$this->alias]['callback'] = 'Fired';
|
||||
}
|
||||
} else {
|
||||
if (isset($results['id'])) {
|
||||
$results['callback'] = 'Fired';
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue