Allow registration of Actions using a callback that returns an Action instance
authorjeroendedauw <jeroendedauw@gmail.com>
Mon, 18 Feb 2013 22:23:16 +0000 (23:23 +0100)
committerJeroen De Dauw <jeroendedauw@gmail.com>
Wed, 4 Sep 2013 21:08:32 +0000 (21:08 +0000)
Basically implementing what Brion suggested on wikitech

This allows for injecting dependencies while still only loading the actual class when needed.

Simple example:

$wgActions['epundo'] = function( Page $page, IContextSource $context = null ) use ( $differ ) {
$undoAction = new \EducationProgram\UndoAction( $page, $context );
$undoAction->setDiffer( $differ );
return $undoAction;
};

Change-Id: I6c0f4022f1df1ebaf9cd1a5fe4bd362d0ecc0d62

RELEASE-NOTES-1.22
includes/Action.php

index e743b48..44b0fae 100644 (file)
@@ -151,6 +151,9 @@ production.
 ** editmyoptions controls whether a user may change their preferences.
 * Add new hook AbortTalkPageEmailNotification, this will be used to determine
   whether to send the regular talk page email notification
+* Action classes registered in $wgActions are now also supported in the form of
+  a callback (which returns an instance of Action) instead of providing the name
+  of a subclass of Action.
 * (bug 46513) Vector: Add the collapsibleTabs script from the Vector extension.
 * Added $wgRecentChangesFlags for defining new flags for RecentChanges and
   watchlists.
index e996104..23b648f 100644 (file)
@@ -59,7 +59,7 @@ abstract class Action {
         * the action is disabled, or null if it's not recognised
         * @param $action String
         * @param $overrides Array
-        * @return bool|null|string
+        * @return bool|null|string|callable
         */
        final private static function getClass( $action, array $overrides ) {
                global $wgActions;
@@ -89,12 +89,18 @@ abstract class Action {
         *     if it is not recognised
         */
        final public static function factory( $action, Page $page, IContextSource $context = null ) {
-               $class = self::getClass( $action, $page->getActionOverrides() );
-               if ( $class ) {
-                       $obj = new $class( $page, $context );
+               $classOrCallable = self::getClass( $action, $page->getActionOverrides() );
+
+               if ( is_string( $classOrCallable ) ) {
+                       $obj = new $classOrCallable( $page, $context );
                        return $obj;
                }
-               return $class;
+
+               if ( is_callable( $classOrCallable ) ) {
+                       return call_user_func_array( $classOrCallable, array( $page, $context ) );
+               }
+
+               return $classOrCallable;
        }
 
        /**
@@ -241,12 +247,14 @@ abstract class Action {
        }
 
        /**
-        * Protected constructor: use Action::factory( $action, $page ) to actually build
-        * these things in the real world
+        * Constructor.
+        *
+        * Only public since 1.21
+        *
         * @param $page Page
         * @param $context IContextSource
         */
-       protected function __construct( Page $page, IContextSource $context = null ) {
+       public function __construct( Page $page, IContextSource $context = null ) {
                $this->page = $page;
                $this->context = $context;
        }