From f270bf620cc898dfe97ba6cd2baa24a74c56366f Mon Sep 17 00:00:00 2001 From: Tac Tacelosky Date: Thu, 14 Nov 2024 15:34:23 -0500 Subject: [PATCH] feat: add array support for metadata (#6) --- README.md | 2 +- src/Metadata.php | 17 ++++++++++++----- src/Metadata/Map.php | 4 +++- tests/Fixture/Classes/Sub/Class5.php | 2 ++ tests/Unit/MetadataTest.php | 6 ++++-- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index faf5ddb..7df14c9 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ an efficient runtime lookup. These can be added via [attributes](#attributes) or 1. **Alias**: short name for a class (could be used as an alternative to storing a FQCN in the database). -2. **Metadata**: key-value map of scalar values specific to a class (could be used +2. **Metadata**: key-value map of scalar or array values specific to a class (could be used to mark a class as _trackable_ in an auditing system). This library provides a Composer plugin that hooks into Composer's dump-autoload diff --git a/src/Metadata.php b/src/Metadata.php index 1c0d41a..3769ba2 100644 --- a/src/Metadata.php +++ b/src/Metadata.php @@ -15,6 +15,8 @@ /** * @author Kevin Bond + * + * @phpstan-type Value scalar|array */ #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] final class Metadata @@ -23,8 +25,11 @@ public function __construct( /** @readonly */ public string $key, - /** @readonly */ - public string|bool|int|float $value, + /** + * @readonly + * @var Value + */ + public string|bool|int|float|array $value, ) { } @@ -33,7 +38,7 @@ public function __construct( * * @param object|class-string|string $objectOrClassOrAlias * - * @return array + * @return array */ public static function for(object|string $objectOrClassOrAlias): array { @@ -45,8 +50,9 @@ public static function for(object|string $objectOrClassOrAlias): array * or null if key does not exist. * * @param object|class-string|string $objectOrClassOrAlias + * @return Value|null */ - public static function get(object|string $objectOrClassOrAlias, string $key): string|bool|int|float|null + public static function get(object|string $objectOrClassOrAlias, string $key): string|bool|int|float|array|null { return self::for($objectOrClassOrAlias)[$key] ?? null; } @@ -56,8 +62,9 @@ public static function get(object|string $objectOrClassOrAlias, string $key): st * class/object/alias or null if no keys exist. * * @param object|class-string|string $objectOrClassOrAlias + * @return Value|null */ - public static function first(object|string $objectOrClassOrAlias, string ...$keys): string|bool|int|float|null + public static function first(object|string $objectOrClassOrAlias, string ...$keys): string|bool|int|float|array|null { $metadata = self::for($objectOrClassOrAlias); diff --git a/src/Metadata/Map.php b/src/Metadata/Map.php index 23bc27f..9ad2cce 100644 --- a/src/Metadata/Map.php +++ b/src/Metadata/Map.php @@ -18,6 +18,8 @@ * @author Kevin Bond * * @internal + * + * @phpstan-import-type Value from Metadata */ final class Map { @@ -27,7 +29,7 @@ final class Map /** @var array */ public array $aliasToClassMap = []; - /** @var array> */ + /** @var array> */ public array $metadataMap = []; /** @var array */ diff --git a/tests/Fixture/Classes/Sub/Class5.php b/tests/Fixture/Classes/Sub/Class5.php index e164551..eb7aca1 100644 --- a/tests/Fixture/Classes/Sub/Class5.php +++ b/tests/Fixture/Classes/Sub/Class5.php @@ -16,6 +16,8 @@ #[Alias('class5')] #[Metadata('key1', 'class5-value1')] +#[Metadata('key2', ['a','b'])] + final class Class5 { } diff --git a/tests/Unit/MetadataTest.php b/tests/Unit/MetadataTest.php index ee58b3d..317f29d 100644 --- a/tests/Unit/MetadataTest.php +++ b/tests/Unit/MetadataTest.php @@ -40,7 +40,7 @@ public function metadata_generated_for_path(): void $this->assertSame(['key1' => 'class2-value1', 'key2' => 2], Metadata::for(new Class2())); $this->assertSame(['key1' => 'class2-value1', 'key2' => 2], Metadata::for('class2')); $this->assertSame(['key1' => 'class4-value1'], Metadata::for(Class4::class)); - $this->assertSame(['key1' => 'class5-value1'], Metadata::for(Class5::class)); + $this->assertSame(['key1' => 'class5-value1', 'key2' => ['a','b']], Metadata::for(Class5::class)); $this->assertNull(Metadata::get(Class1::class, 'key1')); $this->assertNull(Metadata::get(new Class1(), 'key1')); @@ -65,6 +65,8 @@ public function metadata_generated_for_path(): void $this->assertNull(Metadata::first(new Class2(), 'invalid', 'foo')); $this->assertNull(Metadata::first('class2', 'invalid', 'foo')); + $this->assertSame(['a','b'], Metadata::get(new Class5(), 'key2')); + $this->assertSame([], Metadata::classesWith('foo')); $this->assertSame([Class2::class, Class4::class, Class5::class], Metadata::classesWith('key1')); } @@ -86,7 +88,7 @@ public function metadata_generated_for_path_and_mapping_config(): void $this->assertSame(['key1' => 'override-value', 'key2' => 2, 'key3' => 3], Metadata::for(new Class2())); $this->assertSame(['key1' => 'override-value', 'key2' => 2, 'key3' => 3], Metadata::for('class2')); $this->assertSame(['key1' => 'class4-value1'], Metadata::for(Class4::class)); - $this->assertSame(['key1' => 'class5-value1'], Metadata::for(Class5::class)); + $this->assertSame(['key1' => 'class5-value1', 'key2' => ['a','b']], Metadata::for(Class5::class)); $this->assertSame([], Metadata::classesWith('foo')); $this->assertSame([Class2::class, Class4::class, Class5::class, Class1::class], Metadata::classesWith('key1'));