Skip to content

Commit 5d06c35

Browse files
authored
Merge pull request #5 from koolkode/Attributes
Object and Filter Support
2 parents ffaacd3 + b6d392d commit 5d06c35

File tree

11 files changed

+511
-111
lines changed

11 files changed

+511
-111
lines changed
File renamed without changes.

Zend/tests/attributes/filter.phpt

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
--TEST--
2+
Attributes can be filtered by name and base type.
3+
--FILE--
4+
<?php
5+
6+
$ref = new \ReflectionFunction(<<A1>> <<A2>> function () { });
7+
$attr = $ref->getAttributes(A3::class);
8+
9+
var_dump(count($attr));
10+
11+
$ref = new \ReflectionFunction(<<A1>> <<A2>> function () { });
12+
$attr = $ref->getAttributes(A2::class);
13+
14+
var_dump(count($attr), $attr[0]->getName());
15+
16+
$ref = new \ReflectionFunction(<<A1>> <<A2>> <<A2>> function () { });
17+
$attr = $ref->getAttributes(A2::class);
18+
19+
var_dump(count($attr), $attr[0]->getName(), $attr[1]->getName());
20+
21+
echo "\n";
22+
23+
interface Base { }
24+
class A1 implements Base { }
25+
class A2 implements Base { }
26+
class A3 extends A2 { }
27+
28+
$ref = new \ReflectionFunction(<<A1>> <<A2>> <<A5>> function () { });
29+
$attr = $ref->getAttributes(\stdClass::class, \ReflectionAttribute::IS_INSTANCEOF);
30+
var_dump(count($attr));
31+
print_r(array_map(fn ($a) => $a->getName(), $attr));
32+
33+
$ref = new \ReflectionFunction(<<A1>> <<A2>> function () { });
34+
$attr = $ref->getAttributes(A1::class, \ReflectionAttribute::IS_INSTANCEOF);
35+
var_dump(count($attr));
36+
print_r(array_map(fn ($a) => $a->getName(), $attr));
37+
38+
$ref = new \ReflectionFunction(<<A1>> <<A2>> function () { });
39+
$attr = $ref->getAttributes(Base::class, \ReflectionAttribute::IS_INSTANCEOF);
40+
var_dump(count($attr));
41+
print_r(array_map(fn ($a) => $a->getName(), $attr));
42+
43+
$ref = new \ReflectionFunction(<<A1>> <<A2>> <<A3>> function () { });
44+
$attr = $ref->getAttributes(A2::class, \ReflectionAttribute::IS_INSTANCEOF);
45+
var_dump(count($attr));
46+
print_r(array_map(fn ($a) => $a->getName(), $attr));
47+
48+
$ref = new \ReflectionFunction(<<A1>> <<A2>> <<A3>> function () { });
49+
$attr = $ref->getAttributes(Base::class, \ReflectionAttribute::IS_INSTANCEOF);
50+
var_dump(count($attr));
51+
print_r(array_map(fn ($a) => $a->getName(), $attr));
52+
53+
echo "\n";
54+
55+
$ref = new \ReflectionFunction(function () { });
56+
57+
try {
58+
$ref->getAttributes(A1::class, 3);
59+
} catch (\Error $e) {
60+
var_dump('ERROR 1', $e->getMessage());
61+
}
62+
63+
$ref = new \ReflectionFunction(function () { });
64+
65+
try {
66+
$ref->getAttributes(SomeMissingClass::class, \ReflectionAttribute::IS_INSTANCEOF);
67+
} catch (\Error $e) {
68+
var_dump('ERROR 2', $e->getMessage());
69+
}
70+
71+
?>
72+
--EXPECT--
73+
int(0)
74+
int(1)
75+
string(2) "A2"
76+
int(2)
77+
string(2) "A2"
78+
string(2) "A2"
79+
80+
int(0)
81+
Array
82+
(
83+
)
84+
int(1)
85+
Array
86+
(
87+
[0] => A1
88+
)
89+
int(2)
90+
Array
91+
(
92+
[0] => A1
93+
[1] => A2
94+
)
95+
int(2)
96+
Array
97+
(
98+
[0] => A2
99+
[1] => A3
100+
)
101+
int(3)
102+
Array
103+
(
104+
[0] => A1
105+
[1] => A2
106+
[2] => A3
107+
)
108+
109+
string(7) "ERROR 1"
110+
string(39) "Invalid attribute filter flag specified"
111+
string(7) "ERROR 2"
112+
string(34) "Class 'SomeMissingClass' not found"

Zend/tests/attributes/objects.phpt

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
--TEST--
2+
Attributes can be converted into objects.
3+
--FILE--
4+
<?php
5+
6+
class A1
7+
{
8+
public string $name;
9+
public int $ttl;
10+
11+
public function __construct(string $name, int $ttl = 50)
12+
{
13+
$this->name = $name;
14+
$this->ttl = $ttl;
15+
}
16+
}
17+
18+
$ref = new \ReflectionFunction(<<A1('test')>> function () { });
19+
20+
foreach ($ref->getAttributes() as $attr) {
21+
$obj = $attr->getAsObject();
22+
23+
var_dump(get_class($obj), $obj->name, $obj->ttl);
24+
}
25+
26+
echo "\n";
27+
28+
$ref = new \ReflectionFunction(<<A1>> function () { });
29+
30+
try {
31+
$ref->getAttributes()[0]->getAsObject();
32+
} catch (\ArgumentCountError $e) {
33+
var_dump('ERROR 1', $e->getMessage());
34+
}
35+
36+
echo "\n";
37+
38+
$ref = new \ReflectionFunction(<<A1([])>> function () { });
39+
40+
try {
41+
$ref->getAttributes()[0]->getAsObject();
42+
} catch (\TypeError $e) {
43+
var_dump('ERROR 2', $e->getMessage());
44+
}
45+
46+
echo "\n";
47+
48+
$ref = new \ReflectionFunction(<<A2>> function () { });
49+
50+
try {
51+
$ref->getAttributes()[0]->getAsObject();
52+
} catch (\Error $e) {
53+
var_dump('ERROR 3', $e->getMessage());
54+
}
55+
56+
echo "\n";
57+
58+
class A3
59+
{
60+
private function __construct() { }
61+
}
62+
63+
$ref = new \ReflectionFunction(<<A3>> function () { });
64+
65+
try {
66+
$ref->getAttributes()[0]->getAsObject();
67+
} catch (\Error $e) {
68+
var_dump('ERROR 4', $e->getMessage());
69+
}
70+
71+
echo "\n";
72+
73+
class A4 { }
74+
75+
$ref = new \ReflectionFunction(<<A4(1)>> function () { });
76+
77+
try {
78+
$ref->getAttributes()[0]->getAsObject();
79+
} catch (\Error $e) {
80+
var_dump('ERROR 5', $e->getMessage());
81+
}
82+
83+
?>
84+
--EXPECT--
85+
string(2) "A1"
86+
string(4) "test"
87+
int(50)
88+
89+
string(7) "ERROR 1"
90+
string(81) "Too few arguments to function A1::__construct(), 0 passed and at least 1 expected"
91+
92+
string(7) "ERROR 2"
93+
string(74) "A1::__construct(): Argument #1 ($name) must be of type string, array given"
94+
95+
string(7) "ERROR 3"
96+
string(30) "Attribute class 'A2' not found"
97+
98+
string(7) "ERROR 4"
99+
string(50) "Attribute constructor of class 'A3' must be public"
100+
101+
string(7) "ERROR 5"
102+
string(71) "Attribute class 'A4' does not have a constructor, cannot pass arguments"
File renamed without changes.

Zend/zend_compile.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5729,19 +5729,14 @@ static void zend_compile_attribute(zval *v, zend_ast *ast) /* {{{ */
57295729
if (ast->child[1]) {
57305730
zend_ast_list *list;
57315731
uint32_t i;
5732-
57335732
zval tmp;
5734-
zval *x;
57355733

57365734
ZEND_ASSERT(ast->child[1]->kind == ZEND_AST_ARG_LIST);
57375735

57385736
ZVAL_NULL(&tmp);
57395737

57405738
for (list = zend_ast_get_list(ast->child[1]), i = 0; i < list->children; i++) {
5741-
zend_ast *el = list->child[i];
5742-
5743-
x = zend_hash_next_index_insert(Z_ARRVAL_P(v), &tmp);
5744-
zend_const_expr_to_zval(x, el);
5739+
zend_const_expr_to_zval(zend_hash_next_index_insert(Z_ARRVAL_P(v), &tmp), list->child[i]);
57455740
}
57465741
}
57475742
}
@@ -5782,14 +5777,13 @@ static HashTable *zend_compile_attributes(zend_ast *ast) /* {{{ */
57825777
add_next_index_zval(x, &a);
57835778
} else {
57845779
zval array;
5785-
zval ref;
57865780

57875781
ZEND_ASSERT(Z_TYPE_P(zend_hash_index_find(Z_ARRVAL_P(x), 0)) == IS_STRING);
57885782

5789-
ZVAL_COPY(&ref, x);
5783+
Z_ADDREF_P(x);
57905784

57915785
array_init(&array);
5792-
add_next_index_zval(&array, &ref);
5786+
add_next_index_zval(&array, x);
57935787
add_next_index_zval(&array, &a);
57945788
zend_hash_update(attr, name, &array);
57955789
}

0 commit comments

Comments
 (0)