From 8ff566d345db623b83f16811d41322add0a29eea Mon Sep 17 00:00:00 2001 From: Italo Israel Baeza Cabrera Date: Tue, 17 Mar 2026 22:07:01 -0300 Subject: [PATCH 1/2] [5.x] Adds more Attr helpers. --- src/Attr.php | 62 +++++++++++++++++++++++++++++++-- tests/AttrTest.php | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 2 deletions(-) diff --git a/src/Attr.php b/src/Attr.php index c4e62ed..8fb5141 100644 --- a/src/Attr.php +++ b/src/Attr.php @@ -4,6 +4,7 @@ use Closure; use Countable; +use Illuminate\Support\Arr; use Illuminate\Support\Collection; use InvalidArgumentException; use ReflectionAttribute; @@ -13,6 +14,7 @@ use ReflectionParameter; use ReflectionProperty; +use function array_values; use function class_exists; use function function_exists; use function is_array; @@ -68,7 +70,7 @@ public function __construct(mixed $target) } } else { throw new InvalidArgumentException( - 'The target must be a class, object, callable, or class-property array.' + 'The target must be a class, object, callable, or class-property array.', ); } } @@ -102,7 +104,7 @@ public function all(?string $attribute = null): Collection } /** - * Retrieves the first instanced attribute value from a class, method, or property. + * Retrieves the first instanced attribute value from a target. * * @template TAttribute of object * @@ -114,6 +116,62 @@ public function first(?string $attribute = null): ?object return $this->collect($attribute)->first()?->newInstance(); } + /** + * Retrieves all the arguments declared for the first given attribute. + * + * @param class-string $attribute + * @return scalar[]|null + */ + public function arguments(string $attribute): ?array + { + return $this->collect($attribute)->first()?->getArguments(); + } + + /** + * Retrieves a Collection of all the arguments for the all declarations of the given attribute. + * + * @param class-string $attribute + * @return array|null + */ + public function allArguments(string $attribute): ?array + { + return $this->collect($attribute)->map(static function (ReflectionAttribute $attribute): array { + return $attribute->getArguments(); + })->toArray(); + } + + /** + * Check if the target has no attributes set. + */ + public function isEmpty(): bool + { + return $this->collect(null)->isEmpty(); + } + + /** + * Check if the target has any attribute set. + */ + public function isNotEmpty(): bool + { + return !$this->isEmpty(); + } + + /** + * Check if the target has the given attribute. + */ + public function has(string $attribute): bool + { + return $this->collect($attribute)->isNotEmpty(); + } + + /** + * Check if the target does not have the given attribute. + */ + public function missing(string $attribute): bool + { + return !$this->has($attribute); + } + /** * Executes a method from the first instanced attribute. * diff --git a/tests/AttrTest.php b/tests/AttrTest.php index cbbc67e..651f351 100644 --- a/tests/AttrTest.php +++ b/tests/AttrTest.php @@ -6,9 +6,17 @@ use Error; use InvalidArgumentException; use Laragear\Meta\Attr; +use ReflectionClass; class AttrTest extends TestCase { + public function test_resolves_from_reflection(): void + { + $attr = Attr::of(new ReflectionClass(StubClass::class)); + + static::assertNotEmpty($attr); + } + public function test_resolves_from_class_string(): void { $attr = Attr::of(StubClass::class); @@ -102,6 +110,52 @@ public function test_throws_error_if_attribute_class_does_not_exist(): void $attr->first('NonExistentAttribute'); } + public function test_retrieves_arguments(): void + { + $attr = Attr::of(StubClass::class); + + static::assertSame(['class'], $attr->arguments(TestAttribute::class)); + } + + public function test_retrieves_all_arguments(): void + { + $attr = Attr::of(StubClass::class); + + static::assertSame([['class']], $attr->allArguments(TestAttribute::class)); + } + + public function test_emptiness(): void + { + $attr = Attr::of(StubClass::class); + + static::assertFalse($attr->isEmpty()); + static::assertTrue($attr->isNotEmpty()); + } + + public function test_test_not_emptiness(): void + { + $attr = Attr::of(StubClassWithoutAttributes::class); + + static::assertTrue($attr->isEmpty()); + static::assertFalse($attr->isNotEmpty()); + } + + public function test_has_given_attribute(): void + { + $attr = Attr::of(StubClass::class); + + static::assertTrue($attr->has(TestAttribute::class)); + static::assertFalse($attr->has(StubClass::class)); + } + + public function test_missing_given_attribute(): void + { + $attr = Attr::of(StubClass::class); + + static::assertFalse($attr->missing(TestAttribute::class)); + static::assertTrue($attr->missing(StubClass::class)); + } + public function test_get_retrieves_property_from_attribute(): void { $attr = Attr::of(StubClass::class); @@ -147,6 +201,19 @@ public function getValue(): string } } +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +class TestRepeatableAttribute +{ + public function __construct(public string $value = 'default', public ?string $second = null) + { + } + + public function getValue(): string + { + return $this->value; + } +} + #[TestAttribute('class')] class StubClass { @@ -157,6 +224,26 @@ class StubClass public function stubMethod() { } + + public function stubMethodWithoutAttributes() + { + } + + #[TestRepeatableAttribute('first')] + #[TestRepeatableAttribute(value: 'second')] + #[TestRepeatableAttribute(second: 'test-argument', value: 'third')] + public function stubMethodWithMultipleAttributes() + { + } +} + +class StubClassWithoutAttributes +{ + #[TestAttribute('method')] + public function stubMethod() + { + + } } #[TestAttribute('function')] From f2e475c42203ddb4a7069c4a45e70b17a2681521 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Wed, 18 Mar 2026 01:07:14 +0000 Subject: [PATCH 2/2] Apply fixes from StyleCI --- src/Attr.php | 6 ++---- tests/AttrTest.php | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Attr.php b/src/Attr.php index 8fb5141..bc8ec80 100644 --- a/src/Attr.php +++ b/src/Attr.php @@ -4,7 +4,6 @@ use Closure; use Countable; -use Illuminate\Support\Arr; use Illuminate\Support\Collection; use InvalidArgumentException; use ReflectionAttribute; @@ -14,7 +13,6 @@ use ReflectionParameter; use ReflectionProperty; -use function array_values; use function class_exists; use function function_exists; use function is_array; @@ -153,7 +151,7 @@ public function isEmpty(): bool */ public function isNotEmpty(): bool { - return !$this->isEmpty(); + return ! $this->isEmpty(); } /** @@ -169,7 +167,7 @@ public function has(string $attribute): bool */ public function missing(string $attribute): bool { - return !$this->has($attribute); + return ! $this->has($attribute); } /** diff --git a/tests/AttrTest.php b/tests/AttrTest.php index 651f351..81c1ecd 100644 --- a/tests/AttrTest.php +++ b/tests/AttrTest.php @@ -242,7 +242,6 @@ class StubClassWithoutAttributes #[TestAttribute('method')] public function stubMethod() { - } }