* (bug 15558) Allow includable special pages to be parameterized using wiki syntax
authorAlexandre Emsenhuber <ialex@users.mediawiki.org>
Tue, 2 Aug 2011 15:40:03 +0000 (15:40 +0000)
committerAlexandre Emsenhuber <ialex@users.mediawiki.org>
Tue, 2 Aug 2011 15:40:03 +0000 (15:40 +0000)
* Changed SpecialPageFactory::capturePath() to take the same parameters as SpecialPageFactory::executePath() (except the last one) and made it always return a bool instead of bool-or-string. The result HTML can be fetched from the OutputPage object of the context.
* Added module styles, scritps and messages members to ParserOutput in addition to modules. The first one is needed to display Special:RecentChanges correctly when transcluded since EnhancedChangesList::beginRecentChangesList() calls addModuleStyles( 'mediawiki.special.changeslist' )

Yes, this means that you can use {{Special:Recentchanges|enhanced=0}} to use the old changes list. For the ones that wonder, {{Special:Recentchanges|uselang=something}} will not work since the Language object is forced to the one used by the parser.

RELEASE-NOTES-1.19
includes/OutputPage.php
includes/SpecialPageFactory.php
includes/parser/Parser.php
includes/parser/ParserOutput.php

index f1f758b..beb19a2 100644 (file)
@@ -23,6 +23,8 @@ production.
 * (bug 19052) Unicode space separator characters (Zs) now terminates external
   links and images links.
 * (bug 30160) Add public method to mw.loader to get module names from registry.
+* (bug 15558) Parameters to special pages included in wikitext can now be passed
+  as with templates.
 
 === Bug fixes in 1.19 ===
 * $wgUploadNavigationUrl should be used for file redlinks if
index 7808552..b1cf069 100644 (file)
@@ -525,6 +525,15 @@ class OutputPage extends ContextSource {
                $this->mModuleMessages = array_merge( $this->mModuleMessages, (array)$modules );
        }
 
+       /**
+        * Get an array of head items
+        *
+        * @return Array
+        */
+       function getHeadItemsArray() {
+               return $this->mHeadItems;
+       }
+
        /**
         * Get all header items in a string
         *
@@ -1405,6 +1414,9 @@ class OutputPage extends ContextSource {
                $this->mNoGallery = $parserOutput->getNoGallery();
                $this->mHeadItems = array_merge( $this->mHeadItems, $parserOutput->getHeadItems() );
                $this->addModules( $parserOutput->getModules() );
+               $this->addModuleScripts( $parserOutput->getModuleScripts() );
+               $this->addModuleStyles( $parserOutput->getModuleStyles() );
+               $this->addModuleMessages( $parserOutput->getModuleMessages() );
 
                // Template versioning...
                foreach ( (array)$parserOutput->getTemplateIds() as $ns => $dbks ) {
index 1b6be33..2b8e173 100644 (file)
@@ -471,40 +471,47 @@ class SpecialPageFactory {
        }
 
        /**
-        * Just like executePath() except it returns the HTML instead of outputting it
-        * Returns false if there was no such special page, or a title object if it was
+        * Just like executePath() but will override global variables and execute
+        * the page in "inclusion" mode. Returns true if the excution was successful
+        * or false if there was no such special page, or a title object if it was
         * a redirect.
         *
-        * Also saves the current $wgTitle, $wgOut, and $wgRequest variables so that
-        * the special page will get the context it'd expect on a normal request,
-        * and then restores them to their previous values after.
+        * Also saves the current $wgTitle, $wgOut, $wgRequest, $wgUser and $wgLang
+        * variables so that the special page will get the context it'd expect on a
+        * normal request, and then restores them to their previous values after.
         *
         * @param $title Title
+        * @param $context RequestContext
         *
         * @return String: HTML fragment
         */
-       static function capturePath( &$title ) {
-               global $wgOut, $wgTitle, $wgRequest;
+       static function capturePath( Title $title, RequestContext $context ) {
+               global $wgOut, $wgTitle, $wgRequest, $wgUser, $wgLang;
 
+               // Save current globals
                $oldTitle = $wgTitle;
                $oldOut = $wgOut;
                $oldRequest = $wgRequest;
+               $oldUser = $wgUser;
+               $oldLang = $wgLang;
 
-               // Don't want special pages interpreting ?feed=atom parameters.
-               $wgRequest = new FauxRequest( array() );
-
-               $context = new RequestContext;
-               $context->setTitle( $title );
-               $context->setRequest( $wgRequest );
+               // Set the globals to the current context
+               $wgTitle = $title;
                $wgOut = $context->getOutput();
+               $wgRequest = $context->getRequest();
+               $wgUser = $context->getUser();
+               $wgLang = $context->getLang();
 
+               // The useful part
                $ret = self::executePath( $title, $context, true );
-               if ( $ret === true ) {
-                       $ret = $wgOut->getHTML();
-               }
+
+               // And restore that globals
                $wgTitle = $oldTitle;
                $wgOut = $oldOut;
                $wgRequest = $oldRequest;
+               $wgUser = $oldUser;
+               $wgLang = $oldLang;
+
                return $ret;
        }
 
index 614b72a..6033b18 100644 (file)
@@ -3250,8 +3250,24 @@ class Parser {
                                        && $this->mOptions->getAllowSpecialInclusion()
                                        && $this->ot['html'] )
                                {
-                                       $text = SpecialPageFactory::capturePath( $title );
-                                       if ( is_string( $text ) ) {
+                                       $pageArgs = array();
+                                       for ( $i = 0; $i < $args->getLength(); $i++ ) {
+                                               $bits = $args->item( $i )->splitArg();
+                                               if ( strval( $bits['index'] ) === '' ) {
+                                                       $name = trim( $frame->expand( $bits['name'], PPFrame::STRIP_COMMENTS ) );
+                                                       $value = trim( $frame->expand( $bits['value'] ) );
+                                                       $pageArgs[$name] = $value;
+                                               }
+                                       }
+                                       $context = new RequestContext;
+                                       $context->setTitle( $title );
+                                       $context->setRequest( new FauxRequest( $pageArgs ) );
+                                       $context->setUser( $this->getUser() );
+                                       $context->setLang( Language::factory( $this->mOptions->getUserLang() ) );
+                                       $ret = SpecialPageFactory::capturePath( $title, $context );
+                                       if ( $ret ) {
+                                               $text = $context->getOutput()->getHTML();
+                                               $this->mOutput->addOutputPage( $context->getOutput() );
                                                $found = true;
                                                $isHTML = true;
                                                $this->disableCache();
index 363da78..aafcee8 100644 (file)
@@ -130,6 +130,9 @@ class ParserOutput extends CacheTime {
                $mNoGallery = false,          # No gallery on category page? (__NOGALLERY__)
                $mHeadItems = array(),        # Items to put in the <head> section
                $mModules = array(),          # Modules to be loaded by the resource loader
+               $mModuleScripts = array(),    # Modules of which only the JS will be loaded by the resource loader
+               $mModuleStyles = array(),     # Modules of which only the CSSS will be loaded by the resource loader
+               $mModuleMessages = array(),   # Modules of which only the messages will be loaded by the resource loader
                $mOutputHooks = array(),      # Hook tags as per $wgParserOutputHooks
                $mWarnings = array(),         # Warning text to be returned to the user. Wikitext formatted, in the key only
                $mSections = array(),         # Table of contents
@@ -195,6 +198,9 @@ class ParserOutput extends CacheTime {
        function getNoGallery()              { return $this->mNoGallery; }
        function getHeadItems()              { return $this->mHeadItems; }
        function getModules()                { return $this->mModules; }
+       function getModuleScripts()          { return $this->mModuleScripts; }
+       function getModuleStyles()           { return $this->mModuleStyles; }
+       function getModuleMessages()         { return $this->mModuleMessages; }
        function getOutputHooks()            { return (array)$this->mOutputHooks; }
        function getWarnings()               { return array_keys( $this->mWarnings ); }
        function getIndexPolicy()            { return $this->mIndexPolicy; }
@@ -334,10 +340,36 @@ class ParserOutput extends CacheTime {
                }
        }
 
-       function addModules( $modules ) {
+       public function addModules( $modules ) {
                $this->mModules = array_merge( $this->mModules, (array) $modules );
        }
 
+       public function addModuleScripts( $modules ) {
+               $this->mModuleScripts = array_merge( $this->mModuleScripts, (array)$modules );
+       }
+
+       public function addModuleStyles( $modules ) {
+               $this->mModuleStyles = array_merge( $this->mModuleStyles, (array)$modules );
+       }
+
+       public function addModuleMessages( $modules ) {
+               $this->mModuleMessages = array_merge( $this->mModuleMessages, (array)$modules );
+       }
+
+       /**
+        * Copy items from the OutputPage object into this one
+        *
+        * @param $out OutputPage object
+        */
+       public function addOutputPage( OutputPage $out ) {
+               $this->addModules( $out->getModules() );
+               $this->addModuleScripts( $out->getModuleScripts() );
+               $this->addModuleStyles( $out->getModuleStyles() );
+               $this->addModuleMessages( $out->getModuleMessages() );
+
+               $this->mHeadItems = array_merge( $this->mHeadItems, $out->getHeadItemsArray() );
+       }
+
        /**
         * Override the title to be used for display
         * -- this is assumed to have been validated