Skip to content

Commit 8ff566d

Browse files
[5.x] Adds more Attr helpers.
1 parent 5232e64 commit 8ff566d

2 files changed

Lines changed: 147 additions & 2 deletions

File tree

src/Attr.php

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Closure;
66
use Countable;
7+
use Illuminate\Support\Arr;
78
use Illuminate\Support\Collection;
89
use InvalidArgumentException;
910
use ReflectionAttribute;
@@ -13,6 +14,7 @@
1314
use ReflectionParameter;
1415
use ReflectionProperty;
1516

17+
use function array_values;
1618
use function class_exists;
1719
use function function_exists;
1820
use function is_array;
@@ -68,7 +70,7 @@ public function __construct(mixed $target)
6870
}
6971
} else {
7072
throw new InvalidArgumentException(
71-
'The target must be a class, object, callable, or class-property array.'
73+
'The target must be a class, object, callable, or class-property array.',
7274
);
7375
}
7476
}
@@ -102,7 +104,7 @@ public function all(?string $attribute = null): Collection
102104
}
103105

104106
/**
105-
* Retrieves the first instanced attribute value from a class, method, or property.
107+
* Retrieves the first instanced attribute value from a target.
106108
*
107109
* @template TAttribute of object
108110
*
@@ -114,6 +116,62 @@ public function first(?string $attribute = null): ?object
114116
return $this->collect($attribute)->first()?->newInstance();
115117
}
116118

119+
/**
120+
* Retrieves all the arguments declared for the first given attribute.
121+
*
122+
* @param class-string $attribute
123+
* @return scalar[]|null
124+
*/
125+
public function arguments(string $attribute): ?array
126+
{
127+
return $this->collect($attribute)->first()?->getArguments();
128+
}
129+
130+
/**
131+
* Retrieves a Collection of all the arguments for the all declarations of the given attribute.
132+
*
133+
* @param class-string $attribute
134+
* @return array<scalar[]>|null
135+
*/
136+
public function allArguments(string $attribute): ?array
137+
{
138+
return $this->collect($attribute)->map(static function (ReflectionAttribute $attribute): array {
139+
return $attribute->getArguments();
140+
})->toArray();
141+
}
142+
143+
/**
144+
* Check if the target has no attributes set.
145+
*/
146+
public function isEmpty(): bool
147+
{
148+
return $this->collect(null)->isEmpty();
149+
}
150+
151+
/**
152+
* Check if the target has any attribute set.
153+
*/
154+
public function isNotEmpty(): bool
155+
{
156+
return !$this->isEmpty();
157+
}
158+
159+
/**
160+
* Check if the target has the given attribute.
161+
*/
162+
public function has(string $attribute): bool
163+
{
164+
return $this->collect($attribute)->isNotEmpty();
165+
}
166+
167+
/**
168+
* Check if the target does not have the given attribute.
169+
*/
170+
public function missing(string $attribute): bool
171+
{
172+
return !$this->has($attribute);
173+
}
174+
117175
/**
118176
* Executes a method from the first instanced attribute.
119177
*

tests/AttrTest.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,17 @@
66
use Error;
77
use InvalidArgumentException;
88
use Laragear\Meta\Attr;
9+
use ReflectionClass;
910

1011
class AttrTest extends TestCase
1112
{
13+
public function test_resolves_from_reflection(): void
14+
{
15+
$attr = Attr::of(new ReflectionClass(StubClass::class));
16+
17+
static::assertNotEmpty($attr);
18+
}
19+
1220
public function test_resolves_from_class_string(): void
1321
{
1422
$attr = Attr::of(StubClass::class);
@@ -102,6 +110,52 @@ public function test_throws_error_if_attribute_class_does_not_exist(): void
102110
$attr->first('NonExistentAttribute');
103111
}
104112

113+
public function test_retrieves_arguments(): void
114+
{
115+
$attr = Attr::of(StubClass::class);
116+
117+
static::assertSame(['class'], $attr->arguments(TestAttribute::class));
118+
}
119+
120+
public function test_retrieves_all_arguments(): void
121+
{
122+
$attr = Attr::of(StubClass::class);
123+
124+
static::assertSame([['class']], $attr->allArguments(TestAttribute::class));
125+
}
126+
127+
public function test_emptiness(): void
128+
{
129+
$attr = Attr::of(StubClass::class);
130+
131+
static::assertFalse($attr->isEmpty());
132+
static::assertTrue($attr->isNotEmpty());
133+
}
134+
135+
public function test_test_not_emptiness(): void
136+
{
137+
$attr = Attr::of(StubClassWithoutAttributes::class);
138+
139+
static::assertTrue($attr->isEmpty());
140+
static::assertFalse($attr->isNotEmpty());
141+
}
142+
143+
public function test_has_given_attribute(): void
144+
{
145+
$attr = Attr::of(StubClass::class);
146+
147+
static::assertTrue($attr->has(TestAttribute::class));
148+
static::assertFalse($attr->has(StubClass::class));
149+
}
150+
151+
public function test_missing_given_attribute(): void
152+
{
153+
$attr = Attr::of(StubClass::class);
154+
155+
static::assertFalse($attr->missing(TestAttribute::class));
156+
static::assertTrue($attr->missing(StubClass::class));
157+
}
158+
105159
public function test_get_retrieves_property_from_attribute(): void
106160
{
107161
$attr = Attr::of(StubClass::class);
@@ -147,6 +201,19 @@ public function getValue(): string
147201
}
148202
}
149203

204+
#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
205+
class TestRepeatableAttribute
206+
{
207+
public function __construct(public string $value = 'default', public ?string $second = null)
208+
{
209+
}
210+
211+
public function getValue(): string
212+
{
213+
return $this->value;
214+
}
215+
}
216+
150217
#[TestAttribute('class')]
151218
class StubClass
152219
{
@@ -157,6 +224,26 @@ class StubClass
157224
public function stubMethod()
158225
{
159226
}
227+
228+
public function stubMethodWithoutAttributes()
229+
{
230+
}
231+
232+
#[TestRepeatableAttribute('first')]
233+
#[TestRepeatableAttribute(value: 'second')]
234+
#[TestRepeatableAttribute(second: 'test-argument', value: 'third')]
235+
public function stubMethodWithMultipleAttributes()
236+
{
237+
}
238+
}
239+
240+
class StubClassWithoutAttributes
241+
{
242+
#[TestAttribute('method')]
243+
public function stubMethod()
244+
{
245+
246+
}
160247
}
161248

162249
#[TestAttribute('function')]

0 commit comments

Comments
 (0)