From 1ad6f9840ea8166ce2b24b3d0d6da0f8728daef2 Mon Sep 17 00:00:00 2001 From: Stiven Katuuk Date: Fri, 4 Nov 2022 19:08:41 +0800 Subject: [PATCH 01/11] build(traits): support non backed enum and support php 8.1 --- composer.json | 2 +- src/Traits/LogsActivity.php | 5 +++++ tests/AbleStoreNonBackedEnumTest.php | 14 ++++++++++++++ tests/Enum/NonBackedEnum.php | 10 ++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/AbleStoreNonBackedEnumTest.php create mode 100644 tests/Enum/NonBackedEnum.php diff --git a/composer.json b/composer.json index a56f0293..5b80d9f9 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ ], "homepage": "https://github.com/spatie/activitylog", "require": { - "php": "^8.0", + "php": "^8.0|^8.1", "illuminate/config": "^8.0 || ^9.0", "illuminate/database": "^8.53 || ^9.0", "illuminate/support": "^8.0 || ^9.0", diff --git a/src/Traits/LogsActivity.php b/src/Traits/LogsActivity.php index 5a35f330..cb4bb403 100644 --- a/src/Traits/LogsActivity.php +++ b/src/Traits/LogsActivity.php @@ -17,6 +17,7 @@ use Spatie\Activitylog\Contracts\LoggablePipe; use Spatie\Activitylog\EventLogBag; use Spatie\Activitylog\LogOptions; +use UnitEnum; trait LogsActivity { @@ -366,6 +367,10 @@ public static function logChanges(Model $model): array if ($model->hasCast($attribute)) { $cast = $model->getCasts()[$attribute]; + if(function_exists('enum_exists') && enum_exists($cast)) { + $changes[$attribute] = $model->getStorableEnumValue($changes[$attribute]); + } + if ($model->isCustomDateTimeCast($cast) || $model->isImmutableCustomDateTimeCast($cast)) { $changes[$attribute] = $model->asDateTime($changes[$attribute])->format(explode(':', $cast, 2)[1]); } diff --git a/tests/AbleStoreNonBackedEnumTest.php b/tests/AbleStoreNonBackedEnumTest.php new file mode 100644 index 00000000..9d774018 --- /dev/null +++ b/tests/AbleStoreNonBackedEnumTest.php @@ -0,0 +1,14 @@ +withProperty('role', NonBackedEnum::User)->log($description); + + expect(Activity::query()->latest()->first()->description)->toEqual($description); +}); diff --git a/tests/Enum/NonBackedEnum.php b/tests/Enum/NonBackedEnum.php new file mode 100644 index 00000000..5b5d4710 --- /dev/null +++ b/tests/Enum/NonBackedEnum.php @@ -0,0 +1,10 @@ + Date: Fri, 4 Nov 2022 19:18:06 +0800 Subject: [PATCH 02/11] remove(activity log): unused namespace --- src/Traits/LogsActivity.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Traits/LogsActivity.php b/src/Traits/LogsActivity.php index cb4bb403..67b23771 100644 --- a/src/Traits/LogsActivity.php +++ b/src/Traits/LogsActivity.php @@ -17,7 +17,6 @@ use Spatie\Activitylog\Contracts\LoggablePipe; use Spatie\Activitylog\EventLogBag; use Spatie\Activitylog\LogOptions; -use UnitEnum; trait LogsActivity { From dff2ce99e956d81bc0f585272660843f8ff118b0 Mon Sep 17 00:00:00 2001 From: Stiven Katuuk Date: Fri, 4 Nov 2022 19:19:16 +0800 Subject: [PATCH 03/11] fix(enum): naming lowercase to capitalize --- tests/Enum/NonBackedEnum.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Enum/NonBackedEnum.php b/tests/Enum/NonBackedEnum.php index 5b5d4710..003be00e 100644 --- a/tests/Enum/NonBackedEnum.php +++ b/tests/Enum/NonBackedEnum.php @@ -2,7 +2,7 @@ namespace Spatie\Activitylog\Test\Enum; -enum NonBackedEnum +Enum NonBackedEnum { case Admin; From 6115677f420208c5335a996c0ebe4701939a5e50 Mon Sep 17 00:00:00 2001 From: Stiven Katuuk Date: Sat, 5 Nov 2022 07:35:25 +0800 Subject: [PATCH 04/11] refactor: clean up related commit code --- composer.json | 2 +- src/Traits/LogsActivity.php | 2 +- tests/Enum/NonBackedEnum.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 5b80d9f9..a56f0293 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ ], "homepage": "https://github.com/spatie/activitylog", "require": { - "php": "^8.0|^8.1", + "php": "^8.0", "illuminate/config": "^8.0 || ^9.0", "illuminate/database": "^8.53 || ^9.0", "illuminate/support": "^8.0 || ^9.0", diff --git a/src/Traits/LogsActivity.php b/src/Traits/LogsActivity.php index 67b23771..cbc57e51 100644 --- a/src/Traits/LogsActivity.php +++ b/src/Traits/LogsActivity.php @@ -366,7 +366,7 @@ public static function logChanges(Model $model): array if ($model->hasCast($attribute)) { $cast = $model->getCasts()[$attribute]; - if(function_exists('enum_exists') && enum_exists($cast)) { + if (function_exists('enum_exists') && enum_exists($cast)) { $changes[$attribute] = $model->getStorableEnumValue($changes[$attribute]); } diff --git a/tests/Enum/NonBackedEnum.php b/tests/Enum/NonBackedEnum.php index 003be00e..5b5d4710 100644 --- a/tests/Enum/NonBackedEnum.php +++ b/tests/Enum/NonBackedEnum.php @@ -2,7 +2,7 @@ namespace Spatie\Activitylog\Test\Enum; -Enum NonBackedEnum +enum NonBackedEnum { case Admin; From e24fd6823f322bbdcfaa6523f20c3155f1b139f8 Mon Sep 17 00:00:00 2001 From: Stiven Katuuk Date: Tue, 8 Nov 2022 18:38:06 +0800 Subject: [PATCH 05/11] fix: with property cannot perform non-backed enum --- src/ActivityLogger.php | 4 ++++ tests/AbleStoreNonBackedEnumTest.php | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ActivityLogger.php b/src/ActivityLogger.php index 464862e1..92e2d49c 100644 --- a/src/ActivityLogger.php +++ b/src/ActivityLogger.php @@ -109,6 +109,10 @@ public function withProperties(mixed $properties): static public function withProperty(string $key, mixed $value): static { + if (is_object($value) && function_exists('enum_exists') && enum_exists(get_class($value))) { + $value = $value->value ?? $value->name; + } + $this->getActivity()->properties = $this->getActivity()->properties->put($key, $value); return $this; diff --git a/tests/AbleStoreNonBackedEnumTest.php b/tests/AbleStoreNonBackedEnumTest.php index 9d774018..147cd957 100644 --- a/tests/AbleStoreNonBackedEnumTest.php +++ b/tests/AbleStoreNonBackedEnumTest.php @@ -4,11 +4,14 @@ use Spatie\Activitylog\Test\Enum\NonBackedEnum; use Spatie\Activitylog\Test\Models\Activity; +use Spatie\Activitylog\Test\Models\User; it('can store non backed enum', function () { $description = 'ROLE LOG'; - activity()->withProperty('role', NonBackedEnum::User)->log($description); + activity() + ->performedOn(User::first()) + ->withProperty('role', NonBackedEnum::User)->log($description); expect(Activity::query()->latest()->first()->description)->toEqual($description); }); From d293eebf8902f3dfe49e44697736c22956ec39fc Mon Sep 17 00:00:00 2001 From: Stiven Katuuk Date: Tue, 8 Nov 2022 19:31:14 +0800 Subject: [PATCH 06/11] build(actions): centralized business logic for value resolver --- src/Actions/ResolveForPropertyValueAction.php | 37 +++++++++++++++++++ src/ActivityLogger.php | 7 ++-- tests/AbleStoreNonBackedEnumTest.php | 22 ++++++++++- 3 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 src/Actions/ResolveForPropertyValueAction.php diff --git a/src/Actions/ResolveForPropertyValueAction.php b/src/Actions/ResolveForPropertyValueAction.php new file mode 100644 index 00000000..3e36724a --- /dev/null +++ b/src/Actions/ResolveForPropertyValueAction.php @@ -0,0 +1,37 @@ +isValueAreEnum($value)) { + return $value->value ?? $value->name; + } + + return $value; + } + + protected function isValueAreEnum($value): bool + { + if (! function_exists('enum_exists')){ + return false; + } + + $enumNamespace = is_object($value) + ? get_class($value) + : $value; + + return enum_exists($enumNamespace); + } +} diff --git a/src/ActivityLogger.php b/src/ActivityLogger.php index 92e2d49c..fa10f7c7 100644 --- a/src/ActivityLogger.php +++ b/src/ActivityLogger.php @@ -10,6 +10,7 @@ use Illuminate\Support\Str; use Illuminate\Support\Traits\Conditionable; use Illuminate\Support\Traits\Macroable; +use Spatie\Activitylog\Actions\ResolveForPropertyValueAction; use Spatie\Activitylog\Contracts\Activity as ActivityContract; class ActivityLogger @@ -102,16 +103,14 @@ public function setEvent(string $event): static public function withProperties(mixed $properties): static { - $this->getActivity()->properties = collect($properties); + $this->getActivity()->properties = collect($properties)->map(fn ($value) => ResolveForPropertyValueAction::execute($value)); return $this; } public function withProperty(string $key, mixed $value): static { - if (is_object($value) && function_exists('enum_exists') && enum_exists(get_class($value))) { - $value = $value->value ?? $value->name; - } + $value = ResolveForPropertyValueAction::execute($value); $this->getActivity()->properties = $this->getActivity()->properties->put($key, $value); diff --git a/tests/AbleStoreNonBackedEnumTest.php b/tests/AbleStoreNonBackedEnumTest.php index 147cd957..a7466197 100644 --- a/tests/AbleStoreNonBackedEnumTest.php +++ b/tests/AbleStoreNonBackedEnumTest.php @@ -6,12 +6,30 @@ use Spatie\Activitylog\Test\Models\Activity; use Spatie\Activitylog\Test\Models\User; -it('can store non backed enum', function () { +afterEach(fn() => Activity::query()->latest()->first()->delete()); + +it('can store non backed only a property', function () { $description = 'ROLE LOG'; activity() ->performedOn(User::first()) ->withProperty('role', NonBackedEnum::User)->log($description); - expect(Activity::query()->latest()->first()->description)->toEqual($description); + $latestActivity = Activity::query()->latest()->first(); + + expect($latestActivity->description)->toEqual($description) + ->and($latestActivity->properties['role'])->toEqual('User'); +}); + +it('can store non backed with properties', function () { + $description = 'ROLE LOG'; + + activity() + ->performedOn(User::first()) + ->withProperties(['role' => NonBackedEnum::User])->log($description); + + $latestActivity = Activity::query()->latest()->first(); + + expect($latestActivity->description)->toEqual($description) + ->and($latestActivity->properties['role'])->toEqual('User'); }); From fdb7477c7142e8054780ae96f371751f2d10b6f0 Mon Sep 17 00:00:00 2001 From: Stiven Katuuk Date: Tue, 8 Nov 2022 19:33:59 +0800 Subject: [PATCH 07/11] refactor(test): to meaning name --- tests/AbleStoreNonBackedEnumTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/AbleStoreNonBackedEnumTest.php b/tests/AbleStoreNonBackedEnumTest.php index a7466197..67d3cb6d 100644 --- a/tests/AbleStoreNonBackedEnumTest.php +++ b/tests/AbleStoreNonBackedEnumTest.php @@ -8,7 +8,7 @@ afterEach(fn() => Activity::query()->latest()->first()->delete()); -it('can store non backed only a property', function () { +it('can store non-backed enum only a property', function () { $description = 'ROLE LOG'; activity() @@ -21,7 +21,7 @@ ->and($latestActivity->properties['role'])->toEqual('User'); }); -it('can store non backed with properties', function () { +it('can store non-backed enum with properties', function () { $description = 'ROLE LOG'; activity() From fc49a8328eb137d760e175c1cbb350b839c6c216 Mon Sep 17 00:00:00 2001 From: Stiven Katuuk Date: Wed, 9 Nov 2022 09:51:54 +0800 Subject: [PATCH 08/11] fix: skipping test and fix action logic --- src/Actions/ResolveForPropertyValueAction.php | 11 ++++++----- tests/AbleStoreNonBackedEnumTest.php | 6 ++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Actions/ResolveForPropertyValueAction.php b/src/Actions/ResolveForPropertyValueAction.php index 3e36724a..28f01940 100644 --- a/src/Actions/ResolveForPropertyValueAction.php +++ b/src/Actions/ResolveForPropertyValueAction.php @@ -6,7 +6,7 @@ class ResolveForPropertyValueAction { /** * Action that resolve property value of log - * that cannot be handled by PHP or This Package + * that cannot be handled by PHP as default * * @param mixed $value * @return mixed @@ -15,6 +15,9 @@ public static function execute(mixed $value): mixed { $instance = new static; + /** + * Give a fallback value if value not a backed enum + */ if ($instance->isValueAreEnum($value)) { return $value->value ?? $value->name; } @@ -28,10 +31,8 @@ protected function isValueAreEnum($value): bool return false; } - $enumNamespace = is_object($value) - ? get_class($value) - : $value; + $enumNamespace = is_object($value) ? get_class($value): $value; - return enum_exists($enumNamespace); + return ! is_array($value) && enum_exists($enumNamespace); } } diff --git a/tests/AbleStoreNonBackedEnumTest.php b/tests/AbleStoreNonBackedEnumTest.php index 67d3cb6d..ac9000f2 100644 --- a/tests/AbleStoreNonBackedEnumTest.php +++ b/tests/AbleStoreNonBackedEnumTest.php @@ -19,7 +19,8 @@ expect($latestActivity->description)->toEqual($description) ->and($latestActivity->properties['role'])->toEqual('User'); -}); +}) + ->skip(! function_exists('enum_exists'), "PHP doesn't support enum"); it('can store non-backed enum with properties', function () { $description = 'ROLE LOG'; @@ -32,4 +33,5 @@ expect($latestActivity->description)->toEqual($description) ->and($latestActivity->properties['role'])->toEqual('User'); -}); +}) + ->skip(! function_exists('enum_exists'), "PHP doesn't support enum"); From 72492c5d48e080241cf96696c635f7666f7eaa6c Mon Sep 17 00:00:00 2001 From: Stiven Katuuk Date: Wed, 9 Nov 2022 18:54:40 +0800 Subject: [PATCH 09/11] fix: test strict skipping conditional base on php version --- tests/AbleStoreNonBackedEnumTest.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/AbleStoreNonBackedEnumTest.php b/tests/AbleStoreNonBackedEnumTest.php index ac9000f2..92edf510 100644 --- a/tests/AbleStoreNonBackedEnumTest.php +++ b/tests/AbleStoreNonBackedEnumTest.php @@ -2,6 +2,7 @@ namespace Spatie\Activitylog\Test; +use Illuminate\Support\Str; use Spatie\Activitylog\Test\Enum\NonBackedEnum; use Spatie\Activitylog\Test\Models\Activity; use Spatie\Activitylog\Test\Models\User; @@ -20,7 +21,7 @@ expect($latestActivity->description)->toEqual($description) ->and($latestActivity->properties['role'])->toEqual('User'); }) - ->skip(! function_exists('enum_exists'), "PHP doesn't support enum"); + ->skip(! Str::of(PHP_VERSION)->startsWith('8.1'), "PHP doesn't support enum"); it('can store non-backed enum with properties', function () { $description = 'ROLE LOG'; @@ -34,4 +35,5 @@ expect($latestActivity->description)->toEqual($description) ->and($latestActivity->properties['role'])->toEqual('User'); }) - ->skip(! function_exists('enum_exists'), "PHP doesn't support enum"); + ->skip(! Str::of(PHP_VERSION)->startsWith('8.1'), "PHP doesn't support enum"); + From 6c873a50d2a9b52c36be6e6ebbbd9edb5cd3fda2 Mon Sep 17 00:00:00 2001 From: Stiven Katuuk Date: Wed, 9 Nov 2022 19:03:13 +0800 Subject: [PATCH 10/11] refactor(test): skip test with versio compare conditional --- tests/AbleStoreNonBackedEnumTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/AbleStoreNonBackedEnumTest.php b/tests/AbleStoreNonBackedEnumTest.php index 92edf510..0366d11a 100644 --- a/tests/AbleStoreNonBackedEnumTest.php +++ b/tests/AbleStoreNonBackedEnumTest.php @@ -21,7 +21,7 @@ expect($latestActivity->description)->toEqual($description) ->and($latestActivity->properties['role'])->toEqual('User'); }) - ->skip(! Str::of(PHP_VERSION)->startsWith('8.1'), "PHP doesn't support enum"); + ->skip(version_compare(PHP_VERSION, '8.1', '<'), "PHP < 8.1 doesn't support enum"); it('can store non-backed enum with properties', function () { $description = 'ROLE LOG'; @@ -35,5 +35,5 @@ expect($latestActivity->description)->toEqual($description) ->and($latestActivity->properties['role'])->toEqual('User'); }) - ->skip(! Str::of(PHP_VERSION)->startsWith('8.1'), "PHP doesn't support enum"); + ->skip(version_compare(PHP_VERSION, '8.1', '<'), "PHP < 8.1 doesn't support enum"); From ec8bd332f019e796dc75447e4d86554900c847ee Mon Sep 17 00:00:00 2001 From: Stiven Katuuk Date: Thu, 10 Nov 2022 09:23:57 +0800 Subject: [PATCH 11/11] refactor(action): renaming is value are enum method to is value an enum --- src/Actions/ResolveForPropertyValueAction.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Actions/ResolveForPropertyValueAction.php b/src/Actions/ResolveForPropertyValueAction.php index 28f01940..2d742752 100644 --- a/src/Actions/ResolveForPropertyValueAction.php +++ b/src/Actions/ResolveForPropertyValueAction.php @@ -18,14 +18,14 @@ public static function execute(mixed $value): mixed /** * Give a fallback value if value not a backed enum */ - if ($instance->isValueAreEnum($value)) { + if ($instance->isValueAnEnum($value)) { return $value->value ?? $value->name; } return $value; } - protected function isValueAreEnum($value): bool + protected function isValueAnEnum($value): bool { if (! function_exists('enum_exists')){ return false;