mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Add $filter parameter for ReflectionClass::(getConstants|getReflectionConstants)
This solves [#79628](https://bugs.php.net/79628). Similar to `ReflectionClass::getMethods()` and `ReflectionClass::getProperties()`, this new `$filter` argument allows the filtering of constants defined in a class by their visibility. For that, we create three new constants for `ReflectionClassConstant`: * `IS_PUBLIC` * `IS_PROTECTED` * `IS_PRIVATE` Closes GH-5649.
This commit is contained in:
parent
84492f5b50
commit
7439941d55
8 changed files with 188 additions and 22 deletions
2
NEWS
2
NEWS
|
@ -139,6 +139,8 @@ PHP NEWS
|
|||
. Fixed bug #69180 (Reflection does not honor trait conflict resolution /
|
||||
method aliasing). (Nikita)
|
||||
. Fixed bug #74939 (Nested traits' aliased methods are lowercased). (Nikita)
|
||||
. Implement #79628 (Add $filter parameter for ReflectionClass::getConstants
|
||||
and ReflectionClass::getReflectionConstants) (carusogabriel)
|
||||
|
||||
- Session:
|
||||
. Fixed bug #78624 (session_gc return value for user defined session
|
||||
|
|
|
@ -620,6 +620,15 @@ PHP 8.0 UPGRADE NOTES
|
|||
5. Changed Functions
|
||||
========================================
|
||||
|
||||
- Reflection:
|
||||
. ReflectionClass::getConstants and ReflectionClass::getReflectionConstants results
|
||||
can be now filtered via a new parameter `$filter`. 3 new constants were added to
|
||||
be used with it:
|
||||
|
||||
ReflectionClassConstant::IS_PUBLIC
|
||||
ReflectionClassConstant::IS_PROTECTED
|
||||
ReflectionClassConstant::IS_PRIVATE
|
||||
|
||||
- Zip
|
||||
. ZipArchive::addGlob and ZipArchive::addPattern methods accept more
|
||||
values in the "options" array argument:
|
||||
|
|
|
@ -4502,33 +4502,39 @@ ZEND_METHOD(ReflectionClass, hasConstant)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public array ReflectionClass::getConstants()
|
||||
/* {{{ proto public array ReflectionClass::getConstants([int $filter = ReflectionClassConstant::IS_PUBLIC | ReflectionClassConstant::IS_PROTECTED | ReflectionClassConstant::IS_PRIVATE])
|
||||
Returns an associative array containing this class' constants and their values */
|
||||
ZEND_METHOD(ReflectionClass, getConstants)
|
||||
{
|
||||
reflection_object *intern;
|
||||
zend_class_entry *ce;
|
||||
zend_string *key;
|
||||
zend_class_constant *c;
|
||||
zend_class_constant *constant;
|
||||
zval val;
|
||||
zend_long filter = ZEND_ACC_PPP_MASK;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &filter) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(ce);
|
||||
|
||||
array_init(return_value);
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
|
||||
if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, constant) {
|
||||
if (UNEXPECTED(zval_update_constant_ex(&constant->value, ce) != SUCCESS)) {
|
||||
zend_array_destroy(Z_ARRVAL_P(return_value));
|
||||
RETURN_NULL();
|
||||
}
|
||||
ZVAL_COPY_OR_DUP(&val, &c->value);
|
||||
zend_hash_add_new(Z_ARRVAL_P(return_value), key, &val);
|
||||
|
||||
if (Z_ACCESS_FLAGS(constant->value) & filter) {
|
||||
ZVAL_COPY_OR_DUP(&val, &constant->value);
|
||||
zend_hash_add_new(Z_ARRVAL_P(return_value), key, &val);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public array ReflectionClass::getReflectionConstants()
|
||||
/* {{{ proto public ReflectionClassConstant[] ReflectionClass::getReflectionConstants([int $filter = ReflectionClassConstant::IS_PUBLIC | ReflectionClassConstant::IS_PROTECTED | ReflectionClassConstant::IS_PRIVATE])
|
||||
Returns an associative array containing this class' constants as ReflectionClassConstant objects */
|
||||
ZEND_METHOD(ReflectionClass, getReflectionConstants)
|
||||
{
|
||||
|
@ -4536,16 +4542,21 @@ ZEND_METHOD(ReflectionClass, getReflectionConstants)
|
|||
zend_class_entry *ce;
|
||||
zend_string *name;
|
||||
zend_class_constant *constant;
|
||||
zend_long filter = ZEND_ACC_PPP_MASK;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &filter) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(ce);
|
||||
|
||||
array_init(return_value);
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) {
|
||||
zval class_const;
|
||||
reflection_class_constant_factory(name, constant, &class_const);
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &class_const);
|
||||
if (Z_ACCESS_FLAGS(constant->value) & filter) {
|
||||
zval class_const;
|
||||
reflection_class_constant_factory(name, constant, &class_const);
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &class_const);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -6722,6 +6733,11 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
|
|||
zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
|
||||
zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
|
||||
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
|
||||
|
||||
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClassConstant", class_ReflectionClassConstant_methods);
|
||||
reflection_init_class_handlers(&_reflection_entry);
|
||||
reflection_class_constant_ptr = zend_register_internal_class(&_reflection_entry);
|
||||
|
@ -6729,10 +6745,9 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
|
|||
zend_declare_property_string(reflection_class_constant_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
|
||||
zend_declare_property_string(reflection_class_constant_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
|
||||
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(class_constant, "IS_PUBLIC", ZEND_ACC_PUBLIC);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(class_constant, "IS_PROTECTED", ZEND_ACC_PROTECTED);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(class_constant, "IS_PRIVATE", ZEND_ACC_PRIVATE);
|
||||
|
||||
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", class_ReflectionExtension_methods);
|
||||
reflection_init_class_handlers(&_reflection_entry);
|
||||
|
|
|
@ -263,10 +263,10 @@ class ReflectionClass implements Reflector
|
|||
public function hasConstant(string $name) {}
|
||||
|
||||
/** @return array|null */
|
||||
public function getConstants() {}
|
||||
public function getConstants(int $filter = ReflectionClassConstant::IS_PUBLIC | ReflectionClassConstant::IS_PROTECTED | ReflectionClassConstant::IS_PRIVATE) {}
|
||||
|
||||
/** @return ReflectionClassConstant[] */
|
||||
public function getReflectionConstants() {}
|
||||
public function getReflectionConstants(int $filter = ReflectionClassConstant::IS_PUBLIC | ReflectionClassConstant::IS_PROTECTED | ReflectionClassConstant::IS_PRIVATE) {}
|
||||
|
||||
/** @return mixed */
|
||||
public function getConstant(string $name) {}
|
||||
|
|
|
@ -194,9 +194,11 @@ ZEND_END_ARG_INFO()
|
|||
|
||||
#define arginfo_class_ReflectionClass_hasConstant arginfo_class_ReflectionClass_hasMethod
|
||||
|
||||
#define arginfo_class_ReflectionClass_getConstants arginfo_class_ReflectionFunctionAbstract___clone
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionClass_getConstants, 0, 0, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, filter, IS_LONG, 0, "ReflectionClassConstant::IS_PUBLIC | ReflectionClassConstant::IS_PROTECTED | ReflectionClassConstant::IS_PRIVATE")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_ReflectionClass_getReflectionConstants arginfo_class_ReflectionFunctionAbstract___clone
|
||||
#define arginfo_class_ReflectionClass_getReflectionConstants arginfo_class_ReflectionClass_getConstants
|
||||
|
||||
#define arginfo_class_ReflectionClass_getConstant arginfo_class_ReflectionClass_hasMethod
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
--TEST--
|
||||
ReflectionClass::getConstants() with $filter
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
public const PUBLIC_CONST = 'BAR';
|
||||
public const ANOTHER_PUBLIC_CONST = 'BAZ';
|
||||
protected const PROTECTED_CONST = 'FOO';
|
||||
private const PRIVATE_CONST = 'QUOZ';
|
||||
}
|
||||
|
||||
class B {
|
||||
public const PUBLIC_CONST = 'BAR';
|
||||
protected const ANOTHER_PROTECTED_CONST = 'BAZ';
|
||||
protected const PROTECTED_CONST = 'FOO';
|
||||
private const PRIVATE_CONST = 'QUOZ';
|
||||
}
|
||||
|
||||
class C {
|
||||
public const PUBLIC_CONST = 'BAR';
|
||||
protected const PROTECTED_CONST = 'FOO';
|
||||
private const PRIVATE_CONST = 'QUOZ';
|
||||
private const ANOTHER_PRIVATE_CONST = 'BAZ';
|
||||
}
|
||||
|
||||
$reflectionClassA = new ReflectionClass(A::class);
|
||||
var_dump($reflectionClassA->getConstants(ReflectionClassConstant::IS_PUBLIC));
|
||||
|
||||
$reflectionClassB = new ReflectionClass(B::class);
|
||||
var_dump($reflectionClassB->getConstants(ReflectionClassConstant::IS_PROTECTED));
|
||||
|
||||
$reflectionClassC = new ReflectionClass(C::class);
|
||||
var_dump($reflectionClassC->getConstants(ReflectionClassConstant::IS_PRIVATE));
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(%d) {
|
||||
["PUBLIC_CONST"]=>
|
||||
string(%d) "BAR"
|
||||
["ANOTHER_PUBLIC_CONST"]=>
|
||||
string(%d) "BAZ"
|
||||
}
|
||||
array(%d) {
|
||||
["ANOTHER_PROTECTED_CONST"]=>
|
||||
string(%d) "BAZ"
|
||||
["PROTECTED_CONST"]=>
|
||||
string(%d) "FOO"
|
||||
}
|
||||
array(%d) {
|
||||
["PRIVATE_CONST"]=>
|
||||
string(%d) "QUOZ"
|
||||
["ANOTHER_PRIVATE_CONST"]=>
|
||||
string(%d) "BAZ"
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
--TEST--
|
||||
ReflectionClass::getReflectionConstants() with $filter
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
public const PUBLIC_CONST = 'BAR';
|
||||
public const ANOTHER_PUBLIC_CONST = 'BAZ';
|
||||
protected const PROTECTED_CONST = 'FOO';
|
||||
private const PRIVATE_CONST = 'QUOZ';
|
||||
}
|
||||
|
||||
class B {
|
||||
public const PUBLIC_CONST = 'BAR';
|
||||
protected const ANOTHER_PROTECTED_CONST = 'BAZ';
|
||||
protected const PROTECTED_CONST = 'FOO';
|
||||
private const PRIVATE_CONST = 'QUOZ';
|
||||
}
|
||||
|
||||
class C {
|
||||
public const PUBLIC_CONST = 'BAR';
|
||||
protected const PROTECTED_CONST = 'FOO';
|
||||
private const PRIVATE_CONST = 'QUOZ';
|
||||
private const ANOTHER_PRIVATE_CONST = 'BAZ';
|
||||
}
|
||||
|
||||
$reflectionClassA = new ReflectionClass(A::class);
|
||||
var_dump($reflectionClassA->getReflectionConstants(ReflectionClassConstant::IS_PUBLIC));
|
||||
|
||||
$reflectionClassB = new ReflectionClass(B::class);
|
||||
var_dump($reflectionClassB->getReflectionConstants(ReflectionClassConstant::IS_PROTECTED));
|
||||
|
||||
$reflectionClassC = new ReflectionClass(C::class);
|
||||
var_dump($reflectionClassC->getReflectionConstants(ReflectionClassConstant::IS_PRIVATE));
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(ReflectionClassConstant)#%d (%d) {
|
||||
["name"]=>
|
||||
string(%d) "PUBLIC_CONST"
|
||||
["class"]=>
|
||||
string(%d) "A"
|
||||
}
|
||||
[1]=>
|
||||
object(ReflectionClassConstant)#%d (%d) {
|
||||
["name"]=>
|
||||
string(%d) "ANOTHER_PUBLIC_CONST"
|
||||
["class"]=>
|
||||
string(%d) "A"
|
||||
}
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(ReflectionClassConstant)#%d (%d) {
|
||||
["name"]=>
|
||||
string(%d) "ANOTHER_PROTECTED_CONST"
|
||||
["class"]=>
|
||||
string(%d) "B"
|
||||
}
|
||||
[1]=>
|
||||
object(ReflectionClassConstant)#%d (%d) {
|
||||
["name"]=>
|
||||
string(%d) "PROTECTED_CONST"
|
||||
["class"]=>
|
||||
string(%d) "B"
|
||||
}
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(ReflectionClassConstant)#%d (%d) {
|
||||
["name"]=>
|
||||
string(%d) "PRIVATE_CONST"
|
||||
["class"]=>
|
||||
string(%d) "C"
|
||||
}
|
||||
[1]=>
|
||||
object(ReflectionClassConstant)#%d (%d) {
|
||||
["name"]=>
|
||||
string(%d) "ANOTHER_PRIVATE_CONST"
|
||||
["class"]=>
|
||||
string(%d) "C"
|
||||
}
|
||||
}
|
|
@ -165,13 +165,15 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector, String
|
|||
|
||||
Method [ <internal:Reflection> public method getConstants ] {
|
||||
|
||||
- Parameters [0] {
|
||||
- Parameters [1] {
|
||||
Parameter #0 [ <optional> int $filter = ReflectionClassConstant::IS_PUBLIC | ReflectionClassConstant::IS_PROTECTED | ReflectionClassConstant::IS_PRIVATE ]
|
||||
}
|
||||
}
|
||||
|
||||
Method [ <internal:Reflection> public method getReflectionConstants ] {
|
||||
|
||||
- Parameters [0] {
|
||||
- Parameters [1] {
|
||||
Parameter #0 [ <optional> int $filter = ReflectionClassConstant::IS_PUBLIC | ReflectionClassConstant::IS_PROTECTED | ReflectionClassConstant::IS_PRIVATE ]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue