Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add $filter parameter for ReflectionClass::(getConstants|getReflectionConstants) #5649

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 31 additions & 16 deletions ext/reflection/php_reflection.c
Expand Up @@ -4307,50 +4307,61 @@ 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)
{
reflection_object *intern;
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();
}
/* }}} */
Expand Down Expand Up @@ -6311,17 +6322,21 @@ 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);
zend_class_implements(reflection_class_constant_ptr, 1, reflector_ptr);
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);
Expand Down
4 changes: 2 additions & 2 deletions ext/reflection/php_reflection.stub.php
Expand Up @@ -260,10 +260,10 @@ public function getProperties(?int $filter = null) {}
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) {}
Expand Down
6 changes: 4 additions & 2 deletions ext/reflection/php_reflection_arginfo.h
Expand Up @@ -189,9 +189,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

Expand Down
14 changes: 7 additions & 7 deletions ext/reflection/tests/ReflectionClass_getConstant_basic.phpt
@@ -1,5 +1,5 @@
--TEST--
ReflectionClass::getConstants()
ReflectionClass::getConstant()
--FILE--
<?php
class C {
Expand All @@ -17,25 +17,25 @@ class X {

$classes = array("C", "D", "E", "F", "X");
foreach($classes as $class) {
echo "Reflecting on class $class: \n";
echo "Reflecting on class $class:\n";
$rc = new ReflectionClass($class);
var_dump($rc->getConstant('a'));
var_dump($rc->getConstant('doesnotexist'));
}
?>
--EXPECT--
Reflecting on class C:
Reflecting on class C:
string(12) "hello from C"
bool(false)
Reflecting on class D:
Reflecting on class D:
string(12) "hello from C"
bool(false)
Reflecting on class E:
Reflecting on class E:
string(12) "hello from C"
bool(false)
Reflecting on class F:
Reflecting on class F:
string(12) "hello from F"
bool(false)
Reflecting on class X:
Reflecting on class X:
bool(false)
bool(false)
53 changes: 53 additions & 0 deletions 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"
}
@@ -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"
}
}
6 changes: 4 additions & 2 deletions ext/reflection/tests/ReflectionClass_toString_001.phpt
Expand Up @@ -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 ]
}
}

Expand Down