From 7c730956c554870ad97c853c9d73948921fb49ca Mon Sep 17 00:00:00 2001 From: kolorafa Date: Wed, 28 Aug 2024 17:12:52 +0200 Subject: [PATCH] Ability to disable cascading for trash/restore --- README.md | 8 +++++ src/Model/Behavior/TrashBehavior.php | 2 ++ .../Model/Behavior/TrashBehaviorTest.php | 32 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/README.md b/README.md index cf8301f..e6ebd5e 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,14 @@ item, you can just attach the behavior to the related table classes, and set the This works on relationships where the item being deleted in the owning side of the relationship. Which means that the related table should contain the foreign key. +If you want to cascade normal (purge) deletion, but not to cascade trash/restore then: +```php +// in the initialize() method +$this->addBehavior('Muffin/Trash.Trash', [ + 'cascadeTrashAndRestore' => false, +]); +``` + ### Custom Finders - **onlyTrashed** - helps getting only those trashed records. diff --git a/src/Model/Behavior/TrashBehavior.php b/src/Model/Behavior/TrashBehavior.php index 5af92c3..e13d92b 100644 --- a/src/Model/Behavior/TrashBehavior.php +++ b/src/Model/Behavior/TrashBehavior.php @@ -43,6 +43,7 @@ class TrashBehavior extends Behavior 'Model.beforeDelete', 'Model.beforeFind', ], + 'cascadeTrashAndRestore' => true, ]; /** @@ -388,6 +389,7 @@ protected function _isRecursable(Association $association, Table $table): bool $association->getTarget()->hasBehavior('Trash') || $association->getTarget()->hasBehavior(static::class) ) + && $this->getConfig('cascadeTrashAndRestore') && $association->isOwningSide($table) && $association->getDependent() && $association->getCascadeCallbacks(); diff --git a/tests/TestCase/Model/Behavior/TrashBehaviorTest.php b/tests/TestCase/Model/Behavior/TrashBehaviorTest.php index d75cb69..1adbece 100644 --- a/tests/TestCase/Model/Behavior/TrashBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/TrashBehaviorTest.php @@ -526,6 +526,38 @@ public function testCascadingTrash() $this->assertInstanceOf(DateTime::class, $article->comments[0]->trashed); } + /** + * When cascadeTrashAndRestore = false + * Ensure that when trashing it will not cascade into related dependent records + * + * @return void + */ + public function testDisabledCascadingForTrash() + { + $association = $this->Articles->Comments; + $association->setDependent(true); + $association->setCascadeCallbacks(true); + + // disable cascade trash/restore + $this->Articles->behaviors()->get('Trash')->setConfig('cascadeTrashAndRestore', false); + + $article = $this->Articles->get(1); + $this->Articles->trash($article); + + $article = $this->Articles->find('withTrashed') + ->where(['Articles.id' => 1]) + ->contain(['Comments' => [ + 'finder' => 'withTrashed', + ]]) + ->first(); + + $this->assertNotEmpty($article->trashed); + $this->assertInstanceOf(DateTime::class, $article->trashed); + + // expect not trashed + $this->assertEmpty($article->comments[0]->trashed); + } + public function testCascadingUntrashOptionsArePassedToSave() { $association = $this->Articles->Comments;