Skip to content

Instantly share code, notes, and snippets.

@juzna
Created January 16, 2012 17:12
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juzna/1621839 to your computer and use it in GitHub Desktop.
Save juzna/1621839 to your computer and use it in GitHub Desktop.
Removing finals from PHP
<?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());
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)
@JanTvrdik
Copy link

Looks great. Now I just need to find a way how to compile PHP on Windows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment