diff --git a/README.md b/README.md index 7d58bd5..d75e7e5 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ The config allows you to change the polymorphic pivot name. It should end with ` ## Usage -> This packages utilises Enums, so both PHP 8.1 and Laravel 9 must be used. +> The package utilises Enums, so both PHP 8.1 and Laravel 9 must be used. > > **Note** This package does not approve/deny the data for you, it just stores the new/amended data into the database. It is up to you to decide how you implement a function to approve or deny the Model. @@ -97,7 +97,7 @@ The package comes with some helper methods for the Builder, utilising a custom s By default, all queries to the `approvals` table will return all the Models' no matter the state. -There are three methods to help you retrieve the state of an Approval. +There are three methods to help you retrieve the state of the Approval. ```php postpone(); In the event you need to reset a state, you can use the `withAnyState` helper. +### Helpers + +Conditional helper methods are used, so you can set the state of an Approval when a condition is met. + +```php +$approval->approveIf(true); +$approval->rejectIf(false); +$approval->postponeIf(true); + +$approval->approveUnless(false); +$approval->rejectUnless(true); +$approval->postponeUnless(false); +``` + ### Events Once a Model's state has been changed, an event will be fired. @@ -171,4 +185,4 @@ Please open a PR with as much detail as possible about what you're trying to ach ## License -The MIT License (MIT). Please see [License File](LICENSE.md) for more information. +The MIT Licence (MIT). Please see [Licence File](LICENSE.md) for more information. diff --git a/src/Models/Approval.php b/src/Models/Approval.php index 95df268..5b9f6fc 100644 --- a/src/Models/Approval.php +++ b/src/Models/Approval.php @@ -27,4 +27,46 @@ public function approvalable(): MorphTo { return $this->morphTo(); } + + public function approveIf(bool $boolean): void + { + if ($boolean) { + $this->approve(); + } + } + + public function approveUnless(bool $boolean): void + { + if (! $boolean) { + $this->approve(); + } + } + + public function postponeIf(bool $boolean): void + { + if ($boolean) { + $this->postpone(); + } + } + + public function postponeUnless(bool $boolean): void + { + if (! $boolean) { + $this->postpone(); + } + } + + public function rejectIf(bool $boolean): void + { + if ($boolean) { + $this->reject(); + } + } + + public function rejectUnless(bool $boolean): void + { + if (! $boolean) { + $this->reject(); + } + } } diff --git a/tests/Feature/Scopes/ApprovalStateScopeTest.php b/tests/Feature/Scopes/ApprovalStateScopeTest.php index 5d211d8..56a4ed8 100644 --- a/tests/Feature/Scopes/ApprovalStateScopeTest.php +++ b/tests/Feature/Scopes/ApprovalStateScopeTest.php @@ -116,3 +116,93 @@ 'postpone' => Event::assertDispatched(ModelSetPending::class), }; })->with(['approve', 'reject', 'postpone']); + +test(description: 'A Model can be Approved if a condition is met', closure: function (): void { + FakeModel::create($this->fakeModelData); + + Event::fake(); + + $approval = Approval::first(); + $approval->approveIf(boolean: true); + + expect($approval)->fresh()->state->toBe(ApprovalStatus::Approved); + + Event::assertDispatched(event: ModelApproved::class); + + $this->assertDatabaseHas(table: 'fake_models', data: $this->fakeModelData); +}); + +test(description: 'A Model can be Approved unless a condition is met', closure: function (): void { + FakeModel::create($this->fakeModelData); + + Event::fake(); + + $approval = Approval::first(); + $approval->approveUnless(boolean: false); + + expect($approval)->fresh()->state->toBe(ApprovalStatus::Approved); + + Event::assertDispatched(event: ModelApproved::class); + + $this->assertDatabaseHas(table: 'fake_models', data: $this->fakeModelData); +}); + +test(description: 'A Model can be Rejected if a condition is met', closure: function (): void { + FakeModel::create($this->fakeModelData); + + Event::fake(); + + $approval = Approval::first(); + $approval->rejectIf(boolean: true); + + expect($approval)->fresh()->state->toBe(ApprovalStatus::Rejected); + + Event::assertDispatched(event: ModelRejected::class); + + $this->assertDatabaseMissing(table: 'fake_models', data: $this->fakeModelData); +}); + +test(description: 'A Model can be Rejected unless a condition is met', closure: function (): void { + FakeModel::create($this->fakeModelData); + + Event::fake(); + + $approval = Approval::first(); + $approval->rejectUnless(boolean: false); + + expect($approval)->fresh()->state->toBe(ApprovalStatus::Rejected); + + Event::assertDispatched(event: ModelRejected::class); + + $this->assertDatabaseMissing(table: 'fake_models', data: $this->fakeModelData); +}); + +test(description: 'A Model can be Postponed if a condition is met', closure: function (): void { + FakeModel::create($this->fakeModelData); + + Event::fake(); + + $approval = Approval::first(); + $approval->postponeIf(boolean: true); + + expect($approval)->fresh()->state->toBe(ApprovalStatus::Pending); + + Event::assertDispatched(event: ModelSetPending::class); + + $this->assertDatabaseMissing(table: 'fake_models', data: $this->fakeModelData); +}); + +test(description: 'A Model can be Postponed unless a condition is met', closure: function (): void { + FakeModel::create($this->fakeModelData); + + Event::fake(); + + $approval = Approval::first(); + $approval->postponeUnless(boolean: false); + + expect($approval)->fresh()->state->toBe(ApprovalStatus::Pending); + + Event::assertDispatched(event: ModelSetPending::class); + + $this->assertDatabaseMissing(table: 'fake_models', data: $this->fakeModelData); +});