From 365b3447f58c017a595ed6b52c3ba37290ab2f1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Fri, 12 Jan 2024 22:35:58 +0100 Subject: [PATCH] Support defining #[Meta] on traits (resolve #9) --- src/Meta/Reflection.php | 21 ++++++++++++++++----- tests/Pest/TraitTest.php | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 tests/Pest/TraitTest.php diff --git a/src/Meta/Reflection.php b/src/Meta/Reflection.php index 68799d0..1e585af 100644 --- a/src/Meta/Reflection.php +++ b/src/Meta/Reflection.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ArchTech\Enums\Meta; use ReflectionAttribute; +use ReflectionClass; use ReflectionEnumUnitCase; use ReflectionObject; @@ -19,12 +20,22 @@ class Reflection public static function metaProperties(mixed $enum): array { $reflection = new ReflectionObject($enum); + $metaProperties = static::parseMetaProperties($reflection); - // Attributes of the `Meta` type - $attributes = array_values(array_filter( - $reflection->getAttributes(), - fn (ReflectionAttribute $attr) => $attr->getName() === Meta::class, - )); + // Traits except the `Metadata` trait + $traits = array_values(array_filter($reflection->getTraits(), fn (ReflectionClass $class) => $class->getName() !== 'ArchTech\Enums\Metadata')); + + foreach ($traits as $trait) { + $metaProperties = array_merge($metaProperties, static::parseMetaProperties($trait)); + } + + return $metaProperties; + } + + protected static function parseMetaProperties(ReflectionClass $reflection): array + { + // Only the `Meta` attribute + $attributes = $reflection->getAttributes(Meta::class); if ($attributes) { /** @var Meta $meta */ diff --git a/tests/Pest/TraitTest.php b/tests/Pest/TraitTest.php new file mode 100644 index 0000000..43730aa --- /dev/null +++ b/tests/Pest/TraitTest.php @@ -0,0 +1,37 @@ +description())->toBe('Foo!'); + expect(MyEnum::BAR->description())->toBe('Bar!'); + expect(MyEnum::BAZ->description())->toBe(null); +}); + +enum MyEnum +{ + use Metadata; + use HasDescription; + + #[Description('Foo!')] + case FOO; + + #[Description('Bar!')] + case BAR; + + case BAZ; +} + +#[Attribute] +class Description extends MetaProperty +{} + +/** + * @method string|null description() + */ +#[Meta(Description::class)] +trait HasDescription +{ +}