summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Caruso <carusogabriel34@gmail.com>2020-05-31 00:17:31 +0200
committerGabriel Caruso <carusogabriel34@gmail.com>2020-06-07 15:57:48 +0200
commit7439941d55ea9cf7e1280b6b30f596e34a56512c (patch)
treecc289f8b99ce19ef3c8453543966d6f829fd2995
parent84492f5b50e9c0075e7a9d10a4de38f0674a0197 (diff)
downloadphp-git-7439941d55ea9cf7e1280b6b30f596e34a56512c.tar.gz
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.
-rw-r--r--NEWS2
-rw-r--r--UPGRADING9
-rw-r--r--ext/reflection/php_reflection.c47
-rw-r--r--ext/reflection/php_reflection.stub.php4
-rw-r--r--ext/reflection/php_reflection_arginfo.h6
-rw-r--r--ext/reflection/tests/ReflectionClass_getConstants_filter.phpt53
-rw-r--r--ext/reflection/tests/ReflectionClass_getReflectionConstants_filter.phpt83
-rw-r--r--ext/reflection/tests/ReflectionClass_toString_001.phpt6
8 files changed, 188 insertions, 22 deletions
diff --git a/NEWS b/NEWS
index f43f320b25..c4eb3fdbad 100644
--- a/NEWS
+++ b/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
diff --git a/UPGRADING b/UPGRADING
index 5555786316..f7f4344c6e 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -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:
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 9903863391..e7296b8008 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -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);
diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php
index e3d3fee52c..49872137a4 100644
--- a/ext/reflection/php_reflection.stub.php
+++ b/ext/reflection/php_reflection.stub.php
@@ -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) {}
diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h
index e5ed4742ff..ce3c69de09 100644
--- a/ext/reflection/php_reflection_arginfo.h
+++ b/ext/reflection/php_reflection_arginfo.h
@@ -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
diff --git a/ext/reflection/tests/ReflectionClass_getConstants_filter.phpt b/ext/reflection/tests/ReflectionClass_getConstants_filter.phpt
new file mode 100644
index 0000000000..00dd961b77
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClass_getConstants_filter.phpt
@@ -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"
+}
diff --git a/ext/reflection/tests/ReflectionClass_getReflectionConstants_filter.phpt b/ext/reflection/tests/ReflectionClass_getReflectionConstants_filter.phpt
new file mode 100644
index 0000000000..afff6b67ce
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClass_getReflectionConstants_filter.phpt
@@ -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"
+ }
+}
diff --git a/ext/reflection/tests/ReflectionClass_toString_001.phpt b/ext/reflection/tests/ReflectionClass_toString_001.phpt
index fb39bdb4de..e0860b2005 100644
--- a/ext/reflection/tests/ReflectionClass_toString_001.phpt
+++ b/ext/reflection/tests/ReflectionClass_toString_001.phpt
@@ -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 ]
}
}