Skip to content

Commit aab3973

Browse files
Merge pull request #13
[5.x] Adds more Attr helpers.
2 parents 5232e64 + f2e475c commit aab3973

File tree

2 files changed

+144
-2
lines changed

2 files changed

+144
-2
lines changed

src/Attr.php

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function __construct(mixed $target)
6868
}
6969
} else {
7070
throw new InvalidArgumentException(
71-
'The target must be a class, object, callable, or class-property array.'
71+
'The target must be a class, object, callable, or class-property array.',
7272
);
7373
}
7474
}
@@ -102,7 +102,7 @@ public function all(?string $attribute = null): Collection
102102
}
103103

104104
/**
105-
* Retrieves the first instanced attribute value from a class, method, or property.
105+
* Retrieves the first instanced attribute value from a target.
106106
*
107107
* @template TAttribute of object
108108
*
@@ -114,6 +114,62 @@ public function first(?string $attribute = null): ?object
114114
return $this->collect($attribute)->first()?->newInstance();
115115
}
116116

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

tests/AttrTest.php

Lines changed: 86 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,25 @@ 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+
}
160246
}
161247

162248
#[TestAttribute('function')]

0 commit comments

Comments
 (0)