Skip to content

Commit 3d9c603

Browse files
committed
Bugfix 80097: Have ReflectionAttribute implement Reflector and __toString
1 parent 0d6358f commit 3d9c603

File tree

4 files changed

+90
-4
lines changed

4 files changed

+90
-4
lines changed

ext/reflection/php_reflection.c

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6397,6 +6397,59 @@ ZEND_METHOD(ReflectionAttribute, __clone)
63976397
_DO_THROW("Cannot clone object using __clone()");
63986398
}
63996399

6400+
/* {{{ Returns a string representation */
6401+
ZEND_METHOD(ReflectionAttribute, __toString)
6402+
{
6403+
reflection_object *intern;
6404+
attribute_reference *attr;
6405+
smart_str str = {0};
6406+
zval tmp;
6407+
int i;
6408+
6409+
if (zend_parse_parameters_none() == FAILURE) {
6410+
RETURN_THROWS();
6411+
}
6412+
6413+
GET_REFLECTION_OBJECT_PTR(attr);
6414+
6415+
smart_str_append_printf(&str, "Attribute [ ");
6416+
smart_str_append_printf(&str, "%s", ZSTR_VAL(attr->data->name));
6417+
smart_str_append_printf(&str, " ]");
6418+
6419+
if (attr->data->argc > 0) {
6420+
smart_str_append_printf(&str, " {\n");
6421+
smart_str_append_printf(&str, " - Arguments [%d] {\n", attr->data->argc);
6422+
6423+
for (i = 0; i < attr->data->argc; i++) {
6424+
if (FAILURE == zend_get_attribute_value(&tmp, attr->data, i, attr->scope)) {
6425+
RETURN_THROWS();
6426+
}
6427+
6428+
if (attr->data->args[i].name != NULL) {
6429+
smart_str_append_printf(&str, " Argument #%d [ %s = ", i, ZSTR_VAL(attr->data->args[i].name));
6430+
} else {
6431+
smart_str_append_printf(&str, " Argument #%d [ ", i);
6432+
}
6433+
6434+
if (format_default_value(&str, &tmp, NULL) == FAILURE) {
6435+
return;
6436+
}
6437+
6438+
smart_str_append_printf(&str, " ]\n");
6439+
6440+
zval_ptr_dtor(&tmp);
6441+
}
6442+
smart_str_append_printf(&str, " }\n");
6443+
6444+
smart_str_append_printf(&str, "}\n");
6445+
} else {
6446+
smart_str_append_printf(&str, "\n");
6447+
}
6448+
6449+
RETURN_STR(smart_str_extract(&str));
6450+
}
6451+
/* }}} */
6452+
64006453
/* {{{ * Returns the name of the attribute */
64016454
ZEND_METHOD(ReflectionAttribute, getName)
64026455
{
@@ -7062,7 +7115,7 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
70627115
reflection_reference_ptr = register_class_ReflectionReference();
70637116
reflection_init_class_handlers(reflection_reference_ptr);
70647117

7065-
reflection_attribute_ptr = register_class_ReflectionAttribute();
7118+
reflection_attribute_ptr = register_class_ReflectionAttribute(reflector_ptr);
70667119
reflection_init_class_handlers(reflection_attribute_ptr);
70677120

70687121
reflection_enum_ptr = register_class_ReflectionEnum(reflection_class_ptr);

ext/reflection/php_reflection.stub.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,14 +680,16 @@ private function __clone(): void {}
680680
private function __construct() {}
681681
}
682682

683-
final class ReflectionAttribute
683+
final class ReflectionAttribute implements Reflector
684684
{
685685
public function getName(): string {}
686686
public function getTarget(): int {}
687687
public function isRepeated(): bool {}
688688
public function getArguments(): array {}
689689
public function newInstance(): object {}
690690

691+
public function __toString(): string {}
692+
691693
private function __clone(): void {}
692694

693695
private function __construct() {}

ext/reflection/php_reflection_arginfo.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: b7cb399903fb1965ba6294c4dcf9364539e93b5b */
2+
* Stub hash: 3a424463071c9252fd0b6551d8b6e794f139f8f7 */
33

44
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0)
55
ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0)
@@ -539,6 +539,8 @@ ZEND_END_ARG_INFO()
539539
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionAttribute_newInstance, 0, 0, IS_OBJECT, 0)
540540
ZEND_END_ARG_INFO()
541541

542+
#define arginfo_class_ReflectionAttribute___toString arginfo_class_ReflectionFunction___toString
543+
542544
#define arginfo_class_ReflectionAttribute___clone arginfo_class_ReflectionFunctionAbstract___clone
543545

544546
#define arginfo_class_ReflectionAttribute___construct arginfo_class_ReflectionReference___construct
@@ -794,6 +796,7 @@ ZEND_METHOD(ReflectionAttribute, getTarget);
794796
ZEND_METHOD(ReflectionAttribute, isRepeated);
795797
ZEND_METHOD(ReflectionAttribute, getArguments);
796798
ZEND_METHOD(ReflectionAttribute, newInstance);
799+
ZEND_METHOD(ReflectionAttribute, __toString);
797800
ZEND_METHOD(ReflectionAttribute, __clone);
798801
ZEND_METHOD(ReflectionAttribute, __construct);
799802
ZEND_METHOD(ReflectionEnum, __construct);
@@ -1117,6 +1120,7 @@ static const zend_function_entry class_ReflectionAttribute_methods[] = {
11171120
ZEND_ME(ReflectionAttribute, isRepeated, arginfo_class_ReflectionAttribute_isRepeated, ZEND_ACC_PUBLIC)
11181121
ZEND_ME(ReflectionAttribute, getArguments, arginfo_class_ReflectionAttribute_getArguments, ZEND_ACC_PUBLIC)
11191122
ZEND_ME(ReflectionAttribute, newInstance, arginfo_class_ReflectionAttribute_newInstance, ZEND_ACC_PUBLIC)
1123+
ZEND_ME(ReflectionAttribute, __toString, arginfo_class_ReflectionAttribute___toString, ZEND_ACC_PUBLIC)
11201124
ZEND_ME(ReflectionAttribute, __clone, arginfo_class_ReflectionAttribute___clone, ZEND_ACC_PRIVATE)
11211125
ZEND_ME(ReflectionAttribute, __construct, arginfo_class_ReflectionAttribute___construct, ZEND_ACC_PRIVATE)
11221126
ZEND_FE_END
@@ -1412,13 +1416,14 @@ static zend_class_entry *register_class_ReflectionReference(void)
14121416
return class_entry;
14131417
}
14141418

1415-
static zend_class_entry *register_class_ReflectionAttribute(void)
1419+
static zend_class_entry *register_class_ReflectionAttribute(zend_class_entry *class_entry_Reflector)
14161420
{
14171421
zend_class_entry ce, *class_entry;
14181422

14191423
INIT_CLASS_ENTRY(ce, "ReflectionAttribute", class_ReflectionAttribute_methods);
14201424
class_entry = zend_register_internal_class_ex(&ce, NULL);
14211425
class_entry->ce_flags |= ZEND_ACC_FINAL;
1426+
zend_class_implements(class_entry, 1, class_entry_Reflector);
14221427

14231428
return class_entry;
14241429
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
ReflectionAttribute::__toString
3+
--FILE--
4+
<?php
5+
6+
#[Foo, Bar(a: "foo", b: 1234), Baz("foo", 1234)]
7+
function foo() {}
8+
9+
$refl = new ReflectionFunction('foo');
10+
echo $refl->getAttributes()[0];
11+
echo $refl->getAttributes()[1];
12+
echo $refl->getAttributes()[2];
13+
--EXPECTF--
14+
Attribute [ Foo ]
15+
Attribute [ Bar ] {
16+
- Arguments [2] {
17+
Argument #0 [ a = 'foo' ]
18+
Argument #1 [ b = 1234 ]
19+
}
20+
}
21+
Attribute [ Baz ] {
22+
- Arguments [2] {
23+
Argument #0 [ 'foo' ]
24+
Argument #1 [ 1234 ]
25+
}
26+
}

0 commit comments

Comments
 (0)