Skip to content

Commit 9f587dc

Browse files
committed
Handle dynamic properties, fix order & optionality
1 parent b6eb511 commit 9f587dc

11 files changed

+77
-21
lines changed

ext/reflection/php_reflection.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6682,20 +6682,22 @@ ZEND_METHOD(ReflectionProperty, isReadable)
66826682
{
66836683
reflection_object *intern;
66846684
property_reference *ref;
6685+
zend_string *scope_name;
66856686
zend_object *obj = NULL;
6686-
zend_string *scope_name = ZSTR_KNOWN(ZEND_STR_STATIC);
66876687

6688-
ZEND_PARSE_PARAMETERS_START(0, 2)
6688+
ZEND_PARSE_PARAMETERS_START(1, 2)
6689+
Z_PARAM_STR_OR_NULL(scope_name)
66896690
Z_PARAM_OPTIONAL
66906691
Z_PARAM_OBJ_OR_NULL(obj)
6691-
Z_PARAM_STR_OR_NULL(scope_name)
66926692
ZEND_PARSE_PARAMETERS_END();
66936693

66946694
GET_REFLECTION_OBJECT_PTR(ref);
66956695
zend_property_info *prop = ref->prop;
66966696
if (!prop) {
6697-
_DO_THROW("May not use isReadable on dynamic properties");
6698-
RETURN_THROWS();
6697+
if (!obj->properties) {
6698+
RETURN_FALSE;
6699+
}
6700+
RETURN_BOOL(zend_hash_find_ptr(obj->properties, ref->unmangled_name) != NULL);
66996701
}
67006702

67016703
if (obj) {
@@ -6751,20 +6753,22 @@ ZEND_METHOD(ReflectionProperty, isWritable)
67516753
{
67526754
reflection_object *intern;
67536755
property_reference *ref;
6756+
zend_string *scope_name;
67546757
zend_object *obj = NULL;
6755-
zend_string *scope_name = ZSTR_KNOWN(ZEND_STR_STATIC);
67566758

6757-
ZEND_PARSE_PARAMETERS_START(0, 2)
6759+
ZEND_PARSE_PARAMETERS_START(1, 2)
6760+
Z_PARAM_STR_OR_NULL(scope_name)
67586761
Z_PARAM_OPTIONAL
67596762
Z_PARAM_OBJ_OR_NULL(obj)
6760-
Z_PARAM_STR_OR_NULL(scope_name)
67616763
ZEND_PARSE_PARAMETERS_END();
67626764

67636765
GET_REFLECTION_OBJECT_PTR(ref);
67646766
zend_property_info *prop = ref->prop;
67656767
if (!prop) {
6766-
_DO_THROW("May not use isWritable on dynamic properties");
6767-
RETURN_THROWS();
6768+
if (obj->ce->ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES) {
6769+
RETURN_FALSE;
6770+
}
6771+
RETURN_TRUE;
67686772
}
67696773

67706774
if (obj) {

ext/reflection/php_reflection.stub.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -572,9 +572,9 @@ public function getHook(PropertyHookType $type): ?ReflectionMethod {}
572572

573573
public function isFinal(): bool {}
574574

575-
public function isReadable(?object $object = null, ?string $scope = 'static'): bool {}
575+
public function isReadable(?string $scope, ?object $object = null): bool {}
576576

577-
public function isWritable(?object $object = null, ?string $scope = 'static'): bool {}
577+
public function isWritable(?string $scope, ?object $object = null): bool {}
578578
}
579579

580580
/** @not-serializable */

ext/reflection/php_reflection_arginfo.h

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Test ReflectionProperty::isReadable() dynamic
3+
--FILE--
4+
<?php
5+
6+
#[AllowDynamicProperties]
7+
class A {}
8+
9+
$a = new A;
10+
11+
$a->a = 'a';
12+
$r = new ReflectionProperty($a, 'a');
13+
14+
var_dump($r->isReadable(null, $a));
15+
unset($a->a);
16+
var_dump($r->isReadable(null, $a));
17+
18+
$a = new A;
19+
var_dump($r->isReadable(null, $a));
20+
21+
?>
22+
--EXPECT--
23+
bool(true)
24+
bool(false)
25+
bool(false)

ext/reflection/tests/ReflectionProperty_isReadable_hooks.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ $test = static function ($scope) {
1616
$rc = new ReflectionClass(A::class);
1717
foreach ($rc->getProperties() as $rp) {
1818
echo $rp->getName() . ' from ' . ($scope ?? 'global') . ': ';
19-
var_dump($rp->isReadable(null, $scope));
19+
var_dump($rp->isReadable($scope, null));
2020
}
2121
};
2222

ext/reflection/tests/ReflectionProperty_isReadable_init.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ $test = static function ($class) {
4949
$rc = new ReflectionClass($class);
5050
foreach ($rc->getProperties() as $rp) {
5151
echo $rp->getName() . ' from global: ';
52-
var_dump($rp->isReadable(new $class, NULL));
52+
var_dump($rp->isReadable(null, new $class));
5353
}
5454
};
5555

ext/reflection/tests/ReflectionProperty_isReadable_visibility.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ $test = static function ($scope) {
1818
$rc = new ReflectionClass(B::class);
1919
foreach ($rc->getProperties() as $rp) {
2020
echo $rp->getName() . ' from ' . ($scope ?? 'global') . ': ';
21-
var_dump($rp->isReadable(null, $scope));
21+
var_dump($rp->isReadable($scope, null));
2222
}
2323
};
2424

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Test ReflectionProperty::isWritable() dynamic
3+
--FILE--
4+
<?php
5+
6+
#[AllowDynamicProperties]
7+
class A {
8+
private $a;
9+
}
10+
11+
$a = new A;
12+
13+
$r = new ReflectionProperty($a, 'a');
14+
var_dump($r->isWritable(null, $a));
15+
16+
$a->b = 'b';
17+
$r = new ReflectionProperty($a, 'b');
18+
var_dump($r->isWritable(null, $a));
19+
20+
$a = new A;
21+
var_dump($r->isWritable(null, $a));
22+
23+
?>
24+
--EXPECT--
25+
bool(false)
26+
bool(true)
27+
bool(true)

ext/reflection/tests/ReflectionProperty_isWritable_hooks.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ $test = static function ($scope) {
1616
$rc = new ReflectionClass(A::class);
1717
foreach ($rc->getProperties() as $rp) {
1818
echo $rp->getName() . ' from ' . ($scope ?? 'global') . ': ';
19-
var_dump($rp->isWritable(null, $scope));
19+
var_dump($rp->isWritable($scope, null));
2020
}
2121
};
2222

ext/reflection/tests/ReflectionProperty_isWritable_readonly.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function test($instance) {
2222
$rc = new ReflectionClass($instance);
2323
foreach ($rc->getProperties() as $rp) {
2424
echo $rp->getName() . ' from A: ';
25-
var_dump($rp->isWritable($instance, $instance::class));
25+
var_dump($rp->isWritable($instance::class, $instance));
2626
}
2727
}
2828

0 commit comments

Comments
 (0)