diff options
author | reeze <reeze.xia@gmail.com> | 2012-04-03 13:47:16 +0800 |
---|---|---|
committer | reeze <reeze.xia@gmail.com> | 2012-04-03 13:51:44 +0800 |
commit | 054f3e3ce5af13c2c3a6ccd54f7dc3e2f6cd4f74 (patch) | |
tree | 917f67b12eac5f27cb7241c4d0a2260c6ec624ef | |
parent | 3bf53aa911e1e2128a11aee45c126000635de006 (diff) | |
download | php-git-054f3e3ce5af13c2c3a6ccd54f7dc3e2f6cd4f74.tar.gz |
Implemented FR #61602 Allow access to name of constant used as default value
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 104 | ||||
-rw-r--r-- | ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic1.phpt | 52 | ||||
-rw-r--r-- | ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic2.phpt | 30 | ||||
-rw-r--r-- | ext/reflection/tests/ReflectionParameter_DefaultValueConstant_error.phpt | 25 |
5 files changed, 193 insertions, 20 deletions
@@ -100,6 +100,8 @@ PHP NEWS bytes). (Nikita Popov) - Reflection: + . Implemented FR #61602 (Allow access to the name of constant + used as function/method parameter's default value). (reeze.xia@gmail.com) . Fixed bug #60968 (Late static binding doesn't work with ReflectionMethod::invokeArgs()). (Laruence) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 1cf65cee16..ef1ed7ef65 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1457,6 +1457,57 @@ static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *c } /* }}} */ +/* {{{ _reflection_param_get_default_param */ +static parameter_reference *_reflection_param_get_default_param(INTERNAL_FUNCTION_PARAMETERS) +{ + reflection_object *intern; + parameter_reference *param; + + if (zend_parse_parameters_none() == FAILURE) { + return NULL; + } + + GET_REFLECTION_OBJECT_PTR(param); + + if (param->fptr->type != ZEND_USER_FUNCTION) + { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions"); + return NULL; + } + + if (param->offset < param->required) { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional"); + return NULL; + } + + return param; +} +/* }}} */ + +/* {{{ _reflection_param_get_default_precv */ +static zend_op *_reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAMETERS) +{ + zend_op *precv; + parameter_reference *param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU); + + if (zend_parse_parameters_none() == FAILURE) { + return NULL; + } + + if(!param) { + return NULL; + } + + precv = _get_recv_op((zend_op_array*)param->fptr, param->offset); + if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error"); + return NULL; + } + + return precv; +} +/* }}} */ + /* {{{ Preventing __clone from being called */ ZEND_METHOD(reflection, __clone) { @@ -2535,27 +2586,10 @@ ZEND_METHOD(reflection_parameter, isDefaultValueAvailable) Returns the default value of this parameter or throws an exception */ ZEND_METHOD(reflection_parameter, getDefaultValue) { - reflection_object *intern; - parameter_reference *param; - zend_op *precv; + parameter_reference *param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU); + zend_op *precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU); - if (zend_parse_parameters_none() == FAILURE) { - return; - } - GET_REFLECTION_OBJECT_PTR(param); - - if (param->fptr->type != ZEND_USER_FUNCTION) - { - zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions"); - return; - } - if (param->offset < param->required) { - zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional"); - return; - } - precv = _get_recv_op((zend_op_array*)param->fptr, param->offset); - if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) { - zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error"); + if(!(param && precv)) { return; } @@ -2568,6 +2602,34 @@ ZEND_METHOD(reflection_parameter, getDefaultValue) } /* }}} */ +/* {{{ proto public bool ReflectionParameter::isDefaultValueConstant() + Returns whether the default value of this parameter is constant */ +ZEND_METHOD(reflection_parameter, isDefaultValueConstant) +{ + zend_op *precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU); + + if (precv && (Z_TYPE_P(precv->op2.zv) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { + RETURN_TRUE; + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto public mixed ReflectionParameter::getDefaultValueConstantName() + Returns the default value's constant name if default value is constant or false */ +ZEND_METHOD(reflection_parameter, getDefaultValueConstantName) +{ + zend_op *precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU); + + if (precv && (Z_TYPE_P(precv->op2.zv) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { + RETURN_STRING(Z_STRVAL_P(precv->op2.zv), 1); + } + + RETURN_FALSE; +} +/* }}} */ + /* {{{ proto public static mixed ReflectionMethod::export(mixed class, 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_method, export) @@ -5903,6 +5965,8 @@ static const zend_function_entry reflection_parameter_functions[] = { ZEND_ME(reflection_parameter, isOptional, arginfo_reflection__void, 0) ZEND_ME(reflection_parameter, isDefaultValueAvailable, arginfo_reflection__void, 0) ZEND_ME(reflection_parameter, getDefaultValue, arginfo_reflection__void, 0) + ZEND_ME(reflection_parameter, isDefaultValueConstant, arginfo_reflection__void, 0) + ZEND_ME(reflection_parameter, getDefaultValueConstantName, arginfo_reflection__void, 0) PHP_FE_END }; diff --git a/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic1.phpt b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic1.phpt new file mode 100644 index 0000000000..cdd00d2624 --- /dev/null +++ b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic1.phpt @@ -0,0 +1,52 @@ +--TEST-- +ReflectionParameter::isDefaultValueConstant() && getDefaultValueConstantName() +--FILE-- +<?php + +define("CONST_TEST_1", "const1"); + +function ReflectionParameterTest($test1=array(), $test2 = CONST_TEST_1) { + echo $test; +} +$reflect = new ReflectionFunction('ReflectionParameterTest'); +foreach($reflect->getParameters() as $param) { + if($param->getName() == 'test1') { + var_dump($param->isDefaultValueConstant()); + } + if($param->getName() == 'test2') { + var_dump($param->isDefaultValueConstant()); + } + if($param->isDefaultValueAvailable() && $param->isDefaultValueConstant()) { + var_dump($param->getDefaultValueConstantName()); + } +} + +class Foo2 { + const bar = 'Foo2::bar'; +} + +class Foo { + const bar = 'Foo::bar'; + + public function baz($param1 = self::bar, $param2=Foo2::bar, $param3=CONST_TEST_1) { + } +} + +$method = new ReflectionMethod('Foo', 'baz'); +$params = $method->getParameters(); + +foreach ($params as $param) { + if ($param->isDefaultValueConstant()) { + var_dump($param->getDefaultValueConstantName()); + } +} +?> +==DONE== +--EXPECT-- +bool(false) +bool(true) +string(12) "CONST_TEST_1" +string(9) "self::bar" +string(9) "Foo2::bar" +string(12) "CONST_TEST_1" +==DONE== diff --git a/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic2.phpt b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic2.phpt new file mode 100644 index 0000000000..1ee9e93735 --- /dev/null +++ b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic2.phpt @@ -0,0 +1,30 @@ +--TEST-- +ReflectionParameter::isDefaultValueConstant() && getDefaultValueConstantName() for namespace +--FILE-- +<?php + +namespace ReflectionTestNamespace { + CONST TEST_CONST_1 = "Test Const 1"; + + class TestClass { + const TEST_CONST_2 = "Test Const 2 in class"; + } +} + +namespace { + function ReflectionParameterTest($test=ReflectionTestNamespace\TestClass::TEST_CONST_2, $test2 = ReflectionTestNamespace\CONST_TEST_1) { + echo $test; + } + $reflect = new ReflectionFunction('ReflectionParameterTest'); + foreach($reflect->getParameters() as $param) { + if($param->isDefaultValueAvailable() && $param->isDefaultValueConstant()) { + echo $param->getDefaultValueConstantName() . "\n"; + } + } + echo "==DONE=="; +} +?> +--EXPECT-- +ReflectionTestNamespace\TestClass::TEST_CONST_2 +ReflectionTestNamespace\CONST_TEST_1 +==DONE== diff --git a/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_error.phpt b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_error.phpt new file mode 100644 index 0000000000..984b06efe2 --- /dev/null +++ b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_error.phpt @@ -0,0 +1,25 @@ +--TEST-- +ReflectionParameter::getDefaultValueConstant() should raise exception on non optional parameter +--FILE-- +<?php + +define("CONST_TEST_1", "const1"); + +function ReflectionParameterTest($test, $test2 = CONST_TEST_1) { + echo $test; +} +$reflect = new ReflectionFunction('ReflectionParameterTest'); +foreach($reflect->getParameters() as $param) { + try { + echo $param->getDefaultValueConstantName() . "\n"; + } + catch(ReflectionException $e) { + echo $e->getMessage() . "\n"; + } +} +?> +==DONE== +--EXPECT-- +Parameter is not optional +CONST_TEST_1 +==DONE== |