Skip to content

Commit bdac073

Browse files
#[\Attribute]
1 parent dce08e3 commit bdac073

File tree

4 files changed

+267
-59
lines changed

4 files changed

+267
-59
lines changed

Zend/tests/attributes/delayed_target_validation/errors_from_validator.phpt renamed to Zend/tests/attributes/delayed_target_validation/validator_AllowDynamicProperties.phpt

Lines changed: 1 addition & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
#[\DelayedTargetValidation] affects errors from validators
2+
#[\DelayedTargetValidation] with #[\AllowDynamicProperties]: validator errors delayed
33
--FILE--
44
<?php
55

@@ -19,24 +19,11 @@ readonly class DemoReadonly {}
1919
#[AllowDynamicProperties]
2020
enum DemoEnum {}
2121

22-
class DemoClass {
23-
public string $hooked {
24-
#[DelayedTargetValidation]
25-
#[NoDiscard] // Does nothing here
26-
get => $this->hooked;
27-
#[DelayedTargetValidation]
28-
#[NoDiscard] // Does nothing here
29-
set => $value;
30-
}
31-
}
32-
3322
$cases = [
3423
new ReflectionClass('DemoTrait'),
3524
new ReflectionClass('DemoInterface'),
3625
new ReflectionClass('DemoReadonly'),
3726
new ReflectionClass('DemoEnum'),
38-
new ReflectionProperty('DemoClass', 'hooked')->getHook(PropertyHookType::Get),
39-
new ReflectionProperty('DemoClass', 'hooked')->getHook(PropertyHookType::Set),
4027
];
4128
foreach ($cases as $r) {
4229
echo str_repeat("*", 20) . "\n";
@@ -191,48 +178,3 @@ array(2) {
191178
}
192179
}
193180
Error: Cannot apply #[\AllowDynamicProperties] to enum DemoEnum
194-
********************
195-
Method [ <user> public method $hooked::get ] {
196-
@@ %s %d - %d
197-
198-
- Parameters [0] {
199-
}
200-
- Return [ string ]
201-
}
202-
203-
array(2) {
204-
[0]=>
205-
object(ReflectionAttribute)#%d (1) {
206-
["name"]=>
207-
string(23) "DelayedTargetValidation"
208-
}
209-
[1]=>
210-
object(ReflectionAttribute)#%d (1) {
211-
["name"]=>
212-
string(9) "NoDiscard"
213-
}
214-
}
215-
Error: #[\NoDiscard] is not supported for property hooks
216-
********************
217-
Method [ <user> public method $hooked::set ] {
218-
@@ %s %d - %d
219-
220-
- Parameters [1] {
221-
Parameter #0 [ <required> string $value ]
222-
}
223-
- Return [ void ]
224-
}
225-
226-
array(2) {
227-
[0]=>
228-
object(ReflectionAttribute)#%d (1) {
229-
["name"]=>
230-
string(23) "DelayedTargetValidation"
231-
}
232-
[1]=>
233-
object(ReflectionAttribute)#%d (1) {
234-
["name"]=>
235-
string(9) "NoDiscard"
236-
}
237-
}
238-
Error: #[\NoDiscard] is not supported for property hooks
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
--TEST--
2+
#[\DelayedTargetValidation] with #[\Attribute]: validator errors delayed
3+
--FILE--
4+
<?php
5+
6+
#[DelayedTargetValidation]
7+
#[Attribute]
8+
trait DemoTrait {}
9+
10+
#[DelayedTargetValidation]
11+
#[Attribute]
12+
interface DemoInterface {}
13+
14+
#[DelayedTargetValidation]
15+
#[Attribute]
16+
abstract class DemoAbstract {}
17+
18+
#[DelayedTargetValidation]
19+
#[Attribute]
20+
enum DemoEnum {}
21+
22+
$cases = [
23+
new ReflectionClass('DemoTrait'),
24+
new ReflectionClass('DemoInterface'),
25+
new ReflectionClass('DemoAbstract'),
26+
new ReflectionClass('DemoEnum'),
27+
];
28+
foreach ($cases as $r) {
29+
echo str_repeat("*", 20) . "\n";
30+
echo $r . "\n";
31+
$attributes = $r->getAttributes();
32+
var_dump($attributes);
33+
try {
34+
$attributes[1]->newInstance();
35+
} catch (Error $e) {
36+
echo get_class($e) . ": " . $e->getMessage() . "\n";
37+
}
38+
}
39+
40+
?>
41+
--EXPECTF--
42+
********************
43+
Trait [ <user> trait DemoTrait ] {
44+
@@ %s %d-%d
45+
46+
- Constants [0] {
47+
}
48+
49+
- Static properties [0] {
50+
}
51+
52+
- Static methods [0] {
53+
}
54+
55+
- Properties [0] {
56+
}
57+
58+
- Methods [0] {
59+
}
60+
}
61+
62+
array(2) {
63+
[0]=>
64+
object(ReflectionAttribute)#%d (1) {
65+
["name"]=>
66+
string(23) "DelayedTargetValidation"
67+
}
68+
[1]=>
69+
object(ReflectionAttribute)#%d (1) {
70+
["name"]=>
71+
string(9) "Attribute"
72+
}
73+
}
74+
Error: Cannot apply #[\Attribute] to trait DemoTrait
75+
********************
76+
Interface [ <user> interface DemoInterface ] {
77+
@@ %s %d-%d
78+
79+
- Constants [0] {
80+
}
81+
82+
- Static properties [0] {
83+
}
84+
85+
- Static methods [0] {
86+
}
87+
88+
- Properties [0] {
89+
}
90+
91+
- Methods [0] {
92+
}
93+
}
94+
95+
array(2) {
96+
[0]=>
97+
object(ReflectionAttribute)#%d (1) {
98+
["name"]=>
99+
string(23) "DelayedTargetValidation"
100+
}
101+
[1]=>
102+
object(ReflectionAttribute)#%d (1) {
103+
["name"]=>
104+
string(9) "Attribute"
105+
}
106+
}
107+
Error: Cannot apply #[\Attribute] to interface DemoInterface
108+
********************
109+
Class [ <user> abstract class DemoAbstract ] {
110+
@@ %s %d-%d
111+
112+
- Constants [0] {
113+
}
114+
115+
- Static properties [0] {
116+
}
117+
118+
- Static methods [0] {
119+
}
120+
121+
- Properties [0] {
122+
}
123+
124+
- Methods [0] {
125+
}
126+
}
127+
128+
array(2) {
129+
[0]=>
130+
object(ReflectionAttribute)#%d (1) {
131+
["name"]=>
132+
string(23) "DelayedTargetValidation"
133+
}
134+
[1]=>
135+
object(ReflectionAttribute)#%d (1) {
136+
["name"]=>
137+
string(9) "Attribute"
138+
}
139+
}
140+
Error: Cannot apply #[\Attribute] to abstract class DemoAbstract
141+
********************
142+
Enum [ <user> enum DemoEnum implements UnitEnum ] {
143+
@@ %s %d-%d
144+
145+
- Constants [0] {
146+
}
147+
148+
- Static properties [0] {
149+
}
150+
151+
- Static methods [1] {
152+
Method [ <internal, prototype UnitEnum> static public method cases ] {
153+
154+
- Parameters [0] {
155+
}
156+
- Return [ array ]
157+
}
158+
}
159+
160+
- Properties [1] {
161+
Property [ public protected(set) readonly string $name ]
162+
}
163+
164+
- Methods [0] {
165+
}
166+
}
167+
168+
array(2) {
169+
[0]=>
170+
object(ReflectionAttribute)#%d (1) {
171+
["name"]=>
172+
string(23) "DelayedTargetValidation"
173+
}
174+
[1]=>
175+
object(ReflectionAttribute)#%d (1) {
176+
["name"]=>
177+
string(9) "Attribute"
178+
}
179+
}
180+
Error: Cannot apply #[\Attribute] to enum DemoEnum
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
--TEST--
2+
#[\DelayedTargetValidation] with #[\NoDiscard]: validator errors delayed
3+
--FILE--
4+
<?php
5+
6+
class DemoClass {
7+
public string $hooked {
8+
#[DelayedTargetValidation]
9+
#[NoDiscard] // Does nothing here
10+
get => $this->hooked;
11+
#[DelayedTargetValidation]
12+
#[NoDiscard] // Does nothing here
13+
set => $value;
14+
}
15+
}
16+
17+
$cases = [
18+
new ReflectionProperty('DemoClass', 'hooked')->getHook(PropertyHookType::Get),
19+
new ReflectionProperty('DemoClass', 'hooked')->getHook(PropertyHookType::Set),
20+
];
21+
foreach ($cases as $r) {
22+
echo str_repeat("*", 20) . "\n";
23+
echo $r . "\n";
24+
$attributes = $r->getAttributes();
25+
var_dump($attributes);
26+
try {
27+
$attributes[1]->newInstance();
28+
} catch (Error $e) {
29+
echo get_class($e) . ": " . $e->getMessage() . "\n";
30+
}
31+
}
32+
33+
?>
34+
--EXPECTF--
35+
********************
36+
Method [ <user> public method $hooked::get ] {
37+
@@ %s %d - %d
38+
39+
- Parameters [0] {
40+
}
41+
- Return [ string ]
42+
}
43+
44+
array(2) {
45+
[0]=>
46+
object(ReflectionAttribute)#%d (1) {
47+
["name"]=>
48+
string(23) "DelayedTargetValidation"
49+
}
50+
[1]=>
51+
object(ReflectionAttribute)#%d (1) {
52+
["name"]=>
53+
string(9) "NoDiscard"
54+
}
55+
}
56+
Error: #[\NoDiscard] is not supported for property hooks
57+
********************
58+
Method [ <user> public method $hooked::set ] {
59+
@@ %s %d - %d
60+
61+
- Parameters [1] {
62+
Parameter #0 [ <required> string $value ]
63+
}
64+
- Return [ void ]
65+
}
66+
67+
array(2) {
68+
[0]=>
69+
object(ReflectionAttribute)#%d (1) {
70+
["name"]=>
71+
string(23) "DelayedTargetValidation"
72+
}
73+
[1]=>
74+
object(ReflectionAttribute)#%d (1) {
75+
["name"]=>
76+
string(9) "NoDiscard"
77+
}
78+
}
79+
Error: #[\NoDiscard] is not supported for property hooks

Zend/zend_attributes.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,13 @@ static void validate_attribute(
125125
msg = "Cannot apply #[\\Attribute] to abstract class %s";
126126
}
127127
if (msg != NULL) {
128+
if (target & ZEND_ATTRIBUTE_NO_TARGET_VALIDATION) {
129+
return;
130+
}
131+
if (target & ZEND_ATTRIBUTE_DELAYED_TARGET_VALIDATION) {
132+
zend_throw_error(NULL, msg, ZSTR_VAL(scope->name));
133+
return;
134+
}
128135
zend_error_noreturn(E_ERROR, msg, ZSTR_VAL(scope->name));
129136
}
130137
}

0 commit comments

Comments
 (0)