Gotcha - so when's the submission deadline for patches to 1.10.0?
1.10 will branch from trunk in the first week of April per our quarterly release cycle.
Maybe best to not cut it too fine for anything "massive" though ... my mental model of what's going on is something like this:
V - Quarterly release | .... .... >>>> Zone of normal grumpiness. T .... I .... M - Three weeks to release E >>> Zone of steadily increasing grumpiness - One week to release | >>> Zone of extreme grumpiness! Bugfixes above new features. v - Quarterly release .... .... Rinse, repeat.
Step 1: For each class in MW, create a static factory method for class instantiation. ... Step 2: Replace all calls to the traditional "new Whatever($args)" with "Whatever::instantiate($args)".
Would it be nicer to have a single function / static method that did this (by passing in the classname as a parameter), rather than adding the same boilerplate code to every class in MediaWiki? Rough, probably-buggy, example code below.
Also adds creating singletons; Also adds allowing the class names to be overridden to instantiate a different class via a global. Whether any of these are desirable behaviour is for others to say (how abstract do you want to get?) - it was just a quick & dirty test mockup :
====================================================================== <?php
require_once '/var/www/hosts/mediawiki/wiki/maintenance/commandLine.inc';
/* ** An array of class names to override, where the key is the standard ** class name, and the value is the overridden class name (which should ** extended the standard class and/or implement the same interfaces that ** it does). */ global $wgClassOverrides; $wgClassOverrides = array();
class Factory {
/* ** Instantiate a new object, running before and after hooks. */ public static function wfNew( $class, &$args = NULL ) { $objResult = NULL; wfRunHooks('BeforeInstantiate_' . $class, array( &$objResult, &$args) );
if ($objResult === NULL) { $real_class = self::getRealClass( $class ); $objResult = new $real_class ($args); }
wfRunHooks('AfterInstantiate_' . $class, array( &$objResult, &$args) ); return $objResult; }
/* ** Returns the classname to use, allowing classnames to be overridden. ** Recursively calls itself, so as to allow stacking overrides. */ private static function getRealClass( $class ) { global $wgClassOverrides; if( isset ( $wgClassOverrides[$class] ) ) { return self::getRealClass ( $wgClassOverrides[$class] ); } else { return $class; } }
/* ** An array of singletons, where the key is the class name, and the ** value is the singleton object. */ private $singletons = array();
/* ** Returns a singleton for the specified class. */ public function & singleton( $class ) { $realClass = self::getRealClass( $class ); if( !isset( $this->singletons[$realClass] ) ) { $this->singletons[$realClass] = self::wfNew( $realClass ); } return $this->singletons[$realClass]; } }
// ------------- test code for the above -----------------
$wgHooks['BeforeInstantiate_Title'][] = 'BeforeInstantiate_Title'; $wgHooks['AfterInstantiate_Title' ][] = 'AfterInstantiate_Title';
/* ** Test dummy hooks for Title */ function BeforeInstantiate_Title () { print "In " . __FUNCTION__ . "\n"; }
function AfterInstantiate_Title () { print "In " . __FUNCTION__ . "\n"; }
/* ** Empty test class. */ class myTitle extends Title {
}
// we want to override the Title class, with the myTitle class. $wgClassOverrides['Title'] = 'myTitle';
// Should print out the two "In XXX" lines for the Before then After hooks. $title = Factory::wfNew( 'Title' );
// should give the class as myTitle. print "$title is a: " . get_class( $title ) . "\n";
// The factory that can build itself before it exists... :-) global $wgFactory; $wgFactory = Factory::wfNew( 'Factory' );
// test class that will print out a line when being constructed. class testTitle extends Title { function __construct () { print "Constructing one " . get_class( $this ) . "\n"; } }
// create a singleton $s1 = $wgFactory->singleton( 'testTitle' ); $s2 = $wgFactory->singleton( 'testTitle' ); $wgClassOverrides['fakeTitle'] = 'testTitle'; $s3 = $wgFactory->singleton( 'fakeTitle' );
// should only get one printout from the block of lines above.
?> ======================================================================
Are there reasons why this patch wouldn't be accepted that I should consider before undertaking the work to implement it?
I can't comment on whether others will accept it, only on whether I think it's worth doing, and for that I guess my 3 personal evaluation criteria would be: How much performance overhead would it add in real-world tests? How much harder would it make it for external people to understand what's going on in the code? How many people would use these style of hooks / overrides? (I.e. Not much point in doing it if nobody uses it; not much point in software that does wonderful things if it's so slow to use that nobody wants to use it; and I'm sure we've lost something worth having if newcomers look at the code and are baffled as to what's going on).
All the best, Nick.