X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2Fparser%2FParser.php;h=2d72debbab0ef32e04ad3c62dd65b2dae6b738a4;hb=fcf62b0965dd5ecfc4dee73e103e29bc5e2cc3e9;hp=84bb224300dfe9a362fb08886ab7bef49a9c9ad6;hpb=a01e85de7d06382681dc8e5a9bf112805dd7cdfa;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index 84bb224300..2d72debbab 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. @@ -258,6 +266,21 @@ class Parser { */ public function __clone() { $this->mInParse = false; + + // Bug 56226: When you create a reference "to" an object field, that + // makes the object field itself be a reference too (until the other + // reference goes out of scope). When cloning, any field that's a + // reference is copied as a reference in the new object. Both of these + // are defined PHP5 behaviors, as inconvenient as it is for us when old + // hooks from PHP4 days are passing fields by reference. + foreach ( array( 'mStripState', 'mVarCache' ) as $k ) { + // Make a non-reference copy of the field, then rebind the field to + // reference the new copy. + $tmp = $this->$k; + $this->$k =& $tmp; + unset( $tmp ); + } + wfRunHooks( 'ParserCloned', array( $this ) ); } @@ -305,6 +328,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 +400,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 +613,7 @@ class Parser { $this->mRevisionUser = $oldRevisionUser; $this->mRevisionSize = $oldRevisionSize; $this->mInputSize = false; + $this->currentRevisionCache = null; wfProfileOut( $fname ); wfProfileOut( __METHOD__ ); @@ -3829,6 +3855,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 @@ -3894,9 +3958,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 ) {