Skip to content

Commit bc39abe

Browse files
beberleinikic
authored andcommitted
Fix #80097: Have ReflectionAttribute implement Reflector and __toString
Implement printing for ReflectionAttribute. Attributes aren't printed as part of reflection output for other structures (classes etc) yet. Closes GH-6117.
1 parent ce3846c commit bc39abe

File tree

5 files changed

+90
-5
lines changed

5 files changed

+90
-5
lines changed

NEWS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.1.0beta1
44

5-
5+
- Reflection:
6+
. Fixed bug #80097 (ReflectionAttribute is not a Reflector). (beberlei)
67

78
08 Jul 2021, PHP 8.1.0alpha3
89

ext/reflection/php_reflection.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6452,6 +6452,57 @@ ZEND_METHOD(ReflectionAttribute, __clone)
64526452
_DO_THROW("Cannot clone object using __clone()");
64536453
}
64546454

6455+
/* {{{ Returns a string representation */
6456+
ZEND_METHOD(ReflectionAttribute, __toString)
6457+
{
6458+
reflection_object *intern;
6459+
attribute_reference *attr;
6460+
6461+
if (zend_parse_parameters_none() == FAILURE) {
6462+
RETURN_THROWS();
6463+
}
6464+
6465+
GET_REFLECTION_OBJECT_PTR(attr);
6466+
6467+
smart_str str = {0};
6468+
smart_str_appends(&str, "Attribute [ ");
6469+
smart_str_append(&str, attr->data->name);
6470+
smart_str_appends(&str, " ]");
6471+
6472+
if (attr->data->argc > 0) {
6473+
smart_str_appends(&str, " {\n");
6474+
smart_str_append_printf(&str, " - Arguments [%d] {\n", attr->data->argc);
6475+
6476+
for (uint32_t i = 0; i < attr->data->argc; i++) {
6477+
zval tmp;
6478+
if (FAILURE == zend_get_attribute_value(&tmp, attr->data, i, attr->scope)) {
6479+
RETURN_THROWS();
6480+
}
6481+
6482+
smart_str_append_printf(&str, " Argument #%d [ ", i);
6483+
if (attr->data->args[i].name != NULL) {
6484+
smart_str_append(&str, attr->data->args[i].name);
6485+
smart_str_appends(&str, " = ");
6486+
}
6487+
6488+
if (format_default_value(&str, &tmp, NULL) == FAILURE) {
6489+
return;
6490+
}
6491+
6492+
smart_str_appends(&str, " ]\n");
6493+
zval_ptr_dtor(&tmp);
6494+
}
6495+
smart_str_appends(&str, " }\n");
6496+
6497+
smart_str_appends(&str, "}\n");
6498+
} else {
6499+
smart_str_appendc(&str, '\n');
6500+
}
6501+
6502+
RETURN_STR(smart_str_extract(&str));
6503+
}
6504+
/* }}} */
6505+
64556506
/* {{{ * Returns the name of the attribute */
64566507
ZEND_METHOD(ReflectionAttribute, getName)
64576508
{
@@ -7121,7 +7172,7 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
71217172
reflection_reference_ptr = register_class_ReflectionReference();
71227173
reflection_init_class_handlers(reflection_reference_ptr);
71237174

7124-
reflection_attribute_ptr = register_class_ReflectionAttribute();
7175+
reflection_attribute_ptr = register_class_ReflectionAttribute(reflector_ptr);
71257176
reflection_init_class_handlers(reflection_attribute_ptr);
71267177

71277178
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
@@ -687,14 +687,16 @@ private function __clone(): void {}
687687
private function __construct() {}
688688
}
689689

690-
final class ReflectionAttribute
690+
final class ReflectionAttribute implements Reflector
691691
{
692692
public function getName(): string {}
693693
public function getTarget(): int {}
694694
public function isRepeated(): bool {}
695695
public function getArguments(): array {}
696696
public function newInstance(): object {}
697697

698+
public function __toString(): string {}
699+
698700
private function __clone(): void {}
699701

700702
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: 2564122a201ca462ee35ead1562c94da3ea3c8a3 */
2+
* Stub hash: b70561858fb66134ce9596921215881fd9b946c0 */
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)
@@ -543,6 +543,8 @@ ZEND_END_ARG_INFO()
543543
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionAttribute_newInstance, 0, 0, IS_OBJECT, 0)
544544
ZEND_END_ARG_INFO()
545545

546+
#define arginfo_class_ReflectionAttribute___toString arginfo_class_ReflectionFunction___toString
547+
546548
#define arginfo_class_ReflectionAttribute___clone arginfo_class_ReflectionFunctionAbstract___clone
547549

548550
#define arginfo_class_ReflectionAttribute___construct arginfo_class_ReflectionReference___construct
@@ -800,6 +802,7 @@ ZEND_METHOD(ReflectionAttribute, getTarget);
800802
ZEND_METHOD(ReflectionAttribute, isRepeated);
801803
ZEND_METHOD(ReflectionAttribute, getArguments);
802804
ZEND_METHOD(ReflectionAttribute, newInstance);
805+
ZEND_METHOD(ReflectionAttribute, __toString);
803806
ZEND_METHOD(ReflectionAttribute, __clone);
804807
ZEND_METHOD(ReflectionAttribute, __construct);
805808
ZEND_METHOD(ReflectionEnum, __construct);
@@ -1130,6 +1133,7 @@ static const zend_function_entry class_ReflectionAttribute_methods[] = {
11301133
ZEND_ME(ReflectionAttribute, isRepeated, arginfo_class_ReflectionAttribute_isRepeated, ZEND_ACC_PUBLIC)
11311134
ZEND_ME(ReflectionAttribute, getArguments, arginfo_class_ReflectionAttribute_getArguments, ZEND_ACC_PUBLIC)
11321135
ZEND_ME(ReflectionAttribute, newInstance, arginfo_class_ReflectionAttribute_newInstance, ZEND_ACC_PUBLIC)
1136+
ZEND_ME(ReflectionAttribute, __toString, arginfo_class_ReflectionAttribute___toString, ZEND_ACC_PUBLIC)
11331137
ZEND_ME(ReflectionAttribute, __clone, arginfo_class_ReflectionAttribute___clone, ZEND_ACC_PRIVATE)
11341138
ZEND_ME(ReflectionAttribute, __construct, arginfo_class_ReflectionAttribute___construct, ZEND_ACC_PRIVATE)
11351139
ZEND_FE_END
@@ -1435,13 +1439,14 @@ static zend_class_entry *register_class_ReflectionReference(void)
14351439
return class_entry;
14361440
}
14371441

1438-
static zend_class_entry *register_class_ReflectionAttribute(void)
1442+
static zend_class_entry *register_class_ReflectionAttribute(zend_class_entry *class_entry_Reflector)
14391443
{
14401444
zend_class_entry ce, *class_entry;
14411445

14421446
INIT_CLASS_ENTRY(ce, "ReflectionAttribute", class_ReflectionAttribute_methods);
14431447
class_entry = zend_register_internal_class_ex(&ce, NULL);
14441448
class_entry->ce_flags |= ZEND_ACC_FINAL;
1449+
zend_class_implements(class_entry, 1, class_entry_Reflector);
14451450

14461451
return class_entry;
14471452
}
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)