diff --git a/src/Actions/ResolveForPropertyValueAction.php b/src/Actions/ResolveForPropertyValueAction.php new file mode 100644 index 00000000..2d742752 --- /dev/null +++ b/src/Actions/ResolveForPropertyValueAction.php @@ -0,0 +1,38 @@ +isValueAnEnum($value)) { + return $value->value ?? $value->name; + } + + return $value; + } + + protected function isValueAnEnum($value): bool + { + if (! function_exists('enum_exists')){ + return false; + } + + $enumNamespace = is_object($value) ? get_class($value): $value; + + return ! is_array($value) && enum_exists($enumNamespace); + } +} diff --git a/src/ActivityLogger.php b/src/ActivityLogger.php index 464862e1..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,13 +103,15 @@ 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 { + $value = ResolveForPropertyValueAction::execute($value); + $this->getActivity()->properties = $this->getActivity()->properties->put($key, $value); return $this; diff --git a/src/Traits/LogsActivity.php b/src/Traits/LogsActivity.php index 5a35f330..cbc57e51 100644 --- a/src/Traits/LogsActivity.php +++ b/src/Traits/LogsActivity.php @@ -366,6 +366,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..0366d11a --- /dev/null +++ b/tests/AbleStoreNonBackedEnumTest.php @@ -0,0 +1,39 @@ + Activity::query()->latest()->first()->delete()); + +it('can store non-backed enum only a property', function () { + $description = 'ROLE LOG'; + + activity() + ->performedOn(User::first()) + ->withProperty('role', NonBackedEnum::User)->log($description); + + $latestActivity = Activity::query()->latest()->first(); + + expect($latestActivity->description)->toEqual($description) + ->and($latestActivity->properties['role'])->toEqual('User'); +}) + ->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'; + + 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'); +}) + ->skip(version_compare(PHP_VERSION, '8.1', '<'), "PHP < 8.1 doesn't support enum"); + 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 @@ +