From 1d4bb4998332de72fe63fb2017175ec562d2646a Mon Sep 17 00:00:00 2001 From: Riccardo Venturini Date: Wed, 11 Dec 2024 18:51:23 +0100 Subject: [PATCH 1/6] add string type to flag function --- src/Models/Concerns/HasFlags.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Models/Concerns/HasFlags.php b/src/Models/Concerns/HasFlags.php index 416afea..9cf6d3e 100644 --- a/src/Models/Concerns/HasFlags.php +++ b/src/Models/Concerns/HasFlags.php @@ -31,7 +31,7 @@ public function hasFlag(string $name): bool ->exists(); } - public function flag($name): self + public function flag(string $name): self { $this->flags()->firstOrCreate(['name' => $name])->touch(); From ecbbeddec2a9427bddce213bcbcda97134436c60 Mon Sep 17 00:00:00 2001 From: Grant Holle Date: Sat, 14 Dec 2024 10:22:06 -0600 Subject: [PATCH 2/6] Add enum support for flags --- composer.json | 2 +- src/Models/Concerns/HasFlags.php | 39 ++++++++++++++++++---------- tests/Datasets/Flags.php | 8 ++++++ tests/HasFlagsTest.php | 26 +++++++++---------- tests/TestSupport/TestBackedEnum.php | 8 ++++++ 5 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 tests/Datasets/Flags.php create mode 100644 tests/TestSupport/TestBackedEnum.php 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..69bea08 100644 --- a/src/Models/Concerns/HasFlags.php +++ b/src/Models/Concerns/HasFlags.php @@ -2,10 +2,12 @@ namespace Spatie\ModelFlags\Models\Concerns; +use BackedEnum; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Support\Carbon; +use function Illuminate\Support\enum_value; use Spatie\ModelFlags\Models\Flag; /** @mixin Model */ @@ -18,48 +20,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 +84,17 @@ public function flagNames(): array ->toArray(); } - public function latestFlag(string $name = null): ?Flag + public function latestFlag(string|BackedEnum $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 @@ + Date: Sat, 14 Dec 2024 10:26:19 -0600 Subject: [PATCH 3/6] Remove unused import --- src/Models/Concerns/HasFlags.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Models/Concerns/HasFlags.php b/src/Models/Concerns/HasFlags.php index 69bea08..192fb1d 100644 --- a/src/Models/Concerns/HasFlags.php +++ b/src/Models/Concerns/HasFlags.php @@ -7,7 +7,6 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Support\Carbon; -use function Illuminate\Support\enum_value; use Spatie\ModelFlags\Models\Flag; /** @mixin Model */ From dd7228b0a932aa44b3a08135c1f705299c662dd7 Mon Sep 17 00:00:00 2001 From: freekmurze Date: Mon, 16 Dec 2024 12:48:40 +0000 Subject: [PATCH 4/6] Fix styling --- src/Models/Concerns/HasFlags.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Models/Concerns/HasFlags.php b/src/Models/Concerns/HasFlags.php index 9cf6d3e..e81467a 100644 --- a/src/Models/Concerns/HasFlags.php +++ b/src/Models/Concerns/HasFlags.php @@ -73,7 +73,7 @@ public function flagNames(): array ->toArray(); } - public function latestFlag(string $name = null): ?Flag + public function latestFlag(?string $name = null): ?Flag { return $this ->flags() From bca40590d2285c8062ed66bfff92e95e1d199486 Mon Sep 17 00:00:00 2001 From: Grant Holle Date: Sat, 14 Dec 2024 10:22:06 -0600 Subject: [PATCH 5/6] Add enum support for flags --- composer.json | 2 +- src/Models/Concerns/HasFlags.php | 38 ++++++++++++++++++---------- tests/Datasets/Flags.php | 8 ++++++ tests/HasFlagsTest.php | 26 +++++++++---------- tests/TestSupport/TestBackedEnum.php | 8 ++++++ 5 files changed, 54 insertions(+), 28 deletions(-) create mode 100644 tests/Datasets/Flags.php create mode 100644 tests/TestSupport/TestBackedEnum.php 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 e81467a..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(string $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 @@ + Date: Mon, 16 Dec 2024 10:47:34 -0600 Subject: [PATCH 6/6] Remove php 8.0 from test runner --- .github/workflows/run-tests.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) 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