Created
January 16, 2012 17:12
-
-
Save juzna/1621839 to your computer and use it in GitHub Desktop.
Removing finals from PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$doRemoveFinal = true; // play with it | |
// Imagine your favorite library here (of course it has finals) | |
class A { | |
final function getName() { return 'A'; } | |
} | |
final class B { | |
function getName() { return 'B'; } | |
} | |
// Hic sunt leones | |
if($doRemoveFinal) { | |
// Remove final from a method | |
$ra = new ReflectionMethod('A', 'getName'); | |
var_dump($ra->isFinal()); // true | |
$ra->setFinal(false); | |
var_dump($ra->isFinal()); // false | |
// Remove final from a method | |
$rb = new ReflectionClass('B'); | |
var_dump($rb->isFinal()); // true | |
$rb->setFinal(false); | |
var_dump($rb->isFinal()); // false | |
} | |
// Put it in a condition so that it's bound in runtime (otherwise error while compiling) | |
// Normally you would autoload mock classes after final has been removed | |
if(true) { | |
class MockA extends A { | |
function getName() { return 'Mock A'; } // would fail normally | |
} | |
class MockB extends B { // would fail normally | |
function getName() { return 'Mock B'; } | |
} | |
} | |
// Test mocks | |
$ma = new MockA(); | |
var_dump($ma->getName()); | |
$mb = new MockB(); | |
var_dump($mb->getName()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: ext/reflection/php_reflection.c | |
IDEA additional info: | |
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP | |
<+>UTF-8 | |
=================================================================== | |
--- ext/reflection/php_reflection.c (revision 322371) | |
+++ ext/reflection/php_reflection.c (revision ) | |
@@ -3113,6 +3113,25 @@ | |
} | |
/* }}} */ | |
+/* {{{ 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 +4066,25 @@ | |
} | |
/* }}} */ | |
+/* {{{ 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 +5689,10 @@ | |
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 +5706,7 @@ | |
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 +5776,10 @@ | |
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 +5832,7 @@ | |
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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Looks great. Now I just need to find a way how to compile PHP on Windows.