Skip to content

Commit 2875a23

Browse files
committed
Convert getAttributes() to return list of ReflectionAttribute and adjust tests.
1 parent 6d49c93 commit 2875a23

File tree

6 files changed

+125
-56
lines changed

6 files changed

+125
-56
lines changed

Zend/tests/attributes_001.phpt

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,28 @@
22
Basic attributes usage
33
--FILE--
44
<?php
5+
function dump_attributes($attributes) {
6+
$arr = [];
7+
foreach ($attributes as $attribute) {
8+
if (!isset($arr[$attribute->getName()])) {
9+
$arr[$attribute->getName()] = [];
10+
}
11+
$arr[$attribute->getName()][] = $attribute->getArguments();
12+
}
13+
var_dump($arr);
14+
}
515
// No attributes
616
function f0() {
717
}
818
$r = new ReflectionFunction("f0");
9-
var_dump($r->getAttributes());
19+
dump_attributes($r->getAttributes());
1020

1121
// Function attributes
1222
<<TestFunction>>
1323
function foo() {
1424
}
1525
$r = new ReflectionFunction("foo");
16-
var_dump($r->getAttributes());
26+
dump_attributes($r->getAttributes());
1727

1828
// Class attributes
1929
<<TestClass>>
@@ -25,30 +35,30 @@ class Bar {
2535

2636
}
2737
$r = new ReflectionClass("Bar");
28-
var_dump($r->getAttributes());
38+
dump_attributes($r->getAttributes());
2939
$r1 = $r->getReflectionConstant("C");
30-
var_dump($r1->getAttributes());
40+
dump_attributes($r1->getAttributes());
3141
$r2 = $r->getProperty("x");
32-
var_dump($r2->getAttributes());
42+
dump_attributes($r2->getAttributes());
3343

3444
// Multiple attributes with multiple values
3545
<<a1,a2(1),a3(1,2)>>
3646
function f1() {}
3747
$r = new ReflectionFunction("f1");
38-
var_dump($r->getAttributes());
48+
dump_attributes($r->getAttributes());
3949

4050
// Attributes with AST
4151
<<a1,a2(1+1),a3(1+3,2+2),a4(["a"=>1,"b"=>2])>>
4252
function f2() {}
4353
$r = new ReflectionFunction("f2");
44-
var_dump($r->getAttributes());
54+
dump_attributes($r->getAttributes());
4555

4656
// Attributes with namespaces
4757
<<Foo\Bar>>
4858
function f4() {
4959
}
5060
$r = new ReflectionFunction("f4");
51-
var_dump($r->getAttributes());
61+
dump_attributes($r->getAttributes());
5262
?>
5363
--EXPECT--
5464
array(0) {

Zend/tests/attributes_002.phpt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ namespace Doctrine\ORM {
1414
function GetClassAttributes($class_name) {
1515
$reflClass = new \ReflectionClass($class_name);
1616
$attrs = $reflClass->getAttributes();
17-
foreach ($attrs as $name => $values) {
18-
$attrs[$name] = new $name($values[0][0]);
17+
$values = [];
18+
foreach ($attrs as $attribute) {
19+
$class = $attribute->getName();
20+
$values[$attribute->getName()] = new $class(...$attribute->getArguments());
1921
}
20-
return $attrs;
22+
return $values;
2123
}
2224
}
2325

@@ -46,9 +48,11 @@ namespace {
4648
?>
4749
--EXPECT--
4850
array(1) {
49-
["ORM\Entity"]=>
50-
object(Doctrine\ORM\Entity)#2 (1) {
51-
["name":"Doctrine\ORM\Entity":private]=>
51+
["Doctrine\ORM\Mapping\Entity"]=>
52+
object(Doctrine\ORM\Mapping\Entity)#3 (2) {
53+
["tableName"]=>
5254
string(4) "user"
55+
["repository"]=>
56+
string(14) "UserRepository"
5357
}
5458
}

Zend/tests/attributes_003.phpt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
Resolve attribute names
33
--FILE--
44
<?php
5+
function dump_attributes($attributes) {
6+
$arr = [];
7+
foreach ($attributes as $attribute) {
8+
if (!isset($arr[$attribute->getName()])) {
9+
$arr[$attribute->getName()] = [];
10+
}
11+
$arr[$attribute->getName()][] = $attribute->getArguments();
12+
}
13+
var_dump($arr);
14+
}
515

616
namespace Doctrine\ORM\Mapping {
717
class Entity {
@@ -17,7 +27,7 @@ namespace Foo {
1727
}
1828

1929
namespace {
20-
var_dump((new ReflectionFunction('Foo\foo'))->getAttributes());
30+
dump_attributes((new ReflectionFunction('Foo\foo'))->getAttributes());
2131
}
2232
--EXPECTF--
2333
array(1) {

Zend/zend_ast.c

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,34 +2140,28 @@ ZEND_API void zend_ast_convert_to_object(zval *p, zend_ast *ast, zend_class_entr
21402140
}
21412141
}
21422142

2143-
ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes, zend_class_entry *ce)
2143+
ZEND_API zval *zend_ast_convert_attributes(HashTable *attributes, zend_class_entry *ce)
21442144
{
21452145
zval *val, tmp;
2146-
HashTable *ht, *ht2, *res_ht;
2147-
zend_string *key;
2148-
int convert_ast = 0;
2146+
HashTable *ht, *ht2;
2147+
zval *res = emalloc(sizeof(zval));
2148+
2149+
array_init(res);
21492150

21502151
ZEND_HASH_FOREACH_VAL(attributes, val) {
21512152
if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
2152-
convert_ast = 1;
2153+
zend_ast_convert_to_object(&tmp, Z_ASTVAL_P(val), ce);
2154+
zend_hash_next_index_insert(Z_ARRVAL_P(res), &tmp);
21532155
break;
2154-
} else if (Z_TYPE_P(val) == IS_ARRAY) {
2155-
ht = Z_ARR_P(val);
2156-
ZEND_HASH_FOREACH_VAL(ht, val) {
2157-
if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
2158-
convert_ast = 1;
2159-
break;
2160-
}
2161-
} ZEND_HASH_FOREACH_END();
2162-
if (convert_ast) {
2163-
break;
2156+
} else {
2157+
if (Z_REFCOUNTED_P(val)) {
2158+
Z_ADDREF_P(val);
21642159
}
2160+
zend_hash_next_index_insert(Z_ARRVAL_P(res), val);
21652161
}
21662162
} ZEND_HASH_FOREACH_END();
21672163

2168-
if (convert_ast) {
2169-
array_init_size(ret, zend_hash_num_elements(attributes));
2170-
res_ht = Z_ARR_P(ret);
2164+
/* if (convert_ast) {
21712165
ZEND_HASH_FOREACH_STR_KEY_VAL(attributes, key, val) {
21722166
if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
21732167
zend_ast_convert_to_object(&tmp, Z_ASTVAL_P(val), ce);
@@ -2201,15 +2195,16 @@ ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes, zend
22012195
GC_ADDREF(attributes);
22022196
ZVAL_ARR(ret, attributes);
22032197
}
2198+
*/
2199+
2200+
return res;
22042201
}
22052202

22062203
void zend_ast_add_attribute(zend_ast *name, zend_ast *value) /* {{{ */
22072204
{
22082205
zval *val, tmp;
22092206
zend_string *key;
22102207

2211-
znode class_node;
2212-
22132208
zval *zv = zend_ast_get_zval(name);
22142209
key = Z_STR_P(zv);
22152210

@@ -2248,7 +2243,7 @@ void zend_ast_add_attribute(zend_ast *name, zend_ast *value) /* {{{ */
22482243

22492244
zend_ast *zend_ast_add_attribute_value(zend_ast *list_ast, zend_ast *val_ast) /* {{{ */
22502245
{
2251-
zval *list, *val, arr, tmp;
2246+
zval *list, *val, arr;
22522247

22532248
if (list_ast->kind == ZEND_AST_ZVAL) {
22542249
list = zend_ast_get_zval(list_ast);

Zend/zend_ast.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,4 +356,5 @@ static zend_always_inline zend_ast *zend_ast_list_rtrim(zend_ast *ast) {
356356

357357
void zend_ast_add_attribute(zend_ast *name, zend_ast *value);
358358
zend_ast *zend_ast_add_attribute_value(zend_ast *list_ast, zend_ast *val_ast);
359+
ZEND_API zval *zend_ast_convert_attributes(HashTable *attributes, zend_class_entry *ce);
359360
#endif

ext/reflection/php_reflection.c

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include "zend.h"
3333
#include "zend_API.h"
34+
#include "zend_ast.h"
3435
#include "zend_exceptions.h"
3536
#include "zend_operators.h"
3637
#include "zend_constants.h"
@@ -256,6 +257,9 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
256257
break;
257258
case REF_TYPE_ATTRIBUTE:
258259
attr_reference = (attribute_reference*)intern->ptr;
260+
if (attr_reference->arguments) {
261+
zval_ptr_dtor(attr_reference->arguments);
262+
}
259263
efree(attr_reference);
260264
break;
261265
case REF_TYPE_GENERATOR:
@@ -1036,6 +1040,45 @@ static void _extension_string(smart_str *str, zend_module_entry *module, char *i
10361040
}
10371041
/* }}} */
10381042

1043+
/* {{{ reflection_attribute_factory */
1044+
static void reflection_attribute_factory(zval *object, zend_string *name, zval *arguments)
1045+
{
1046+
reflection_object *intern;
1047+
attribute_reference *reference;
1048+
1049+
reflection_instantiate(reflection_attribute_ptr, object);
1050+
intern = Z_REFLECTION_P(object);
1051+
reference = (attribute_reference*) emalloc(sizeof(attribute_reference));
1052+
reference->name = name;
1053+
reference->arguments = arguments;
1054+
intern->ptr = reference;
1055+
intern->ref_type = REF_TYPE_ATTRIBUTE;
1056+
}
1057+
/* }}} */
1058+
1059+
1060+
static zval* convert_attributes(zval *ret, HashTable *attributes, zend_class_entry *ce)
1061+
{
1062+
zend_string *attribute_name;
1063+
zval *attrs, *attr, *object;
1064+
zval *converted_attributes;
1065+
1066+
array_init(ret);
1067+
1068+
ZEND_HASH_FOREACH_STR_KEY_VAL(attributes, attribute_name, attrs) {
1069+
if (attribute_name) {
1070+
1071+
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(attrs), attr) {
1072+
converted_attributes = zend_ast_convert_attributes(Z_ARRVAL_P(attr), ce);
1073+
1074+
reflection_attribute_factory(object, attribute_name, converted_attributes);
1075+
1076+
zend_hash_next_index_insert(Z_ARRVAL_P(ret), object);
1077+
} ZEND_HASH_FOREACH_END();
1078+
}
1079+
} ZEND_HASH_FOREACH_END();
1080+
}
1081+
10391082
static void _zend_extension_string(smart_str *str, zend_extension *extension, char *indent) /* {{{ */
10401083
{
10411084
smart_str_append_printf(str, "%sZend Extension [ %s ", indent, extension->name);
@@ -1191,22 +1234,6 @@ static void reflection_type_factory(zend_type type, zval *object, zend_bool lega
11911234
}
11921235
/* }}} */
11931236

1194-
/* {{{ reflection_attribute_factory */
1195-
static void reflection_attribute_factory(zval *object, zend_string *name, zval *arguments)
1196-
{
1197-
reflection_object *intern;
1198-
attribute_reference *reference;
1199-
1200-
reflection_instantiate(reflection_attribute_ptr, object);
1201-
intern = Z_REFLECTION_P(object);
1202-
reference = (attribute_reference*) emalloc(sizeof(attribute_reference));
1203-
reference->name = name;
1204-
reference->arguments = arguments;
1205-
intern->ptr = reference;
1206-
intern->ref_type = REF_TYPE_ATTRIBUTE;
1207-
}
1208-
/* }}} */
1209-
12101237
/* {{{ reflection_function_factory */
12111238
static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object)
12121239
{
@@ -1671,7 +1698,7 @@ ZEND_METHOD(reflection_function, getAttributes)
16711698
}
16721699
GET_REFLECTION_OBJECT_PTR(fptr);
16731700
if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.attributes) {
1674-
zend_ast_convert_attributes(return_value, fptr->op_array.attributes, NULL);
1701+
convert_attributes(return_value, fptr->op_array.attributes, NULL);
16751702
} else {
16761703
array_init(return_value);
16771704
}
@@ -3674,7 +3701,7 @@ ZEND_METHOD(reflection_class_constant, getAttributes)
36743701
}
36753702
GET_REFLECTION_OBJECT_PTR(ref);
36763703
if (ref->attributes) {
3677-
zend_ast_convert_attributes(return_value, ref->attributes, ref->ce);
3704+
convert_attributes(return_value, ref->attributes, ref->ce);
36783705
} else {
36793706
array_init(return_value);
36803707
}
@@ -4055,7 +4082,7 @@ ZEND_METHOD(reflection_class, getAttributes)
40554082
}
40564083
GET_REFLECTION_OBJECT_PTR(ce);
40574084
if (ce->type == ZEND_USER_CLASS && ce->info.user.attributes) {
4058-
zend_ast_convert_attributes(return_value, ce->info.user.attributes, ce);
4085+
convert_attributes(return_value, ce->info.user.attributes, ce);
40594086
} else {
40604087
array_init(return_value);
40614088
}
@@ -5573,7 +5600,7 @@ ZEND_METHOD(reflection_property, getAttributes)
55735600
}
55745601
GET_REFLECTION_OBJECT_PTR(ref);
55755602
if (ref->prop->attributes) {
5576-
zend_ast_convert_attributes(return_value, ref->prop->attributes, ref->prop->ce);
5603+
convert_attributes(return_value, ref->prop->attributes, ref->prop->ce);
55775604
} else {
55785605
array_init(return_value);
55795606
}
@@ -6308,13 +6335,35 @@ ZEND_METHOD(reflection_reference, getId)
63086335
* Returns the name of the attribute */
63096336
ZEND_METHOD(reflection_attribute, getName)
63106337
{
6338+
reflection_object *intern;
6339+
attribute_reference *param;
6340+
6341+
if (zend_parse_parameters_none() == FAILURE) {
6342+
RETURN_THROWS();
6343+
}
6344+
GET_REFLECTION_OBJECT_PTR(param);
6345+
6346+
RETVAL_STR(param->name);
63116347
}
63126348
/* }}} */
63136349

63146350
/* {{{ proto public string ReflectionAttribute::getArguments()
63156351
* Returns the arguments passed to the attribute */
63166352
ZEND_METHOD(reflection_attribute, getArguments)
63176353
{
6354+
if (zend_parse_parameters_none() == FAILURE) {
6355+
RETURN_THROWS();
6356+
}
6357+
6358+
reflection_object *intern;
6359+
attribute_reference *param;
6360+
6361+
if (zend_parse_parameters_none() == FAILURE) {
6362+
RETURN_THROWS();
6363+
}
6364+
GET_REFLECTION_OBJECT_PTR(param);
6365+
6366+
ZVAL_COPY(return_value, param->arguments);
63186367
}
63196368
/* }}} */
63206369

0 commit comments

Comments
 (0)