From: Jackmcbarn Date: Tue, 16 Sep 2014 00:07:52 +0000 (-0400) Subject: Add parser callback to get a page's current revision X-Git-Tag: 1.31.0-rc.0~13815^2 X-Git-Url: http://git.cyclocoop.org/%22%20.%20generer_url_ecrire%28%22messagerie%22%29%20.%20%22?a=commitdiff_plain;h=edc9f2acd91c0c8e6b31bcef075b57486f0a2071;p=lhc%2Fweb%2Fwiklou.git Add parser callback to get a page's current revision Add Parser::fetchCurrentRevisionOfTitle(). By default, this just calls Revision::newFromTitle, but a callback can be set in ParserOptions that will override it. Anything that runs as part of a parse should use this wherever possible. Bug: 70495 Change-Id: I521f1f68ad819cf0f37e63240806f10c1cceef9c --- diff --git a/includes/parser/CoreParserFunctions.php b/includes/parser/CoreParserFunctions.php index eacbecd409..355a3c1216 100644 --- a/includes/parser/CoreParserFunctions.php +++ b/includes/parser/CoreParserFunctions.php @@ -1000,11 +1000,6 @@ class CoreParserFunctions { * @since 1.23 */ private static function getCachedRevisionObject( $parser, $title = null ) { - static $cache = null; - if ( $cache == null ) { - $cache = new MapCacheLRU( 50 ); - } - if ( is_null( $title ) ) { return null; } @@ -1024,22 +1019,18 @@ class CoreParserFunctions { // Normalize name for cache $page = $title->getPrefixedDBkey(); - if ( $cache->has( $page ) ) { // cache contains null values - return $cache->get( $page ); + if ( !( $parser->currentRevisionCache && $parser->currentRevisionCache->has( $page ) ) + && !$parser->incrementExpensiveFunctionCount() ) { + return null; } - if ( $parser->incrementExpensiveFunctionCount() ) { - $rev = Revision::newFromTitle( $title, false, Revision::READ_NORMAL ); - $pageID = $rev ? $rev->getPage() : 0; - $revID = $rev ? $rev->getId() : 0; - $cache->set( $page, $rev ); // maybe null + $rev = $parser->fetchCurrentRevisionOfTitle( $title ); + $pageID = $rev ? $rev->getPage() : 0; + $revID = $rev ? $rev->getId() : 0; - // Register dependency in templatelinks - $parser->getOutput()->addTemplate( $title, $pageID, $revID ); + // Register dependency in templatelinks + $parser->getOutput()->addTemplate( $title, $pageID, $revID ); - return $rev; - } - $cache->set( $page, null ); - return null; + return $rev; } /** diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index 8bf400a0cf..bff9c0dc27 100644 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@ -210,6 +210,14 @@ class Parser { */ public $mLangLinkLanguages; + /** + * @var MapCacheLRU|null + * @since 1.24 + * + * A cache of the current revisions of titles. Keys are $title->getPrefixedDbKey() + */ + public $currentRevisionCache; + /** * @var bool Recursive call protection. * This variable should be treated as if it were private. @@ -305,6 +313,7 @@ class Parser { $this->mVarCache = array(); $this->mUser = null; $this->mLangLinkLanguages = array(); + $this->currentRevisionCache = null; /** * Prefix for temporary replacement strings for the multipass parser. @@ -376,6 +385,7 @@ class Parser { $this->startParse( $title, $options, self::OT_HTML, $clearState ); + $this->currentRevisionCache = null; $this->mInputSize = strlen( $text ); if ( $this->mOptions->getEnableLimitReport() ) { $this->mOutput->resetParseStartTime(); @@ -588,6 +598,7 @@ class Parser { $this->mRevisionUser = $oldRevisionUser; $this->mRevisionSize = $oldRevisionSize; $this->mInputSize = false; + $this->currentRevisionCache = null; wfProfileOut( $fname ); wfProfileOut( __METHOD__ ); @@ -3794,6 +3805,44 @@ class Parser { return array( $dom, $title ); } + /** + * Fetch the current revision of a given title. Note that the revision + * (and even the title) may not exist in the database, so everything + * contributing to the output of the parser should use this method + * where possible, rather than getting the revisions themselves. This + * method also caches its results, so using it benefits performance. + * + * @since 1.24 + * @param Title $title + * @return Revision + */ + public function fetchCurrentRevisionOfTitle( $title ) { + $cacheKey = $title->getPrefixedDBkey(); + if ( !$this->currentRevisionCache ) { + $this->currentRevisionCache = new MapCacheLRU( 100 ); + } + if ( !$this->currentRevisionCache->has( $cacheKey ) ) { + $this->currentRevisionCache->set( $cacheKey, + // Defaults to Parser::statelessFetchRevision() + call_user_func( $this->mOptions->getCurrentRevisionCallback(), $title, $this ) + ); + } + return $this->currentRevisionCache->get( $cacheKey ); + } + + /** + * Wrapper around Revision::newFromTitle to allow passing additional parameters + * without passing them on to it. + * + * @since 1.24 + * @param Title $title + * @param Parser|bool $parser + * @return Revision + */ + public static function statelessFetchRevision( $title, $parser = false ) { + return Revision::newFromTitle( $title ); + } + /** * Fetch the unparsed text of a template and register a reference to it. * @param Title $title @@ -3859,9 +3908,13 @@ class Parser { break; } # Get the revision - $rev = $id - ? Revision::newFromId( $id ) - : Revision::newFromTitle( $title, false, Revision::READ_NORMAL ); + if ( $id ) { + $rev = Revision::newFromId( $id ); + } elseif ( $parser ) { + $rev = $parser->fetchCurrentRevisionOfTitle( $title ); + } else { + $rev = Revision::newFromTitle( $title ); + } $rev_id = $rev ? $rev->getId() : 0; # If there is no current revision, there is no page if ( $id === false && !$rev ) { diff --git a/includes/parser/ParserOptions.php b/includes/parser/ParserOptions.php index 2ca9d505bb..9966a1d79b 100644 --- a/includes/parser/ParserOptions.php +++ b/includes/parser/ParserOptions.php @@ -116,6 +116,12 @@ class ParserOptions { */ public $mRemoveComments = true; + /** + * Callback for current revision fetching. Used as first argument to call_user_func(). + */ + public $mCurrentRevisionCallback = + array( 'Parser', 'statelessFetchRevision' ); + /** * Callback for template fetching. Used as first argument to call_user_func(). */ @@ -282,6 +288,11 @@ class ParserOptions { return $this->mRemoveComments; } + /* @since 1.24 */ + public function getCurrentRevisionCallback() { + return $this->mCurrentRevisionCallback; + } + public function getTemplateCallback() { return $this->mTemplateCallback; } @@ -455,6 +466,11 @@ class ParserOptions { return wfSetVar( $this->mRemoveComments, $x ); } + /* @since 1.24 */ + public function setCurrentRevisionCallback( $x ) { + return wfSetVar( $this->mCurrentRevisionCallback, $x ); + } + public function setTemplateCallback( $x ) { return wfSetVar( $this->mTemplateCallback, $x ); }