mirror of
https://github.com/php/php-src.git
synced 2025-08-19 17:04:47 +02:00
Implement ReflectionClass::setFinal() and ReflectionMethod::setFinal().
Patch by Jan Dolecek <juzna.cz@gmail.com>.
This commit is contained in:
parent
9025d6219d
commit
e76c1cc03c
5 changed files with 130 additions and 2 deletions
5
NEWS
5
NEWS
|
@ -35,4 +35,9 @@ PHP NEWS
|
||||||
- pgsql
|
- pgsql
|
||||||
. Added pg_escape_literal() and pg_escape_identifier() (Yasuo)
|
. 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 <juzna.cz@gmail.com>)
|
||||||
|
|
||||||
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
|
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
|
||||||
|
|
|
@ -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()
|
/* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass()
|
||||||
Get the declaring class */
|
Get the declaring class */
|
||||||
ZEND_METHOD(reflection_method, getDeclaringClass)
|
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()
|
/* {{{ proto public int ReflectionClass::getModifiers()
|
||||||
Returns a bitfield of the access modifiers for this class */
|
Returns a bitfield of the access modifiers for this class */
|
||||||
ZEND_METHOD(reflection_class, getModifiers)
|
ZEND_METHOD(reflection_class, getModifiers)
|
||||||
|
@ -5651,6 +5695,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setAccessible, 0)
|
||||||
ZEND_ARG_INFO(0, value)
|
ZEND_ARG_INFO(0, value)
|
||||||
ZEND_END_ARG_INFO()
|
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_BEGIN_ARG_INFO(arginfo_reflection_method_getClosure, 0)
|
||||||
ZEND_ARG_INFO(0, object)
|
ZEND_ARG_INFO(0, object)
|
||||||
ZEND_END_ARG_INFO()
|
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, isProtected, arginfo_reflection__void, 0)
|
||||||
ZEND_ME(reflection_method, isAbstract, 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, 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, isStatic, arginfo_reflection__void, 0)
|
||||||
ZEND_ME(reflection_method, isConstructor, arginfo_reflection__void, 0)
|
ZEND_ME(reflection_method, isConstructor, arginfo_reflection__void, 0)
|
||||||
ZEND_ME(reflection_method, isDestructor, 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_ARG_INFO(0, object)
|
||||||
ZEND_END_ARG_INFO()
|
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_BEGIN_ARG_INFO(arginfo_reflection_class_newInstance, 0)
|
||||||
ZEND_ARG_INFO(0, args)
|
ZEND_ARG_INFO(0, args)
|
||||||
ZEND_END_ARG_INFO()
|
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, isTrait, arginfo_reflection__void, 0)
|
||||||
ZEND_ME(reflection_class, isAbstract, 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, 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, getModifiers, arginfo_reflection__void, 0)
|
||||||
ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0)
|
ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0)
|
||||||
ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0)
|
ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0)
|
||||||
|
|
33
ext/reflection/tests/ReflectionClass_setFinal.phpt
Normal file
33
ext/reflection/tests/ReflectionClass_setFinal.phpt
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
--TEST--
|
||||||
|
Test ReflectionClass::setFinal().
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class a {
|
||||||
|
public final function b() {
|
||||||
|
print __METHOD__;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = new ReflectionClass('a');
|
||||||
|
$c->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
|
|
@ -8,7 +8,7 @@ Steve Seear <stevseea@php.net>
|
||||||
$rc = new ReflectionClass("ReflectionClass");
|
$rc = new ReflectionClass("ReflectionClass");
|
||||||
echo $rc;
|
echo $rc;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECT--
|
||||||
Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
|
Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
|
||||||
|
|
||||||
- Constants [3] {
|
- Constants [3] {
|
||||||
|
@ -34,7 +34,7 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
|
||||||
Property [ <default> public $name ]
|
Property [ <default> public $name ]
|
||||||
}
|
}
|
||||||
|
|
||||||
- Methods [49] {
|
- Methods [50] {
|
||||||
Method [ <internal:Reflection> final private method __clone ] {
|
Method [ <internal:Reflection> final private method __clone ] {
|
||||||
|
|
||||||
- Parameters [0] {
|
- Parameters [0] {
|
||||||
|
@ -230,6 +230,13 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Method [ <internal:Reflection> public method setFinal ] {
|
||||||
|
|
||||||
|
- Parameters [1] {
|
||||||
|
Parameter #0 [ <required> $value ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Method [ <internal:Reflection> public method getModifiers ] {
|
Method [ <internal:Reflection> public method getModifiers ] {
|
||||||
|
|
||||||
- Parameters [0] {
|
- Parameters [0] {
|
||||||
|
|
29
ext/reflection/tests/ReflectionMethod_setFinal.phpt
Normal file
29
ext/reflection/tests/ReflectionMethod_setFinal.phpt
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
--TEST--
|
||||||
|
Test ReflectionMethod::setFinal().
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class a {
|
||||||
|
public final function b() {
|
||||||
|
print __METHOD__;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$m = new ReflectionMethod('a', 'b');
|
||||||
|
$m->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
|
Loading…
Add table
Add a link
Reference in a new issue