Skip to content

Commit d744b99

Browse files
committed
Added ability to control how deeps associations can be saved and what
options are passed to each level
1 parent 2c7026d commit d744b99

File tree

2 files changed

+117
-1
lines changed

2 files changed

+117
-1
lines changed

Cake/ORM/Table.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,11 @@ protected function _processSave($entity, $options) {
10121012

10131013
protected function _sortAssociationTypes($assocs) {
10141014
$parents = $children = [];
1015-
foreach ($assocs as $assoc) {
1015+
foreach ($assocs as $key => $assoc) {
1016+
if (!is_string($assoc)) {
1017+
$assoc = $key;
1018+
}
1019+
10161020
$association = $this->association($assoc);
10171021
if (!$association) {
10181022
$msg = __d('cake_dev', '%s is not associated to %s', $this->alias(), $assoc);
@@ -1033,6 +1037,7 @@ protected function _saveAssociations($assocs, $entity, array $options) {
10331037
return $entity;
10341038
}
10351039

1040+
$associated = $options['associated'];
10361041
unset($options['associated']);
10371042

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

1051+
if (isset($associated[$alias])) {
1052+
$options = (array)$associated[$alias] + $options;
1053+
}
1054+
10461055
if (!$association->save($entity, $options)) {
10471056
return false;
10481057
}

Cake/Test/TestCase/ORM/TableTest.php

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2462,4 +2462,111 @@ public function testBelongsToManyIntegration() {
24622462
$this->assertEquals($tags, $article->tags);
24632463
}
24642464

2465+
/**
2466+
* Tests that it is possible to do a deep save and control what associations get saved,
2467+
* while having control of the options passed to each level of the save
2468+
*
2469+
* @group save
2470+
* @return void
2471+
*/
2472+
public function testSaveDeepAssociationOptions() {
2473+
$articles = $this->getMock(
2474+
'\Cake\ORM\Table',
2475+
['_insert'],
2476+
[['table' => 'articles', 'connection' => $this->connection]]
2477+
);
2478+
$authors = $this->getMock(
2479+
'\Cake\ORM\Table',
2480+
['_insert', '_processValidation'],
2481+
[['table' => 'authors', 'connection' => $this->connection]]
2482+
);
2483+
$supervisors = $this->getMock(
2484+
'\Cake\ORM\Table',
2485+
['_insert', '_processValidation'],
2486+
[[
2487+
'table' => 'authors',
2488+
'alias' => 'supervisors',
2489+
'connection' => $this->connection
2490+
]]
2491+
);
2492+
$tags = $this->getMock(
2493+
'\Cake\ORM\Table',
2494+
['_insert'],
2495+
[['table' => 'tags', 'connection' => $this->connection]]
2496+
);
2497+
2498+
$articles->belongsTo('authors', ['targetTable' => $authors]);
2499+
$authors->hasOne('supervisors', ['targetTable' => $supervisors]);
2500+
$supervisors->belongsToMany('tags', ['targetTable' => $tags]);
2501+
2502+
$entity = new \Cake\ORM\Entity([
2503+
'title' => 'bar',
2504+
'author' => new \Cake\ORM\Entity([
2505+
'name' => 'Juan',
2506+
'supervisor' => new \Cake\ORM\Entity(['name' => 'Marc']),
2507+
'tags' => [
2508+
new \Cake\ORM\Entity(['name' => 'foo'])
2509+
]
2510+
]),
2511+
]);
2512+
$entity->isNew(true);
2513+
$entity->author->isNew(true);
2514+
$entity->author->supervisor->isNew(true);
2515+
$entity->author->tags[0]->isNew(true);
2516+
2517+
$articles->expects($this->once())
2518+
->method('_insert')
2519+
->with($entity, ['title' => 'bar'])
2520+
->will($this->returnValue($entity));
2521+
2522+
$authors->expects($this->once())
2523+
->method('_insert')
2524+
->with($entity->author, ['name' => 'Juan'])
2525+
->will($this->returnValue($entity->author));
2526+
2527+
$options = new \ArrayObject([
2528+
'validate' => 'special',
2529+
'atomic' => true,
2530+
'associated' => ['supervisors' => [
2531+
'atomic' => false, 'validate' => false, 'associated' => false
2532+
]]
2533+
]);
2534+
$authors->expects($this->once())
2535+
->method('_processValidation')
2536+
->with($entity->author, $options)
2537+
->will($this->returnValue(true));
2538+
2539+
$supervisors->expects($this->once())
2540+
->method('_insert')
2541+
->with($entity->author->supervisor, ['name' => 'Marc'])
2542+
->will($this->returnValue($entity->author->supervisor));
2543+
2544+
$options = new \ArrayObject([
2545+
'validate' => false,
2546+
'atomic' => false,
2547+
'associated' => []
2548+
]);
2549+
$supervisors->expects($this->once())
2550+
->method('_processValidation')
2551+
->with($entity->author->supervisor, $options)
2552+
->will($this->returnValue(true));
2553+
2554+
$tags->expects($this->never())->method('_insert');
2555+
2556+
$this->assertSame($entity, $articles->save($entity, [
2557+
'associated' => [
2558+
'authors' => [
2559+
'validate' => 'special',
2560+
'associated' => [
2561+
'supervisors' => [
2562+
'atomic' => false,
2563+
'validate' => false,
2564+
'associated' => false
2565+
]
2566+
]
2567+
]
2568+
]
2569+
]));
2570+
}
2571+
24652572
}

0 commit comments

Comments
 (0)