diff --git a/README.md b/README.md index 10cbc5a..9818cb3 100644 --- a/README.md +++ b/README.md @@ -11,22 +11,19 @@ This package provides a `HasStatuses` trait that, once installed on a model, all ```php // set a status -$model->setStatus(ModelStatus::Pending, 'needs verification'); +$model->setStatus('pending', 'needs verification'); // set another status -$model->setStatus(ModelStatus::Approved); +$model->setStatus('accepted'); // specify a reason -$model->setStatus(ModelStatus::Rejected, 'My rejection reason'); +$model->setStatus('rejected', 'My rejection reason'); -// get the current status model +// get the current status $model->status(); // returns an instance of \Spatie\ModelStatus\Status -//get the current status -$model->status; //returns an instance of the status enum - // get the previous status -$latestPendingStatus = $model->latestStatus(ModelStatus::Pending); +$latestPendingStatus = $model->latestStatus('pending'); $latestPendingStatus->reason; // returns 'needs verification' ``` @@ -87,19 +84,7 @@ return [ ## Usage -Create The Enum that holds all of your available statuses for the model. \ -The enum must be string backed - -```php -enum ModelStatusEnum: string -{ - case Pending = "pending"; - case Approved = "approved"; - case Rejected = "rejected"; -} -``` - -Add the `HasStatuses` trait to a model you like to use statuses on and implement the abstract function getStatusEnumClass. Inside, you must return the class name of the enum you desire to use with this model. +Add the `HasStatuses` trait to a model you like to use statuses on. ```php use Spatie\ModelStatus\HasStatuses; @@ -107,11 +92,6 @@ use Spatie\ModelStatus\HasStatuses; class YourEloquentModel extends Model { use HasStatuses; - - public static function getStatusEnumClass(): string - { - return ModelStatusEnum::class; - } } ``` @@ -120,13 +100,13 @@ class YourEloquentModel extends Model You can set a new status like this: ```php -$model->setStatus(ModelStatusEnum::Pending); +$model->setStatus('status-name'); ``` A reason for the status change can be passed as a second argument. ```php -$model->setStatus(ModelStatusEnum::Approved, 'optional reason'); +$model->setStatus('status-name', 'optional reason'); ``` ### Retrieving statuses @@ -134,27 +114,31 @@ $model->setStatus(ModelStatusEnum::Approved, 'optional reason'); You can get the current status of model: ```php -$model->status; // returns an enum instance of the latest status assigned to the model +$model->status; // returns a string with the name of the latest status $model->status(); // returns the latest instance of `Spatie\ModelStatus\Status` $model->latestStatus(); // equivalent to `$model->status()` ``` -You can also get latest status of a given value: +You can also get latest status of a given name: ```php -$model->latestStatus(ModelStatusEnum::Approved); // returns an instance of `Spatie\ModelStatus\Status` that has the value `approved` +$model->latestStatus('pending'); // returns an instance of `Spatie\ModelStatus\Status` that has the name `pending` ``` +Get all available status names for the model. +```php +$statusNames = $model->getStatusNames(); // returns a collection of all available status names. +``` -The following examples will return statusses of type Approved or Rejected, whichever is latest. +The following examples will return statusses of type `status 1` or `status 2`, whichever is latest. ```php -$lastStatus = $model->latestStatus([ModelStatusEnum::Approved, ModelStatusEnum::Rejected]); +$lastStatus = $model->latestStatus(['status 1', 'status 2']); // or alternatively... -$lastStatus = $model->latestStatus(ModelStatusEnum::Approved, ModelStatusEnum::Rejected); +$lastStatus = $model->latestStatus('status 1', 'status 2'); ``` All associated statuses of a model can be retrieved like this: @@ -165,45 +149,45 @@ $allStatuses = $model->statuses; This will check if the model has status: ```php -$model->setStatus(ModelStatusEnum::Approved); +$model->setStatus('status1'); -$isStatusExist = $model->hasStatus(ModelStatusEnum::Approved); // return true -$isStatusExist = $model->hasStatus(ModelStatusEnum::Rejected); // return false +$isStatusExist = $model->hasStatus('status1'); // return true +$isStatusExist = $model->hasStatus('status2'); // return false ``` ### Retrieving models with a given latest state -The `currentStatus` scope will return models that have a status with the given value. +The `currentStatus` scope will return models that have a status with the given name. ```php -$allPendingModels = Model::currentStatus(ModelStatusEnum::Approved); +$allPendingModels = Model::currentStatus('pending'); //or array of statuses -$allPendingModels = Model::currentStatus([ModelStatusEnum::Approved, ModelStatusEnum::Pending]); -$allPendingModels = Model::currentStatus(ModelStatusEnum::Approved, ModelStatusEnum::Pending); +$allPendingModels = Model::currentStatus(['pending', 'initiated']); +$allPendingModels = Model::currentStatus('pending', 'initiated'); ``` -### Retrieving models without a given status +### Retrieving models without a given state The `otherCurrentStatus` scope will return all models that do not have a status with the given name, including any model that does not have any statuses associated with them. ```php -$allNonPendingModels = Model::otherCurrentStatus(ModelStatusEnum::Pending); +$allNonPendingModels = Model::otherCurrentStatus('pending'); ``` You can also provide an array of status names to exclude from the query. ```php -$allNonPendingOrRejectedModels = Model::otherCurrentStatus([ModelStatusEnum::Pending, ModelStatusEnum::Rejected]); +$allNonInitiatedOrPendingModels = Model::otherCurrentStatus(['initiated', 'pending']); // or alternatively... -$allNonPendingOrRejectedModels = Model::otherCurrentStatus(ModelStatusEnum::Pending, ModelStatusEnum::Rejected); +$allNonInitiatedOrPendingModels = Model::otherCurrentStatus('initiated', 'pending'); ``` ### Validating a status before setting it -You can add custom validation when setting a status by overriding the `isValidStatus` method: +You can add custom validation when setting a status by overwriting the `isValidStatus` method: ```php -public function isValidStatus($statusEnum, ?string $reason = null): bool +public function isValidStatus(string $name, ?string $reason = null): bool { ... @@ -220,7 +204,7 @@ If `isValidStatus` returns `false` a `Spatie\ModelStatus\Exceptions\InvalidStatu You may bypass validation with the `forceSetStatus` method: ```php -$model->forceSetStatus(ModelStatusEnum::Pending); +$model->forceSetStatus('invalid-status-name'); ``` ### Check if status has been assigned @@ -228,7 +212,7 @@ $model->forceSetStatus(ModelStatusEnum::Pending); You can check if a specific status has been set on the model at any time by using the `hasEverHadStatus` method: ```php -$model->hasEverHadStatus(ModelStatusEnum::Approved); +$model->hasEverHadStatus('status 1'); ``` ### Delete status from model @@ -238,13 +222,13 @@ You can delete any given status that has been set on the model at any time by us Delete single status from model: ```php -$model->deleteStatus(ModelStatusEnum::Rejected); +$model->deleteStatus('status 1'); ``` Delete multiple statuses from model at once: ```php -$model->deleteStatus([ModelStatusEnum::Pending, ModelStatusEnum::Rejected]); +$model->deleteStatus(['status 1', 'status 2']); ``` ### Events diff --git a/src/Exceptions/InvalidEnumClass.php b/src/Exceptions/InvalidEnumClass.php deleted file mode 100644 index fa30d9f..0000000 --- a/src/Exceptions/InvalidEnumClass.php +++ /dev/null @@ -1,13 +0,0 @@ -morphMany($this->getStatusModelClassName(), 'model', 'model_type', $this->getModelKeyColumnName()) ->latest('id'); } @@ -33,72 +25,63 @@ public function status(): ?Status return $this->latestStatus(); } - public function setStatus($statusEnum, ?string $reason = null): self + public function setStatus(string $name, ?string $reason = null): self { - if (! $this->isValidStatus($statusEnum, $reason)) { - throw InvalidStatus::create($statusEnum->value); + if (! $this->isValidStatus($name, $reason)) { + throw InvalidStatus::create($name); } - return $this->forceSetStatus($statusEnum, $reason); + return $this->forceSetStatus($name, $reason); } - public function isValidStatus($statusEnum, ?string $reason = null): bool + public function isValidStatus(string $name, ?string $reason = null): bool { return true; } /** - * @param object|array $names + * @param string|array $names * * @return null|Status */ - public function latestStatus(...$statusEnums): ?Status + public function latestStatus(...$names): ?Status { $statuses = $this->relationLoaded('statuses') ? $this->statuses : $this->statuses(); - $statusEnums = is_array($statusEnums) ? Arr::flatten($statusEnums) : func_get_args(); - - Arr::map($statusEnums, fn ($statusEnum) => $statusEnum->value); - - if (count($statusEnums) < 1) { + $names = is_array($names) ? Arr::flatten($names) : func_get_args(); + if (count($names) < 1) { return $statuses->first(); } - return $statuses->whereIn('name', $statusEnums)->first(); + return $statuses->whereIn('name', $names)->first(); } - public function hasEverHadStatus($statusEnum): bool + public function hasEverHadStatus($name): bool { $statuses = $this->relationLoaded('statuses') ? $this->statuses : $this->statuses(); - return $statuses->where('name', $statusEnum->value)->count() > 0; + return $statuses->where('name', $name)->count() > 0; } - public function deleteStatus(...$statusEnums) + public function deleteStatus(...$names) { - $statusEnums = is_array($statusEnums) ? Arr::flatten($statusEnums) : func_get_args(); - - Arr::map($statusEnums, fn ($statusEnum) => $statusEnum->value); - - if (count($statusEnums) < 1) { + $names = is_array($names) ? Arr::flatten($names) : func_get_args(); + if (count($names) < 1) { return $this; } - $this->statuses()->whereIn('name', $statusEnums)->delete(); + $this->statuses()->whereIn('name', $names)->delete(); } - public function scopeCurrentStatus(Builder $builder, ...$statusEnums) + public function scopeCurrentStatus(Builder $builder, ...$names) { - $statusEnums = is_array($statusEnums) ? Arr::flatten($statusEnums) : func_get_args(); - - Arr::map($statusEnums, fn ($statusEnum) => $statusEnum->value); - + $names = is_array($names) ? Arr::flatten($names) : func_get_args(); $builder ->whereHas( 'statuses', - function (Builder $query) use ($statusEnums) { + function (Builder $query) use ($names) { $query - ->whereIn('name', $statusEnums) + ->whereIn('name', $names) ->whereIn( 'id', function (QueryBuilder $query) { @@ -114,25 +97,22 @@ function (QueryBuilder $query) { } /** - * @param object|array $names + * @param string|array $names * * @return void **/ - public function scopeOtherCurrentStatus(Builder $builder, ...$statusEnums) + public function scopeOtherCurrentStatus(Builder $builder, ...$names) { - $statusEnums = is_array($statusEnums) ? Arr::flatten($statusEnums) : func_get_args(); - - Arr::map($statusEnums, fn ($statusEnum) => $statusEnum->value); - + $names = is_array($names) ? Arr::flatten($names) : func_get_args(); $builder ->whereHas( 'statuses', - function (Builder $query) use ($statusEnums) { + function (Builder $query) use ($names) { $query - ->whereNotIn('name', $statusEnums) + ->whereNotIn('name', $names) ->whereIn( 'id', - function (QueryBuilder $query) use ($statusEnums) { + function (QueryBuilder $query) use ($names) { $query ->select(DB::raw('max(id)')) ->from($this->getStatusTableName()) @@ -145,30 +125,12 @@ function (QueryBuilder $query) use ($statusEnums) { ->orWhereDoesntHave('statuses'); } - - private static function isInstanceOfEnum($statusEnum): bool - { - $statusEnumType = self::getStatusEnumClass(); - - return $statusEnum instanceof $statusEnumType; - } - - private static function enumIsStringBacked(): bool - { - return method_exists(self::getStatusEnumClass(), 'from'); - } - - - public function forceSetStatus($statusEnum, ?string $reason = null): self + public function forceSetStatus(string $name, ?string $reason = null): self { - if (! self::isInstanceOfEnum($statusEnum)) { - throw InvalidEnumClass::create(self::getStatusEnumClass()); - } - $oldStatus = $this->latestStatus(); $newStatus = $this->statuses()->create([ - 'name' => $statusEnum->value, + 'name' => $name, 'reason' => $reason, ]); @@ -212,14 +174,25 @@ protected function getStatusModelType(): string public function __get($key): mixed { if ($key === $this->getStatusAttributeName()) { - return $this->getStatusEnumClass()::from((string) $this->latestStatus()); + return (string) $this->latestStatus(); } return parent::__get($key); } + /* + * Get all available status names for the model. + * + * @return \Illuminate\Support\Collection + */ + public function getStatusNames(): Collection + { + $statusModel = app($this->getStatusModelClassName()); + + return $statusModel->pluck('name'); + } - public function hasStatus($statusEnum): bool + public function hasStatus(string $name): bool { - return $this->statuses()->where('name', $statusEnum->value)->exists(); + return $this->statuses()->where('name', $name)->exists(); } } diff --git a/tests/Events/StatusEventsTest.php b/tests/Events/StatusEventsTest.php index 5faf020..91d4fb8 100644 --- a/tests/Events/StatusEventsTest.php +++ b/tests/Events/StatusEventsTest.php @@ -2,7 +2,6 @@ use Illuminate\Support\Facades\Event; use Spatie\ModelStatus\Events\StatusUpdated; -use Spatie\ModelStatus\Tests\Models\TestEnum; use Spatie\ModelStatus\Tests\Models\TestModel; beforeEach(function () { @@ -12,11 +11,11 @@ }); it('fires an event when status changes', function () { - $this->testModel->setStatus(TestEnum::Pending, 'waiting on action'); + $this->testModel->setStatus('pending', 'waiting on action'); Event::fake(); - $this->testModel->setStatus(TestEnum::Approved, 'Reason a'); + $this->testModel->setStatus('status a', 'Reason a'); Event::assertDispatched( StatusUpdated::class, @@ -25,11 +24,11 @@ function (StatusUpdated $event) { return false; } - if ($event->newStatus->name !== TestEnum::Approved->value) { + if ($event->newStatus->name !== 'status a') { return false; } - if ($event->oldStatus->name !== TestEnum::Pending->value) { + if ($event->oldStatus->name !== 'pending') { return false; } diff --git a/tests/HasStatusesTest.php b/tests/HasStatusesTest.php index 1050ff3..a127789 100644 --- a/tests/HasStatusesTest.php +++ b/tests/HasStatusesTest.php @@ -1,16 +1,10 @@ testModel->setStatus(TestEnum::Pending, 'waiting on action'); + $this->testModel->setStatus('pending', 'waiting on action'); $name = $this->testModel->statuses->first()->name; $reason = $this->testModel->statuses->first()->reason; - expect($name)->toEqual(TestEnum::Pending->value) + expect($name)->toEqual('pending') ->and($reason)->toEqual('waiting on action'); }); test('a reason can be set') - ->tap(fn () => $this->testModel->setStatus(TestEnum::Pending, 'waiting on action')) + ->tap(fn () => $this->testModel->setStatus('pending', 'waiting on action')) ->expect(fn () => $this->testModel->status()->reason) ->toEqual('waiting on action'); @@ -39,7 +33,7 @@ 'name' => 'name', ]); - $validationUser->setStatus(TestEnum::InvalidStatus); + $validationUser->setStatus('InvalidStatus'); })->throws(InvalidStatus::class); it('can force set an invalid status', function () { @@ -47,30 +41,24 @@ 'name' => 'name', ]); - $validationUser->forceSetStatus(TestEnum::InvalidStatus); + $validationUser->forceSetStatus('InvalidStatus'); - $status = $validationUser->statuses->first()->name; + $name = $validationUser->statuses->first()->name; - expect($status)->toEqual(TestEnum::InvalidStatus->value); + expect($name)->toEqual('InvalidStatus'); }); -it('throws an exception if status enum instance was from a different enum', function () { - $this->testModel->setStatus(TestEnum2::TestStatus, 'test'); -})->throws(InvalidEnumClass::class); -; - - -it('can find the last status by enum', function () { +it('can find the last status by name', function () { $this->testModel - ->setStatus(TestEnum::Pending, 'reason 1') - ->setStatus(TestEnum::Approved, 'reason 2') - ->setStatus(TestEnum::Pending, 'reason 3'); + ->setStatus('status a', 'reason 1') + ->setStatus('status b', 'reason 2') + ->setStatus('status a', 'reason 3'); expect( - $this->testModel->latestStatus(TestEnum::Pending)->reason + $this->testModel->latestStatus('status a')->reason )->toEqual('reason 3') ->and( - $this->testModel->latestStatus(TestEnum::Approved)->reason + $this->testModel->latestStatus('status b')->reason )->toEqual('reason 2'); }); @@ -79,69 +67,71 @@ ->toBeNull(); it('can handle an empty reason when setting a status') - ->tap(fn () => $this->testModel->setStatus(TestEnum::Approved)) + ->tap(fn () => $this->testModel->setStatus('status')) ->expect(fn () => $this->testModel->status()->name) - ->toEqual(TestEnum::Approved->value); + ->toEqual('status'); it('allows null for an empty reason when setting a status') - ->tap(fn () => $this->testModel->setStatus(TestEnum::Approved, null)) + ->tap(fn () => $this->testModel->setStatus('status', null)) ->expect(fn () => $this->testModel->status()->reason) ->toBeNull(); -it('can return the latest status', function () { +it('can return the latest status', function ( + +) { $this->testModel - ->setStatus(TestEnum::Pending) - ->setStatus(TestEnum::Rejected) - ->setStatus(TestEnum::Approved) - ->setStatus(TestEnum::Pending) - ->setStatus(TestEnum::Approved); + ->setStatus('status 1') + ->setStatus('status 3') + ->setStatus('status 2') + ->setStatus('status 1') + ->setStatus('status 2'); - $model = $this->testModel->latestStatus(TestEnum::Pending, TestEnum::Rejected); - expect($model->name)->toBe(TestEnum::Pending->value); + $model = $this->testModel->latestStatus('status 1', 'status 3'); + expect($model->name)->toBe('status 1'); - $model = $this->testModel->latestStatus([TestEnum::Pending, TestEnum::Rejected]); - expect($model->name)->toBe(TestEnum::Pending->value); + $model = $this->testModel->latestStatus(['status 1', 'status 3']); + expect($model->name)->toBe('status 1'); - $model = $this->testModel->latestStatus(TestEnum::Pending, TestEnum::Approved, TestEnum::Rejected); - expect($model->name)->toBe(TestEnum::Approved->value); + $model = $this->testModel->latestStatus('status 1', 'status 2', 'status 3'); + expect($model->name)->toBe('status 2'); - $model = $this->testModel->latestStatus(TestEnum::UnusedStatus); + $model = $this->testModel->latestStatus('non existing status'); expect($model)->toBeNull(); }); it('will return `true` if specific status is found') - ->tap(fn () => $this->testModel->setStatus(TestEnum::Pending)) - ->expect(fn () => $this->testModel->hasEverHadStatus(TestEnum::Pending)) + ->tap(fn () => $this->testModel->setStatus('status 1')) + ->expect(fn () => $this->testModel->hasEverHadStatus('status 1')) ->toBeTrue(); it('will return `false` if specific status is not found') - ->tap(fn () => $this->testModel->setStatus(TestEnum::Pending)) - ->expect(fn () => $this->testModel->hasEverHadStatus(TestEnum::Approved)) + ->tap(fn () => $this->testModel->setStatus('status 1')) + ->expect(fn () => $this->testModel->hasEverHadStatus('status 2')) ->toBeFalse(); it('can delete a specific status', function () { - $this->testModel->setStatus(TestEnum::Rejected); + $this->testModel->setStatus('status to delete'); expect($this->testModel->statuses()->count())->toEqual(1); - $this->testModel->deleteStatus(TestEnum::Rejected); + $this->testModel->deleteStatus('status to delete'); expect($this->testModel->statuses()->count())->toEqual(0); }); it('can delete a multiple statuses at once', function () { - $this->testModel->setStatus(TestEnum::Rejected) - ->setStatus(TestEnum::Approved); + $this->testModel->setStatus('status to delete 1') + ->setStatus('status to delete 2'); expect($this->testModel->statuses()->count())->toEqual(2); - $this->testModel->deleteStatus(TestEnum::Rejected, TestEnum::Approved); + $this->testModel->deleteStatus('status to delete 1', 'status to delete 2'); expect($this->testModel->statuses()->count())->toEqual(0); }); it('will keep status when invalid delete status is given', function () { - $this->testModel->setStatus(TestEnum::Approved); + $this->testModel->setStatus('status to delete'); expect($this->testModel->statuses()->count())->toEqual(1); @@ -155,82 +145,82 @@ fn () => config()->set('model-status.status_model', AlternativeStatusModel::class) ) ->tap( - fn () => $this->testModel->setStatus(TestEnum::Approved, 'waiting on action') + fn () => $this->testModel->setStatus('pending', 'waiting on action') ) ->expect(fn () => $this->testModel->status()) ->toBeInstanceOf(AlternativeStatusModel::class); -it('can find all models that have a last status with the given enum', function () { +it('can find all models that have a last status with the given name', function () { $model1 = TestModel::create(['name' => 'model1']); $model2 = TestModel::create(['name' => 'model2']); $model3 = TestModel::create(['name' => 'model3']); $model4 = TestModel::create(['name' => 'model4']); $model1 - ->setStatus(TestEnum::Pending) - ->setStatus(TestEnum::Approved) - ->setStatus(TestEnum::Rejected) - ->setStatus(TestEnum::Approved); + ->setStatus('status-a') + ->setStatus('status-b') + ->setStatus('status-c') + ->setStatus('status-b'); - $model2->setStatus(TestEnum::Rejected); + $model2->setStatus('status-c'); - $model3->setStatus(TestEnum::Approved); + $model3->setStatus('status-b'); - $model4->setStatus(TestEnum::Pending); + $model4->setStatus('status-a'); expect([ - TestModel::currentStatus(TestEnum::Pending)->get()->pluck('name')->toArray(), - TestModel::currentStatus(TestEnum::Approved)->get()->pluck('name')->toArray(), - TestModel::currentStatus(TestEnum::Rejected)->get()->pluck('name')->toArray(), - TestModel::currentStatus(TestEnum::UnusedStatus)->get()->pluck('name')->toArray(), + TestModel::currentStatus('status-a')->get()->pluck('name')->toArray(), + TestModel::currentStatus('status-b')->get()->pluck('name')->toArray(), + TestModel::currentStatus('status-c')->get()->pluck('name')->toArray(), + TestModel::currentStatus('status-d')->get()->pluck('name')->toArray(), ])->sequence(['model4'], ['model1', 'model3'], ['model2'], []); }); -it('can return an enum instance when calling the attribute', function () { +it('can return a string when calling the attribute', function () { $this ->testModel - ->setStatus(TestEnum::Pending) - ->setStatus(TestEnum::Rejected, 'waiting for a change'); + ->setStatus('free') + ->setStatus('pending', 'waiting for a change'); - expect($this->testModel->status)->toEqual(TestEnum::Rejected) - ->and($this->testModel->status()->name)->toEqual(TestEnum::Rejected->value) + expect($this->testModel->status)->toEqual('pending') + ->and($this->testModel->status()->name)->toEqual('pending') ->and($this->testModel->status()->reason)->toEqual('waiting for a change'); }); it('can handle a different status attribute', function () { $this->testModel - ->setStatus(TestEnum::Pending) - ->setStatus(TestEnum::Approved, 'waiting for a change'); + ->setStatus('free') + ->setStatus('pending', 'waiting for a change'); config()->set('model-status.status_attribute', 'alternative_status'); expect($this->testModel->alternative_status) - ->toEqual(TestEnum::Approved); + ->toEqual('pending'); }); -it('can find all models that do not a certain status', function () { +it('can find all models that do not have a status with a given name', function () { $model1 = TestModel::create(['name' => 'model1']); $model2 = TestModel::create(['name' => 'model2']); $model3 = TestModel::create(['name' => 'model3']); $model4 = TestModel::create(['name' => 'model4']); $model5 = TestModel::create(['name' => 'model5']); - $this->testModel->setStatus(TestEnum::Pending); - $model1->setStatus(TestEnum::Pending); + $this->testModel->setStatus('initiated'); + $model1->setStatus('initiated'); - $model2->setStatus(TestEnum::Approved); - $model3->setStatus(TestEnum::Rejected); - $model4->setStatus(TestEnum::UnusedStatus); + $model2->setStatus('pending'); + $model3->setStatus('ready'); + $model4->setStatus('complete'); - expect(TestModel::otherCurrentStatus(TestEnum::Pending)->get())->toHaveCount(4) - ->and(TestModel::otherCurrentStatus(TestEnum::Pending, TestEnum::Approved)->get())->toHaveCount(3) - ->and(TestModel::otherCurrentStatus([TestEnum::Pending, TestEnum::Approved])->get())->toHaveCount(3); + expect(TestModel::otherCurrentStatus('initiated')->get())->toHaveCount(4) + ->and(TestModel::otherCurrentStatus('initiated', 'pending')->get())->toHaveCount(3) + ->and(TestModel::otherCurrentStatus(['initiated', 'pending'])->get())->toHaveCount(3); }); it('supports custom polymorphic model types') ->tap(fn () => Relation::morphMap(['custom-test-model' => TestModel::class])) - ->tap(fn () => $this->testModel->setStatus(TestEnum::Pending)) - ->expect(fn () => TestModel::currentStatus(TestEnum::Pending)->get()) + ->tap(fn () => $this->testModel->setStatus('initiated')) + ->expect(fn () => TestModel::currentStatus('initiated')->get()) ->toHaveCount(1); it('can use a custom name for the relationship id column', function () { @@ -238,9 +228,9 @@ config()->set('model-status.model_primary_key_attribute', 'model_custom_fk'); $model = TestModel::create(['name' => 'model1']); - $model->setStatus(TestEnum::Pending); + $model->setStatus('pending'); - expect($model->status)->toEqual(TestEnum::Pending) + expect($model->status)->toEqual('pending') ->and($model->status()->model_custom_fk)->toEqual($model->id) ->and($model->status()->is(CustomModelKeyStatusModel::first()))->toBeTrue(); }); @@ -249,26 +239,46 @@ config()->offsetUnset('model-status.model_primary_key_attribute'); $model = TestModel::create(['name' => 'model1']); - $model->setStatus(TestEnum::Pending); + $model->setStatus('pending'); - expect($model->status)->toEqual(TestEnum::Pending) + expect($model->status)->toEqual('pending') ->and($model->status()->model_id)->toEqual($model->id); }); +it('returns all available status names', function () { + + $model = TestModel::create(['name' => 'model1']); + // Set up some test statuses + $model->setStatus('status1'); + $model->setStatus('status2'); + $model->setStatus('status3'); + + // Get the status names + $statusNames = $model->getStatusNames(); + + // Assert the returned status names + expect($statusNames)->toContain('status1') + ->toContain('status2') + ->toContain('status3'); +}); + +it('returns an empty collection when there are no statuses', function () { + $model = TestModel::create(['name' => 'model1']); + + // Get the status names + $statusNames = $model->getStatusNames(); + + // Assert the returned status names + expect($statusNames)->toBeEmpty(); +}); it('checks if the model has a specific status', function () { $model = TestModel::create(['name' => 'model1']); // Set up some test statuses - $model->setStatus(TestEnum::Pending); - $model->setStatus(TestEnum::Approved); + $model->setStatus('status1'); + $model->setStatus('status3'); // Assert that the model has the specified status - expect($model->hasStatus(TestEnum::Pending))->toBeTrue(); + expect($model->hasStatus('status1'))->toBeTrue(); // Assert that the model does not have a different status - expect($model->hasStatus(TestEnum::Rejected))->toBeFalse(); + expect($model->hasStatus('status2'))->toBeFalse(); }); - - -it('throws an exception if the enum is not string backed', function () { - $model = TestModelInvalidEnumType::create(['name' => 'model1']); - $model->setStatus(TestEnumNotBacked::TestStatus1); -})->throws(InvalidEnumType::class); diff --git a/tests/Models/TestEnum.php b/tests/Models/TestEnum.php deleted file mode 100644 index b4fce7f..0000000 --- a/tests/Models/TestEnum.php +++ /dev/null @@ -1,12 +0,0 @@ -