diff --git a/src/Drivers/SoftDeleteDriver.php b/src/Drivers/SoftDeleteDriver.php index 725c443..c728892 100644 --- a/src/Drivers/SoftDeleteDriver.php +++ b/src/Drivers/SoftDeleteDriver.php @@ -23,6 +23,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; use InvalidArgumentException; +use RuntimeException; class SoftDeleteDriver extends StandardDriver { @@ -81,11 +82,23 @@ public function persist(Model $model): bool * @see https://github.com/cloudcreativity/laravel-json-api/issues/371 */ if ($this->willSoftDelete($model)) { + assert(method_exists($model, 'getDeletedAtColumn')); $column = $model->getDeletedAtColumn(); // save the original date so we can put it back later on. $deletedAt = $model->{$column}; // delete the record so that deleting and deleted events get fired. - $model->delete(); + $response = $model->delete(); // capture the response + + // if a listener prevented the delete from happening, we need to throw as we are in an invalid state. + // developers should prevent this scenario from happening either through authorization or validation. + if ($response === false) { + throw new RuntimeException(sprintf( + 'Failed to soft delete model - %s:%s', + $model::class, + $model->getKey(), + )); + } + // apply the original date back before saving, so that we keep date provided by the client. $model->{$column} = $deletedAt; } diff --git a/tests/lib/Acceptance/SoftDeleteTest.php b/tests/lib/Acceptance/SoftDeleteTest.php index 46344a6..d74be32 100644 --- a/tests/lib/Acceptance/SoftDeleteTest.php +++ b/tests/lib/Acceptance/SoftDeleteTest.php @@ -332,6 +332,23 @@ public function testItDoesNotSoftDeleteOnUpdate(): void ])); } + public function testItDoesNotSoftDeleteOnUpdateIfListenerReturnsFalse(): void + { + $post = Post::factory()->create(['deleted_at' => null]); + + $data = ['deletedAt' => now()->toJSON(), 'title' => 'Hello World!']; + + Post::deleting(fn() => false); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Failed to soft delete model - App\Models\Post:' . $post->getKey()); + + $this->schema + ->repository() + ->update($post) + ->store($data); + } + public function testItRestores(): void { $restored = false;