Add ReflectionProperty::getDefaultValue and ReflectionProperty::hasDefaultValue

This commit is contained in:
Benjamin Eberlei 2020-01-09 22:51:15 +01:00
parent 476636841f
commit 7a52bf21d3
5 changed files with 229 additions and 0 deletions

View File

@ -5686,6 +5686,90 @@ ZEND_METHOD(reflection_property, hasType)
}
/* }}} */
/* {{{ proto public bool ReflectionProperty::hasDefaultValue()
Returns whether property has a default value */
ZEND_METHOD(reflection_property, hasDefaultValue)
{
reflection_object *intern;
property_reference *ref;
zend_property_info *prop_info;
zval *prop;
zend_class_entry *ce;
if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
GET_REFLECTION_OBJECT_PTR(ref);
prop_info = ref->prop;
if (prop_info == NULL) {
RETURN_FALSE;
}
ce = prop_info->ce;
if ((prop_info->flags & ZEND_ACC_STATIC) != 0) {
prop = &ce->default_static_members_table[prop_info->offset];
ZVAL_DEINDIRECT(prop);
} else {
prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
}
RETURN_BOOL(!Z_ISUNDEF_P(prop));
}
/* }}} */
/* {{{ proto public mixed ReflectionProperty::getDefaultValue()
Returns the default value of a property */
ZEND_METHOD(reflection_property, getDefaultValue)
{
reflection_object *intern;
property_reference *ref;
zend_property_info *prop_info;
zval *prop;
zend_class_entry *ce;
if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
GET_REFLECTION_OBJECT_PTR(ref);
prop_info = ref->prop;
if (prop_info == NULL) {
return; // throw exception?
}
ce = prop_info->ce;
if ((prop_info->flags & ZEND_ACC_STATIC) != 0) {
prop = &ce->default_static_members_table[prop_info->offset];
ZVAL_DEINDIRECT(prop);
} else {
prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
}
if (Z_ISUNDEF_P(prop)) {
return;
}
/* copy: enforce read only access */
ZVAL_DEREF(prop);
ZVAL_COPY_OR_DUP(return_value, prop);
/* this is necessary to make it able to work with default array
* properties, returned to user */
if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
if (UNEXPECTED(zval_update_constant_ex(return_value, ce) != SUCCESS)) {
RETURN_THROWS();
}
}
}
/* }}} */
/* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException
Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_extension, export)
@ -6461,6 +6545,8 @@ static const zend_function_entry reflection_property_functions[] = {
ZEND_ME(reflection_property, setAccessible, arginfo_class_ReflectionProperty_setAccessible, 0)
ZEND_ME(reflection_property, getType, arginfo_class_ReflectionProperty_getType, 0)
ZEND_ME(reflection_property, hasType, arginfo_class_ReflectionProperty_hasType, 0)
ZEND_ME(reflection_property, hasDefaultValue, arginfo_class_ReflectionProperty_hasDefaultValue, 0)
ZEND_ME(reflection_property, getDefaultValue, arginfo_class_ReflectionProperty_getDefaultValue, 0)
PHP_FE_END
};

View File

@ -425,6 +425,11 @@ class ReflectionProperty implements Reflector
/** @return bool */
public function hasType() {}
public function hasDefaultValue(): bool {}
/** @return mixed */
public function getDefaultValue() {}
}
class ReflectionClassConstant implements Reflector

View File

@ -343,6 +343,11 @@ ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionProperty_hasType arginfo_class_Reflector___toString
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_hasDefaultValue, 0, 0, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_ReflectionProperty_getDefaultValue arginfo_class_Reflector___toString
#define arginfo_class_ReflectionClassConstant___clone arginfo_class_Reflector___toString
#define arginfo_class_ReflectionClassConstant_export arginfo_class_ReflectionMethod_export

View File

@ -0,0 +1,73 @@
--TEST--
reflection: ReflectionProperty::getDefaultValue
--FILE--
<?php
define('FOO', 42);
class TestClass
{
public $foo;
public $bar = 'baz';
public static $static1;
public static $static2 = 1234;
public int $val1;
public int $val2 = 1234;
public ?int $nullable;
public ?int $nullable2 = null;
public $constantAst = 2 * 2;
public $constantRuntimeAst = FOO;
}
$property = new ReflectionProperty(TestClass::class, 'foo');
var_dump($property->getDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'bar');
var_dump($property->getDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'static1');
var_dump($property->getDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'static2');
var_dump($property->getDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'val1');
var_dump($property->getDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'val2');
var_dump($property->getDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'nullable');
var_dump($property->getDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'nullable2');
var_dump($property->getDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'constantAst');
var_dump($property->getDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'constantRuntimeAst');
var_dump($property->getDefaultValue());
$test = new TestClass;
$test->dynamic = null;
$property = new ReflectionProperty($test, 'dynamic');
var_dump($property->getDefaultValue());
?>
--EXPECT--
NULL
string(3) "baz"
NULL
int(1234)
NULL
int(1234)
NULL
NULL
int(4)
int(42)
NULL

View File

@ -0,0 +1,60 @@
--TEST--
reflection: ReflectionProperty::hasDefaultValue
--FILE--
<?php
class TestClass
{
public $foo;
public $bar = 'baz';
public static $static1;
public static $static2 = 1234;
public int $val1;
public int $val2 = 1234;
public ?int $nullable;
public ?int $nullable2 = null;
}
$property = new ReflectionProperty(TestClass::class, 'foo');
var_dump($property->hasDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'bar');
var_dump($property->hasDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'static1');
var_dump($property->hasDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'static2');
var_dump($property->hasDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'val1');
var_dump($property->hasDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'val2');
var_dump($property->hasDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'nullable');
var_dump($property->hasDefaultValue());
$property = new ReflectionProperty(TestClass::class, 'nullable2');
var_dump($property->hasDefaultValue());
$test = new TestClass;
$test->dynamic = null;
$property = new ReflectionProperty($test, 'dynamic');
var_dump($property->hasDefaultValue());
?>
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)
bool(false)
bool(true)
bool(false)
bool(true)
bool(false)