diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 08aa00a..9fa6749 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: true matrix: - php: [8.0, 8.1, 8.2, 8.3] + php: [8.1, 8.2, 8.3] laravel: ['9.*', '10.*', '11.*'] stability: [prefer-stable] include: @@ -28,10 +28,6 @@ jobs: exclude: - laravel: 10.* php: 8.3 - - laravel: 10.* - php: 8.0 - - laravel: 11.* - php: 8.0 - laravel: 11.* php: 8.1 diff --git a/composer.json b/composer.json index 8155a4b..4faf664 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": "^8.0", + "php": "^8.1", "spatie/laravel-package-tools": "^1.13.6", "illuminate/contracts": "^9.0|^10.0|^11.0" }, diff --git a/src/Models/Concerns/HasFlags.php b/src/Models/Concerns/HasFlags.php index 416afea..0573b41 100644 --- a/src/Models/Concerns/HasFlags.php +++ b/src/Models/Concerns/HasFlags.php @@ -2,6 +2,7 @@ namespace Spatie\ModelFlags\Models\Concerns; +use BackedEnum; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphMany; @@ -18,48 +19,57 @@ public static function bootHasFlags() }); } + protected function enumValue(string|BackedEnum $value): string + { + if (is_string($value)) { + return $value; + } + + return (string) $value->value; + } + public function flags(): MorphMany { return $this->morphMany(config('model-flags.flag_model'), 'flaggable'); } - public function hasFlag(string $name): bool + public function hasFlag(string|BackedEnum $name): bool { return $this ->flags() - ->where('name', $name) + ->where('name', $this->enumValue($name)) ->exists(); } - public function flag($name): self + public function flag(string|BackedEnum $name): self { - $this->flags()->firstOrCreate(['name' => $name])->touch(); + $this->flags()->firstOrCreate(['name' => $this->enumValue($name)])->touch(); return $this; } - public function unflag(string $name): self + public function unflag(string|BackedEnum $name): self { - $this->flags()->where('name', $name)->delete(); + $this->flags()->where('name', $this->enumValue($name))->delete(); return $this; } - public function scopeFlagged(Builder $query, string $name): void + public function scopeFlagged(Builder $query, string|BackedEnum $name): void { $query ->whereHas( 'flags', - fn (Builder $query) => $query->where('name', $name) + fn (Builder $query) => $query->where('name', $this->enumValue($name)) ); } - public function scopeNotFlagged(Builder $query, string $name): void + public function scopeNotFlagged(Builder $query, string|BackedEnum $name): void { $query ->doesntHave( 'flags', - callback: fn (Builder $query) => $query->where('name', $name) + callback: fn (Builder $query) => $query->where('name', $this->enumValue($name)) ); } @@ -73,17 +83,17 @@ public function flagNames(): array ->toArray(); } - public function latestFlag(string $name = null): ?Flag + public function latestFlag(string|BackedEnum|null $name = null): ?Flag { return $this ->flags() - ->when($name, fn (Builder $query) => $query->where('name', $name)) + ->when($name, fn (Builder $query) => $query->where('name', $this->enumValue($name))) ->orderByDesc('updated_at')->orderByDesc('id') ->first(); } - public function lastFlaggedAt(string $name): ?Carbon + public function lastFlaggedAt(string|BackedEnum $name): ?Carbon { - return $this->latestFlag($name)?->updated_at; + return $this->latestFlag($this->enumValue($name))?->updated_at; } } diff --git a/tests/Datasets/Flags.php b/tests/Datasets/Flags.php new file mode 100644 index 0000000..b122449 --- /dev/null +++ b/tests/Datasets/Flags.php @@ -0,0 +1,8 @@ + 'flag-a', + 'a backed enum' => TestBackedEnum::test_case, +]); diff --git a/tests/HasFlagsTest.php b/tests/HasFlagsTest.php index 09f8db3..4e540df 100644 --- a/tests/HasFlagsTest.php +++ b/tests/HasFlagsTest.php @@ -10,28 +10,28 @@ $this->otherModel = TestModel::create(); }); -it('can add a flag to a model', function () { - expect($this->model->hasFlag('flag-a'))->toBeFalse(); +it('can add a flag to a model', function (string|BackedEnum $flag) { + expect($this->model->hasFlag($flag))->toBeFalse(); - $this->model->flag('flag-a'); + $this->model->flag($flag); - expect($this->model->hasFlag('flag-a'))->toBeTrue(); + expect($this->model->hasFlag($flag))->toBeTrue(); expect($this->model->hasFlag('flag-B'))->toBeFalse(); - expect($this->otherModel->hasFlag('flag-a'))->toBeFalse(); -}); + expect($this->otherModel->hasFlag($flag))->toBeFalse(); +})->with('flags'); -it('can unflag a model', function () { - $this->model->unflag('flag-a'); +it('can unflag a model', function (string|BackedEnum $flag) { + $this->model->unflag($flag); - $this->model->flag('flag-a'); + $this->model->flag($flag); $this->model->flag('flag-b'); - expect($this->model->hasFlag('flag-a'))->toBeTrue(); + expect($this->model->hasFlag($flag))->toBeTrue(); - $this->model->unflag('flag-a'); + $this->model->unflag($flag); - expect($this->model->hasFlag('flag-a'))->toBeFalse(); + expect($this->model->hasFlag($flag))->toBeFalse(); expect($this->model->hasFlag('flag-b'))->toBeTrue(); -}); +})->with('flags'); it('can get the flags from a model', function () { $this->model diff --git a/tests/TestSupport/TestBackedEnum.php b/tests/TestSupport/TestBackedEnum.php new file mode 100644 index 0000000..b6d1885 --- /dev/null +++ b/tests/TestSupport/TestBackedEnum.php @@ -0,0 +1,8 @@ +