From: Sebastian Bergmann Date: Tue, 17 Jan 2012 12:59:33 +0000 (+0000) Subject: Implement ReflectionClass::setFinal() and ReflectionMethod::setFinal(). X-Git-Tag: php-5.5.0alpha1~617 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e76c1cc03c3b20024e6773204e2501b64018697d;p=php Implement ReflectionClass::setFinal() and ReflectionMethod::setFinal(). Patch by Jan Dolecek . --- diff --git a/NEWS b/NEWS index 0cf44aa4d7..5a7ca1480a 100644 --- a/NEWS +++ b/NEWS @@ -35,4 +35,9 @@ PHP NEWS - pgsql . Added pg_escape_literal() and pg_escape_identifier() (Yasuo) +- Reflection: + . Added ReflectionCLass::setFinal() and ReflectionMethod::setFinal() to allow + stubbing and mocking of final classes and methods, for instance. + (Sebastian, Jan Dolecek ) + <<< NOTE: Insert NEWS from last stable release here prior to actual release! >>> diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 663eb405de..8fccd90547 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -3113,6 +3113,28 @@ ZEND_METHOD(reflection_method, getModifiers) } /* }}} */ +/* {{{ proto public void ReflectionMethod::setFinal([bool isFinal = true]) + Sets/unsets class as final */ +ZEND_METHOD(reflection_method, setFinal) +{ + reflection_object *intern; + zend_function *mptr; + zend_bool isFinal = 1; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &isFinal) == FAILURE) { + return; + } + + GET_REFLECTION_OBJECT_PTR(mptr); + + if (isFinal) { + mptr->common.fn_flags |= ZEND_ACC_FINAL; + } else { + mptr->common.fn_flags &= ~ZEND_ACC_FINAL; + } +} +/* }}} */ + /* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass() Get the declaring class */ ZEND_METHOD(reflection_method, getDeclaringClass) @@ -4047,6 +4069,28 @@ ZEND_METHOD(reflection_class, isAbstract) } /* }}} */ +/* {{{ proto public void ReflectionClass::setFinal([bool isFinal = true]) + Sets/unsets class as final */ +ZEND_METHOD(reflection_class, setFinal) +{ + reflection_object *intern; + zend_class_entry *ce; + zend_bool isFinal = 1; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &isFinal) == FAILURE) { + return; + } + + GET_REFLECTION_OBJECT_PTR(ce); + + if (isFinal) { + ce->ce_flags |= ZEND_ACC_FINAL_CLASS; + } else { + ce->ce_flags &= ~ZEND_ACC_FINAL_CLASS; + } +} +/* }}} */ + /* {{{ proto public int ReflectionClass::getModifiers() Returns a bitfield of the access modifiers for this class */ ZEND_METHOD(reflection_class, getModifiers) @@ -5651,6 +5695,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setAccessible, 0) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setFinal, 0) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_getClosure, 0) ZEND_ARG_INFO(0, object) ZEND_END_ARG_INFO() @@ -5664,6 +5712,7 @@ static const zend_function_entry reflection_method_functions[] = { ZEND_ME(reflection_method, isProtected, arginfo_reflection__void, 0) ZEND_ME(reflection_method, isAbstract, arginfo_reflection__void, 0) ZEND_ME(reflection_method, isFinal, arginfo_reflection__void, 0) + ZEND_ME(reflection_method, setFinal, arginfo_reflection_method_setFinal, 0) ZEND_ME(reflection_method, isStatic, arginfo_reflection__void, 0) ZEND_ME(reflection_method, isConstructor, arginfo_reflection__void, 0) ZEND_ME(reflection_method, isDestructor, arginfo_reflection__void, 0) @@ -5733,6 +5782,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isInstance, 0) ZEND_ARG_INFO(0, object) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_setFinal, 0) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstance, 0) ZEND_ARG_INFO(0, args) ZEND_END_ARG_INFO() @@ -5785,6 +5838,7 @@ static const zend_function_entry reflection_class_functions[] = { ZEND_ME(reflection_class, isTrait, arginfo_reflection__void, 0) ZEND_ME(reflection_class, isAbstract, arginfo_reflection__void, 0) ZEND_ME(reflection_class, isFinal, arginfo_reflection__void, 0) + ZEND_ME(reflection_class, setFinal, arginfo_reflection_class_setFinal, 0) ZEND_ME(reflection_class, getModifiers, arginfo_reflection__void, 0) ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0) ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0) diff --git a/ext/reflection/tests/ReflectionClass_setFinal.phpt b/ext/reflection/tests/ReflectionClass_setFinal.phpt new file mode 100644 index 0000000000..dfd98f3b6b --- /dev/null +++ b/ext/reflection/tests/ReflectionClass_setFinal.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test ReflectionClass::setFinal(). +--FILE-- +setFinal(FALSE); + +var_dump($c->isFinal()); + +# Not sure if it is by design that the following two lines are required +$m = new ReflectionMethod('a', 'b'); +$m->setFinal(FALSE); + +if (TRUE) { + class c extends a { + public function b() { + print __METHOD__; + } + } +} + +$o = new c; +$o->b(); +?> +--EXPECT-- +bool(false) +c::b diff --git a/ext/reflection/tests/ReflectionClass_toString_001.phpt b/ext/reflection/tests/ReflectionClass_toString_001.phpt index 508530a547..35ae07c884 100644 --- a/ext/reflection/tests/ReflectionClass_toString_001.phpt +++ b/ext/reflection/tests/ReflectionClass_toString_001.phpt @@ -8,7 +8,7 @@ Steve Seear $rc = new ReflectionClass("ReflectionClass"); echo $rc; ?> ---EXPECTF-- +--EXPECT-- Class [ class ReflectionClass implements Reflector ] { - Constants [3] { @@ -34,7 +34,7 @@ Class [ class ReflectionClass implements Reflector ] { Property [ public $name ] } - - Methods [49] { + - Methods [50] { Method [ final private method __clone ] { - Parameters [0] { @@ -230,6 +230,13 @@ Class [ class ReflectionClass implements Reflector ] { } } + Method [ public method setFinal ] { + + - Parameters [1] { + Parameter #0 [ $value ] + } + } + Method [ public method getModifiers ] { - Parameters [0] { diff --git a/ext/reflection/tests/ReflectionMethod_setFinal.phpt b/ext/reflection/tests/ReflectionMethod_setFinal.phpt new file mode 100644 index 0000000000..19d3ac8f30 --- /dev/null +++ b/ext/reflection/tests/ReflectionMethod_setFinal.phpt @@ -0,0 +1,29 @@ +--TEST-- +Test ReflectionMethod::setFinal(). +--FILE-- +setFinal(FALSE); + +var_dump($m->isFinal()); + +if (TRUE) { + class c extends a { + public function b() { + print __METHOD__; + } + } +} + +$o = new c; +$o->b(); +?> +--EXPECT-- +bool(false) +c::b