Skip to content

Commit

Permalink
Adding cascade delete for dependent HasMany associations
Browse files Browse the repository at this point in the history
  • Loading branch information
mylux committed Sep 30, 2015
1 parent a237c89 commit 10f8798
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 5 deletions.
22 changes: 20 additions & 2 deletions src/ORM/Association/HasMany.php
Expand Up @@ -148,8 +148,7 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
$options['_sourceTable'] = $this->source();

if ($this->_saveStrategy === self::SAVE_REPLACE) {
$updateFields = array_fill_keys(array_keys($properties), null);
$target->updateAll($updateFields, $properties);
$this->_unlinkAssociated($properties, $entity, $target, $options);
}

foreach ($targetEntities as $k => $targetEntity) {
Expand Down Expand Up @@ -185,6 +184,25 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
return $entity;
}

/**
* Deletes/sets null the related objects according to the dependency between source and targets
*
* @param array $properties array of foreignKey properties
* @param EntityInterface $entity the entity which should have its associated entities unassigned
* @param Table $target The associated table
* @param array $options original list of options passed in constructor
* @return void
*/
protected function _unlinkAssociated(array $properties, EntityInterface $entity, Table $target, array $options)
{
if ($this->dependent()) {
$this->cascadeDelete($entity, $options);
} else {
$updateFields = array_fill_keys(array_keys($properties), null);
$target->updateAll($updateFields, $properties);
}
}

/**
* {@inheritDoc}
*/
Expand Down
52 changes: 49 additions & 3 deletions tests/TestCase/ORM/TableTest.php
Expand Up @@ -1739,7 +1739,7 @@ public function testSavePrimaryKeyEntityExists()


/**
* Test that save works with replace saveStrategy
* Test that save works with replace saveStrategy and are not deleted once they are not null
*
* @return void
*/
Expand Down Expand Up @@ -1770,17 +1770,19 @@ public function testSaveReplaceSaveStrategy()

$this->assertEquals(2, $authors->Articles->find('all')->where(['author_id' => $entity['id']])->count());

$articleId = $entity->articles[0]->id;
unset($entity->articles[0]);
$entity->dirty('articles', true);

$authors->save($entity, ['associated' => ['Articles']]);

$this->assertEquals(1, $authors->Articles->find('all')->where(['author_id' => $entity['id']])->count());
$this->assertTrue($authors->Articles->exists(['id' => $articleId]));
}


/**
* Test that save works with append saveStrategy
* Test that save works with append saveStrategy not deleting or setting null anything
*
* @return void
*/
Expand Down Expand Up @@ -1810,13 +1812,15 @@ public function testSaveAppendSaveStrategy()
$entity = $authors->save($entity, ['associated' => ['Articles']]);

$this->assertEquals(2, $authors->Articles->find('all')->where(['author_id' => $entity['id']])->count());


$articleId = $entity->articles[0]->id;
unset($entity->articles[0]);
$entity->dirty('articles', true);

$authors->save($entity, ['associated' => ['Articles']]);

$this->assertEquals(2, $authors->Articles->find('all')->where(['author_id' => $entity['id']])->count());
$this->assertTrue($authors->Articles->exists(['id' => $articleId]));
}
/**
* Test that save has append as the default save strategy
Expand All @@ -1840,6 +1844,48 @@ public function testSaveDefaultSaveStrategy()
$this->assertEquals('append', $authors->association('articles')->saveStrategy());
}

/**
* Test that the associated entities are unlinked and deleted when they are dependent
*
* @return void
*/
public function testSaveReplaceSaveStrategyDependent()
{
$authors = $this->getMock(
'Cake\ORM\Table',
['exists'],
[
[
'connection' => $this->connection,
'alias' => 'Authors',
'table' => 'authors',
]
]
);
$authors->hasMany('Articles', ['saveStrategy' => 'replace', 'dependent' => true]);

$entity = $authors->newEntity([
'name' => 'mylux',
'articles' => [
['title' => 'One Random Post', 'body' => 'The cake is not a lie'],
['title' => 'Another Random Post', 'body' => 'The cake is nice'],
]
], ['associated' => ['Articles']]);

$entity = $authors->save($entity, ['associated' => ['Articles']]);

$this->assertEquals(2, $authors->Articles->find('all')->where(['author_id' => $entity['id']])->count());

$articleId = $entity->articles[0]->id;
unset($entity->articles[0]);
$entity->dirty('articles', true);

$authors->save($entity, ['associated' => ['Articles']]);

$this->assertEquals(1, $authors->Articles->find('all')->where(['author_id' => $entity['id']])->count());
$this->assertFalse($authors->Articles->exists(['id' => $articleId]));
}

/**
* Test that saving a new entity with a Primary Key set does not call exists when checkExisting is false.
*
Expand Down

0 comments on commit 10f8798

Please sign in to comment.