Use preview content when it transcludes itself
authorJackmcbarn <jackmcbarn@gmail.com>
Tue, 3 Jun 2014 20:10:02 +0000 (16:10 -0400)
committerJackmcbarn <jackmcbarn@gmail.com>
Tue, 30 Dec 2014 17:59:16 +0000 (12:59 -0500)
When a page transcludes itself, such as <noinclude>foo
{{:{{FULLPAGENAME}}}}</noinclude><includeonly>bar</includeonly>, use the
preview content in its own transclusions. This code was basically ripped
straight from Extension:TemplateSandbox.

Bug: T85408
Bug: T7278
Change-Id: I1aa091a395a4f7b7b744e09e0bed59bc2e1176d0

includes/EditPage.php
includes/parser/ParserOptions.php

index 2155c1b..b65668e 100644 (file)
@@ -3561,6 +3561,8 @@ HTML
                        # But it's now deprecated, so never mind
 
                        $pstContent = $content->preSaveTransform( $this->mTitle, $wgUser, $parserOptions );
+                       $scopedCallback = $parserOptions->setupFakeRevision(
+                               $this->mTitle, $pstContent, $wgUser );
                        $parserOutput = $pstContent->getParserOutput( $this->mTitle, null, $parserOptions );
 
                        # Try to stash the edit for the final submission step
index 7ad85a9..ddeb906 100644 (file)
@@ -818,4 +818,46 @@ class ParserOptions {
 
                return $confstr;
        }
+
+       /**
+        * Sets a hook to force that a page exists, and sets a current revision callback to return a
+        * revision with custom content when the current revision of the page is requested.
+        *
+        * @since 1.25
+        * @param Title $title
+        * @param Content $content
+        * @param User $user The user that the fake revision is attributed to
+        * @return ScopedCallback to unset the hook
+        */
+       public function setupFakeRevision( $title, $content, $user ) {
+               $oldCallback = $this->setCurrentRevisionCallback( function ( $titleToCheck, $parser = false ) use ( $title, $content, $user, &$oldCallback ) {
+                       if ( $titleToCheck->equals( $title ) ) {
+                               return new Revision( array(
+                                       'page' => $title->getArticleID(),
+                                       'user_text' => $user->getName(),
+                                       'user' => $user->getId(),
+                                       'parent_id' => $title->getLatestRevId(),
+                                       'title' => $title,
+                                       'content' => $content
+                               ) );
+                       } else {
+                               return call_user_func( $oldCallback, $titleToCheck, $parser );
+                       }
+               } );
+               global $wgHooks;
+               $wgHooks['TitleExists'][] =
+                       function ( $titleToCheck, &$exists ) use ( $title ) {
+                               if ( $titleToCheck->equals( $title ) ) {
+                                       $exists = true;
+                               }
+                       };
+               end( $wgHooks['TitleExists'] );
+               $key = key( $wgHooks['TitleExists'] );
+               LinkCache::singleton()->clearBadLink( $title->getPrefixedDBkey() );
+               return new ScopedCallback( function () use ( $title, $key ) {
+                       global $wgHooks;
+                       unset( $wgHooks['TitleExists'][$key] );
+                       LinkCache::singleton()->clearLink( $title );
+               } );
+       }
 }