Skip to content

Commit

Permalink
Guard against missing new entities.
Browse files Browse the repository at this point in the history
If a find operation has been modified via an event listener or
overloaded find method we should avoid trying to marshal data that
doesn't exist.

Refs #5922
  • Loading branch information
markstory committed Feb 19, 2015
1 parent cbb2d34 commit 3b2680c
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/ORM/Marshaller.php
Expand Up @@ -471,11 +471,13 @@ public function mergeMany($entities, array $data, array $options = [])
return $query->orWhere($query->newExpr()->and_(array_combine($primary, $keys)));
}, $this->_table->find());

if (count($maybeExistentQuery->clause('where'))) {
if (!empty($indexed) && count($maybeExistentQuery->clause('where'))) {
foreach ($maybeExistentQuery as $entity) {
$key = implode(';', $entity->extract($primary));
$output[] = $this->merge($entity, $indexed[$key], $options);
unset($indexed[$key]);
if (isset($indexed[$key])) {
$output[] = $this->merge($entity, $indexed[$key], $options);
unset($indexed[$key]);
}
}
}

Expand Down
65 changes: 65 additions & 0 deletions tests/TestCase/ORM/MarshallerTest.php
Expand Up @@ -46,6 +46,40 @@ class ProtectedArticle extends Entity
];
}

/**
* Test stub for greedy find operations.
*/
class GreedyCommentsTable extends Table
{
/**
* initialize hook
*
* @param $config Config data.
* @return void
*/
public function initialize(array $config)
{
$this->table('comments');
$this->alias('Comments');
}

/**
* Overload find to cause issues.
*
* @param string $type Find type
* @param array $options find options
* @return object
*/
public function find($type = 'all', $options = [])
{
if (empty($options['conditions'])) {
$options['conditions'] = [];
}
$options['conditions'] = array_merge($options['conditions'], ['Comments.published' => 'Y']);
return parent::find($type, $options);
}
}

/**
* Marshaller test case
*/
Expand Down Expand Up @@ -1211,6 +1245,37 @@ public function testMergeManyCompositeKey()
$this->assertSame($entities[1], $result[1], 'Should retain object');
}

/**
* Test mergeMany() when the exist check returns nothing.
*
* @return void
*/
public function testMergeManyExistQueryFails()
{
$entities = [
new Entity(['id' => 1, 'comment' => 'First post', 'user_id' => 2]),
new Entity(['id' => 2, 'comment' => 'Second post', 'user_id' => 2])
];
$entities[0]->clean();
$entities[1]->clean();

$data = [
['id' => 2, 'comment' => 'Changed 2', 'user_id' => 2],
['id' => 1, 'comment' => 'Changed 1', 'user_id' => 1],
['id' => 3, 'comment' => 'New 1'],
];
$comments = TableRegistry::get('GreedyComments', [
'className' => __NAMESPACE__ . '\\GreedyCommentsTable'
]);
$marshall = new Marshaller($comments);
$result = $marshall->mergeMany($entities, $data);

$this->assertEquals('Changed 1', $result[0]->comment);
$this->assertEquals(1, $result[0]->user_id);
$this->assertEquals('Changed 2', $result[1]->comment);
$this->assertEquals('New 1', $result[2]->comment);
}

/**
* Tests merge with data types that need to be marshalled
*
Expand Down

0 comments on commit 3b2680c

Please sign in to comment.