Skip to content

Commit d9d6221

Browse files
authored
refactor!: throw exception if model cannot be soft deleted #371 (#34)
Covers the scenario where a listener or observer prevents a model from being soft-deleted. When this happens, an exception is thrown as we cannot honour the client's request and are in an invalid state.
1 parent 01aa76a commit d9d6221

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

src/Drivers/SoftDeleteDriver.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Illuminate\Database\Eloquent\Model;
2424
use Illuminate\Database\Eloquent\SoftDeletes;
2525
use InvalidArgumentException;
26+
use RuntimeException;
2627

2728
class SoftDeleteDriver extends StandardDriver
2829
{
@@ -81,11 +82,23 @@ public function persist(Model $model): bool
8182
* @see https://github.com/cloudcreativity/laravel-json-api/issues/371
8283
*/
8384
if ($this->willSoftDelete($model)) {
85+
assert(method_exists($model, 'getDeletedAtColumn'));
8486
$column = $model->getDeletedAtColumn();
8587
// save the original date so we can put it back later on.
8688
$deletedAt = $model->{$column};
8789
// delete the record so that deleting and deleted events get fired.
88-
$model->delete();
90+
$response = $model->delete(); // capture the response
91+
92+
// if a listener prevented the delete from happening, we need to throw as we are in an invalid state.
93+
// developers should prevent this scenario from happening either through authorization or validation.
94+
if ($response === false) {
95+
throw new RuntimeException(sprintf(
96+
'Failed to soft delete model - %s:%s',
97+
$model::class,
98+
$model->getKey(),
99+
));
100+
}
101+
89102
// apply the original date back before saving, so that we keep date provided by the client.
90103
$model->{$column} = $deletedAt;
91104
}

tests/lib/Acceptance/SoftDeleteTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,23 @@ public function testItDoesNotSoftDeleteOnUpdate(): void
332332
]));
333333
}
334334

335+
public function testItDoesNotSoftDeleteOnUpdateIfListenerReturnsFalse(): void
336+
{
337+
$post = Post::factory()->create(['deleted_at' => null]);
338+
339+
$data = ['deletedAt' => now()->toJSON(), 'title' => 'Hello World!'];
340+
341+
Post::deleting(fn() => false);
342+
343+
$this->expectException(\RuntimeException::class);
344+
$this->expectExceptionMessage('Failed to soft delete model - App\Models\Post:' . $post->getKey());
345+
346+
$this->schema
347+
->repository()
348+
->update($post)
349+
->store($data);
350+
}
351+
335352
public function testItRestores(): void
336353
{
337354
$restored = false;

0 commit comments

Comments
 (0)