Skip to content

Commit

Permalink
Added ability to control how deeps associations can be saved and what
Browse files Browse the repository at this point in the history
options are passed to each level
  • Loading branch information
lorenzo committed Dec 2, 2013
1 parent 2c7026d commit d744b99
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 1 deletion.
11 changes: 10 additions & 1 deletion Cake/ORM/Table.php
Expand Up @@ -1012,7 +1012,11 @@ protected function _processSave($entity, $options) {

protected function _sortAssociationTypes($assocs) {
$parents = $children = [];
foreach ($assocs as $assoc) {
foreach ($assocs as $key => $assoc) {
if (!is_string($assoc)) {
$assoc = $key;
}

$association = $this->association($assoc);
if (!$association) {
$msg = __d('cake_dev', '%s is not associated to %s', $this->alias(), $assoc);
Expand All @@ -1033,6 +1037,7 @@ protected function _saveAssociations($assocs, $entity, array $options) {
return $entity;
}

$associated = $options['associated'];
unset($options['associated']);

foreach ($assocs as $alias) {
Expand All @@ -1043,6 +1048,10 @@ protected function _saveAssociations($assocs, $entity, array $options) {
continue;
}

if (isset($associated[$alias])) {
$options = (array)$associated[$alias] + $options;
}

if (!$association->save($entity, $options)) {
return false;
}
Expand Down
107 changes: 107 additions & 0 deletions Cake/Test/TestCase/ORM/TableTest.php
Expand Up @@ -2462,4 +2462,111 @@ public function testBelongsToManyIntegration() {
$this->assertEquals($tags, $article->tags);
}

/**
* Tests that it is possible to do a deep save and control what associations get saved,
* while having control of the options passed to each level of the save
*
* @group save
* @return void
*/
public function testSaveDeepAssociationOptions() {
$articles = $this->getMock(
'\Cake\ORM\Table',
['_insert'],
[['table' => 'articles', 'connection' => $this->connection]]
);
$authors = $this->getMock(
'\Cake\ORM\Table',
['_insert', '_processValidation'],
[['table' => 'authors', 'connection' => $this->connection]]
);
$supervisors = $this->getMock(
'\Cake\ORM\Table',
['_insert', '_processValidation'],
[[
'table' => 'authors',
'alias' => 'supervisors',
'connection' => $this->connection
]]
);
$tags = $this->getMock(
'\Cake\ORM\Table',
['_insert'],
[['table' => 'tags', 'connection' => $this->connection]]
);

$articles->belongsTo('authors', ['targetTable' => $authors]);
$authors->hasOne('supervisors', ['targetTable' => $supervisors]);
$supervisors->belongsToMany('tags', ['targetTable' => $tags]);

$entity = new \Cake\ORM\Entity([
'title' => 'bar',
'author' => new \Cake\ORM\Entity([
'name' => 'Juan',
'supervisor' => new \Cake\ORM\Entity(['name' => 'Marc']),
'tags' => [
new \Cake\ORM\Entity(['name' => 'foo'])
]
]),
]);
$entity->isNew(true);
$entity->author->isNew(true);
$entity->author->supervisor->isNew(true);
$entity->author->tags[0]->isNew(true);

$articles->expects($this->once())
->method('_insert')
->with($entity, ['title' => 'bar'])
->will($this->returnValue($entity));

$authors->expects($this->once())
->method('_insert')
->with($entity->author, ['name' => 'Juan'])
->will($this->returnValue($entity->author));

$options = new \ArrayObject([
'validate' => 'special',
'atomic' => true,
'associated' => ['supervisors' => [
'atomic' => false, 'validate' => false, 'associated' => false
]]
]);
$authors->expects($this->once())
->method('_processValidation')
->with($entity->author, $options)
->will($this->returnValue(true));

$supervisors->expects($this->once())
->method('_insert')
->with($entity->author->supervisor, ['name' => 'Marc'])
->will($this->returnValue($entity->author->supervisor));

$options = new \ArrayObject([
'validate' => false,
'atomic' => false,
'associated' => []
]);
$supervisors->expects($this->once())
->method('_processValidation')
->with($entity->author->supervisor, $options)
->will($this->returnValue(true));

$tags->expects($this->never())->method('_insert');

$this->assertSame($entity, $articles->save($entity, [
'associated' => [
'authors' => [
'validate' => 'special',
'associated' => [
'supervisors' => [
'atomic' => false,
'validate' => false,
'associated' => false
]
]
]
]
]));
}

}

0 comments on commit d744b99

Please sign in to comment.