From 28d492a9a36549bd60a261a29801befab71c5d4b Mon Sep 17 00:00:00 2001 From: Chris Mellor Date: Tue, 22 Aug 2023 18:44:24 +0100 Subject: [PATCH 1/2] Added some conditional methods + tests --- README.md | 20 ++++- src/Models/Approval.php | 42 +++++++++ src/Scopes/ApprovalStateScope.php | 2 +- .../Feature/Scopes/ApprovalStateScopeTest.php | 90 +++++++++++++++++++ 4 files changed, 150 insertions(+), 4 deletions(-) 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/src/Scopes/ApprovalStateScope.php b/src/Scopes/ApprovalStateScope.php index 6b99c90..f09a9e7 100644 --- a/src/Scopes/ApprovalStateScope.php +++ b/src/Scopes/ApprovalStateScope.php @@ -90,7 +90,7 @@ protected function addRejected(Builder $builder): void */ protected function addApprove(Builder $builder): void { - $builder->macro('approve', function (Builder $builder, bool $persist = true): int { + $builder->macro('approve', function (Builder $builder, bool $persist = true, $callback = null): int { if ($persist) { $modelClass = $builder->getModel()->approvalable_type; 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); +}); From 5683592311e6b2f9e5bd0f9a4dde1e16538c406a Mon Sep 17 00:00:00 2001 From: Chris Mellor Date: Tue, 22 Aug 2023 18:57:28 +0100 Subject: [PATCH 2/2] Remove code --- src/Scopes/ApprovalStateScope.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Scopes/ApprovalStateScope.php b/src/Scopes/ApprovalStateScope.php index f09a9e7..6b99c90 100644 --- a/src/Scopes/ApprovalStateScope.php +++ b/src/Scopes/ApprovalStateScope.php @@ -90,7 +90,7 @@ protected function addRejected(Builder $builder): void */ protected function addApprove(Builder $builder): void { - $builder->macro('approve', function (Builder $builder, bool $persist = true, $callback = null): int { + $builder->macro('approve', function (Builder $builder, bool $persist = true): int { if ($persist) { $modelClass = $builder->getModel()->approvalable_type;