Merge "Add tests for API's assert={user|bot}"
[lhc/web/wiklou.git] / includes / WikiPage.php
index d53acd0..cedbcf9 100644 (file)
@@ -352,10 +352,11 @@ class WikiPage implements Page, IDBAccessObject {
         * some source.
         *
         * @param object|string|int $from One of the following:
-        *        - A DB query result object
-        *        - "fromdb" or WikiPage::READ_NORMAL to get from a slave DB
-        *        - "fromdbmaster" or WikiPage::READ_LATEST to get from the master DB
-        *        - "forupdate"  or WikiPage::READ_LOCKING to get from the master DB using SELECT FOR UPDATE
+        *   - A DB query result object.
+        *   - "fromdb" or WikiPage::READ_NORMAL to get from a slave DB.
+        *   - "fromdbmaster" or WikiPage::READ_LATEST to get from the master DB.
+        *   - "forupdate"  or WikiPage::READ_LOCKING to get from the master DB
+        *     using SELECT FOR UPDATE.
         *
         * @return void
         */
@@ -688,7 +689,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @return string|bool The text of the current revision
         * @deprecated since 1.21, getContent() should be used instead.
         */
-       public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) { // @todo deprecated, replace usage!
+       public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) {
                ContentHandler::deprecated( __METHOD__, '1.21' );
 
                $this->loadLastEdit();
@@ -1291,9 +1292,10 @@ class WikiPage implements Page, IDBAccessObject {
         * @param bool $lastRevIsRedirect If given, will optimize adding and
         *   removing rows in redirect table.
         * @return bool true on success, false on failure
-        * @private
         */
-       public function updateRevisionOn( $dbw, $revision, $lastRevision = null, $lastRevIsRedirect = null ) {
+       public function updateRevisionOn( $dbw, $revision, $lastRevision = null,
+               $lastRevIsRedirect = null
+       ) {
                global $wgContentHandlerUseDB;
 
                wfProfileIn( __METHOD__ );
@@ -1385,6 +1387,8 @@ class WikiPage implements Page, IDBAccessObject {
         * If the given revision is newer than the currently set page_latest,
         * update the page record. Otherwise, do nothing.
         *
+        * @deprecated since 1.24, use updateRevisionOn instead
+        *
         * @param DatabaseBase $dbw
         * @param Revision $revision
         * @return bool
@@ -1475,12 +1479,15 @@ class WikiPage implements Page, IDBAccessObject {
         * @throws MWException
         * @return string New complete article text, or null if error.
         *
-        * @deprecated since 1.21, use replaceSectionContent() instead
+        * @deprecated since 1.21, use replaceSectionAtRev() instead
         */
-       public function replaceSection( $section, $text, $sectionTitle = '', $edittime = null ) {
+       public function replaceSection( $section, $text, $sectionTitle = '',
+               $edittime = null
+       ) {
                ContentHandler::deprecated( __METHOD__, '1.21' );
 
-               if ( strval( $section ) == '' ) { //NOTE: keep condition in sync with condition in replaceSectionContent!
+               //NOTE: keep condition in sync with condition in replaceSectionContent!
+               if ( strval( $section ) == '' ) {
                        // Whole-page edit; let the whole text through
                        return $text;
                }
@@ -1504,8 +1511,10 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @return bool
         *
-        * @todo The skin should check this and not offer section functionality if sections are not supported.
-        * @todo The EditPage should check this and not offer section functionality if sections are not supported.
+        * @todo The skin should check this and not offer section functionality if
+        *   sections are not supported.
+        * @todo The EditPage should check this and not offer section functionality
+        *   if sections are not supported.
         */
        public function supportsSections() {
                return $this->getContentHandler()->supportsSections();
@@ -1521,11 +1530,41 @@ class WikiPage implements Page, IDBAccessObject {
         * @return Content New complete article content, or null if error.
         *
         * @since 1.21
+        * @deprecated since 1.24, use replaceSectionAtRev instead
         */
        public function replaceSectionContent( $section, Content $sectionContent, $sectionTitle = '',
                $edittime = null ) {
                wfProfileIn( __METHOD__ );
 
+               $baseRevId = null;
+               if ( $edittime && $section !== 'new' ) {
+                       $dbw = wfGetDB( DB_MASTER );
+                       $rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime );
+                       if ( $rev ) {
+                               $baseRevId = $rev->getId();
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $this->replaceSectionAtRev( $section, $sectionContent, $sectionTitle, $baseRevId );
+       }
+
+       /**
+        * @param string|null|bool $section Null/false, a section number (0, 1, 2, T1, T2, ...) or "new".
+        * @param Content $sectionContent New content of the section.
+        * @param string $sectionTitle New section's subject, only if $section is "new".
+        * @param string $baseRevId integer|null
+        *
+        * @throws MWException
+        * @return Content New complete article content, or null if error.
+        *
+        * @since 1.24
+        */
+       public function replaceSectionAtRev( $section, Content $sectionContent,
+               $sectionTitle = '', $baseRevId = null
+       ) {
+               wfProfileIn( __METHOD__ );
+
                if ( strval( $section ) == '' ) {
                        // Whole-page edit; let the whole text through
                        $newContent = $sectionContent;
@@ -1537,15 +1576,16 @@ class WikiPage implements Page, IDBAccessObject {
                        }
 
                        // Bug 30711: always use current version when adding a new section
-                       if ( is_null( $edittime ) || $section == 'new' ) {
+                       if ( is_null( $baseRevId ) || $section == 'new' ) {
                                $oldContent = $this->getContent();
                        } else {
+                               // TODO: try DB_SLAVE first
                                $dbw = wfGetDB( DB_MASTER );
-                               $rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime );
+                               $rev = Revision::loadFromId( $dbw, $baseRevId );
 
                                if ( !$rev ) {
-                                       wfDebug( "WikiPage::replaceSection asked for bogus section (page: " .
-                                               $this->getId() . "; section: $section; edittime: $edittime)\n" );
+                                       wfDebug( __METHOD__ . " asked for bogus section (page: " .
+                                               $this->getId() . "; section: $section)\n" );
                                        wfProfileOut( __METHOD__ );
                                        return null;
                                }
@@ -1559,7 +1599,6 @@ class WikiPage implements Page, IDBAccessObject {
                                return null;
                        }
 
-                       // FIXME: $oldContent might be null?
                        $newContent = $oldContent->replaceSection( $section, $sectionContent, $sectionTitle );
                }
 
@@ -1606,10 +1645,11 @@ class WikiPage implements Page, IDBAccessObject {
         *      EDIT_AUTOSUMMARY
         *          Fill in blank summaries with generated text where possible
         *
-        * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected.
-        * If EDIT_UPDATE is specified and the article doesn't exist, the function will return an
-        * edit-gone-missing error. If EDIT_NEW is specified and the article does exist, an
-        * edit-already-exists error will be returned. These two conditions are also possible with
+        * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the
+        * article will be detected. If EDIT_UPDATE is specified and the article
+        * doesn't exist, the function will return an edit-gone-missing error. If
+        * EDIT_NEW is specified and the article does exist, an edit-already-exists
+        * error will be returned. These two conditions are also possible with
         * auto-detection due to MediaWiki's performance-optimised locking strategy.
         *
         * @param bool|int $baseRevId The revision ID this edit was based off, if any
@@ -1617,19 +1657,21 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @throws MWException
         * @return Status object. Possible errors:
-        *     edit-hook-aborted:       The ArticleSave hook aborted the edit but didn't set the fatal flag of $status
-        *     edit-gone-missing:       In update mode, but the article didn't exist
-        *     edit-conflict:           In update mode, the article changed unexpectedly
-        *     edit-no-change:          Warning that the text was the same as before
-        *     edit-already-exists:     In creation mode, but the article already exists
+        *   edit-hook-aborted: The ArticleSave hook aborted the edit but didn't
+        *     set the fatal flag of $status
+        *   edit-gone-missing: In update mode, but the article didn't exist.
+        *   edit-conflict: In update mode, the article changed unexpectedly.
+        *   edit-no-change: Warning that the text was the same as before.
+        *   edit-already-exists: In creation mode, but the article already exists.
         *
-        *  Extensions may define additional errors.
+        * Extensions may define additional errors.
         *
-        *  $return->value will contain an associative array with members as follows:
-        *     new:                     Boolean indicating if the function attempted to create a new article
-        *     revision:                The revision object for the inserted revision, or null
+        * $return->value will contain an associative array with members as follows:
+        *     new: Boolean indicating if the function attempted to create a new article.
+        *     revision: The revision object for the inserted revision, or null.
         *
-        *  Compatibility note: this function previously returned a boolean value indicating success/failure
+        * Compatibility note: this function previously returned a boolean value
+        * indicating success/failure
         *
         * @deprecated since 1.21: use doEditContent() instead.
         */
@@ -1663,29 +1705,32 @@ class WikiPage implements Page, IDBAccessObject {
         *      EDIT_AUTOSUMMARY
         *          Fill in blank summaries with generated text where possible
         *
-        * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected.
-        * If EDIT_UPDATE is specified and the article doesn't exist, the function will return an
-        * edit-gone-missing error. If EDIT_NEW is specified and the article does exist, an
-        * edit-already-exists error will be returned. These two conditions are also possible with
+        * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the
+        * article will be detected. If EDIT_UPDATE is specified and the article
+        * doesn't exist, the function will return an edit-gone-missing error. If
+        * EDIT_NEW is specified and the article does exist, an edit-already-exists
+        * error will be returned. These two conditions are also possible with
         * auto-detection due to MediaWiki's performance-optimised locking strategy.
         *
         * @param bool|int $baseRevId The revision ID this edit was based off, if any
         * @param User $user The user doing the edit
-        * @param string $serialisation_format Format for storing the content in the database
+        * @param string $serialisation_format Format for storing the content in the
+        *   database.
         *
         * @throws MWException
         * @return Status object. Possible errors:
-        *     edit-hook-aborted:       The ArticleSave hook aborted the edit but didn't set the fatal flag of $status
-        *     edit-gone-missing:       In update mode, but the article didn't exist
-        *     edit-conflict:           In update mode, the article changed unexpectedly
-        *     edit-no-change:          Warning that the text was the same as before
-        *     edit-already-exists:     In creation mode, but the article already exists
+        *     edit-hook-aborted: The ArticleSave hook aborted the edit but didn't
+        *       set the fatal flag of $status.
+        *     edit-gone-missing: In update mode, but the article didn't exist.
+        *     edit-conflict: In update mode, the article changed unexpectedly.
+        *     edit-no-change: Warning that the text was the same as before.
+        *     edit-already-exists: In creation mode, but the article already exists.
         *
         *  Extensions may define additional errors.
         *
         *  $return->value will contain an associative array with members as follows:
-        *     new:                     Boolean indicating if the function attempted to create a new article
-        *     revision:                The revision object for the inserted revision, or null
+        *     new: Boolean indicating if the function attempted to create a new article.
+        *     revision: The revision object for the inserted revision, or null.
         *
         * @since 1.21
         */
@@ -1825,11 +1870,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                                        // Update page
                                        //
-                                       // Note that we use $this->mLatest instead of fetching a value from the master DB
-                                       // during the course of this function. This makes sure that EditPage can detect
-                                       // edit conflicts reliably, either by $ok here, or by $article->getTimestamp()
-                                       // before this function is called. A previous function used a separate query, this
-                                       // creates a window where concurrent edits can cause an ignored edit conflict.
+                                       // We check for conflicts by comparing $oldid with the current latest revision ID.
                                        $ok = $this->updateRevisionOn( $dbw, $revision, $oldid, $oldIsRedirect );
 
                                        if ( !$ok ) {
@@ -2020,7 +2061,8 @@ class WikiPage implements Page, IDBAccessObject {
                $options = $this->getContentHandler()->makeParserOptions( $context );
 
                if ( $this->getTitle()->isConversionTable() ) {
-                       // @todo ConversionTable should become a separate content model, so we don't need special cases like this one.
+                       // @todo ConversionTable should become a separate content model, so
+                       // we don't need special cases like this one.
                        $options->disableContentConversion();
                }
 
@@ -2087,7 +2129,9 @@ class WikiPage implements Page, IDBAccessObject {
 
                $edit->format = $serialization_format;
                $edit->popts = $this->makeParserOptions( 'canonical' );
-               $edit->output = $edit->pstContent ? $edit->pstContent->getParserOutput( $this->mTitle, $revid, $edit->popts ) : null;
+               $edit->output = $edit->pstContent
+                       ? $edit->pstContent->getParserOutput( $this->mTitle, $revid, $edit->popts )
+                       : null;
 
                $edit->newContent = $content;
                $edit->oldContent = $this->getContent( Revision::RAW );
@@ -2298,7 +2342,9 @@ class WikiPage implements Page, IDBAccessObject {
         * @param User $user The user updating the restrictions
         * @return Status
         */
-       public function doUpdateRestrictions( array $limit, array $expiry, &$cascade, $reason, User $user ) {
+       public function doUpdateRestrictions( array $limit, array $expiry,
+               &$cascade, $reason, User $user
+       ) {
                global $wgCascadingRestrictionLevels, $wgContLang;
 
                if ( wfReadOnly() ) {
@@ -2384,7 +2430,9 @@ class WikiPage implements Page, IDBAccessObject {
                        }
 
                        // Only certain restrictions can cascade...
-                       $editrestriction = isset( $limit['edit'] ) ? array( $limit['edit'] ) : $this->mTitle->getRestrictions( 'edit' );
+                       $editrestriction = isset( $limit['edit'] )
+                               ? array( $limit['edit'] )
+                               : $this->mTitle->getRestrictions( 'edit' );
                        foreach ( array_keys( $editrestriction, 'sysop' ) as $key ) {
                                $editrestriction[$key] = 'editprotected'; // backwards compatibility
                        }
@@ -2407,7 +2455,15 @@ class WikiPage implements Page, IDBAccessObject {
 
                        // insert null revision to identify the page protection change as edit summary
                        $latest = $this->getLatest();
-                       $nullRevision = $this->insertProtectNullRevision( $revCommentMsg, $limit, $expiry, $cascade, $reason, $user );
+                       $nullRevision = $this->insertProtectNullRevision(
+                               $revCommentMsg,
+                               $limit,
+                               $expiry,
+                               $cascade,
+                               $reason,
+                               $user
+                       );
+
                        if ( $nullRevision === null ) {
                                return Status::newFatal( 'no-null-revision', $this->mTitle->getPrefixedText() );
                        }
@@ -2509,7 +2565,9 @@ class WikiPage implements Page, IDBAccessObject {
         * @param User|null $user
         * @return Revision|null Null on error
         */
-       public function insertProtectNullRevision( $revCommentMsg, array $limit, array $expiry, $cascade, $reason, $user = null ) {
+       public function insertProtectNullRevision( $revCommentMsg, array $limit,
+               array $expiry, $cascade, $reason, $user = null
+       ) {
                global $wgContLang;
                $dbw = wfGetDB( DB_MASTER );
 
@@ -2526,7 +2584,8 @@ class WikiPage implements Page, IDBAccessObject {
                $protectDescription = $this->protectDescription( $limit, $expiry );
                if ( $protectDescription ) {
                        $editComment .= wfMessage( 'word-separator' )->inContentLanguage()->text();
-                       $editComment .= wfMessage( 'parentheses' )->params( $protectDescription )->inContentLanguage()->text();
+                       $editComment .= wfMessage( 'parentheses' )->params( $protectDescription )
+                               ->inContentLanguage()->text();
                }
                if ( $cascade ) {
                        $editComment .= wfMessage( 'word-separator' )->inContentLanguage()->text();
@@ -2717,15 +2776,22 @@ class WikiPage implements Page, IDBAccessObject {
                        return $status;
                }
 
+               $dbw = wfGetDB( DB_MASTER );
+               $dbw->begin( __METHOD__ );
+
                if ( $id == 0 ) {
                        $this->loadPageData( 'forupdate' );
                        $id = $this->getID();
                        if ( $id == 0 ) {
+                               $dbw->rollback( __METHOD__ );
                                $status->error( 'cannotdelete', wfEscapeWikiText( $this->getTitle()->getPrefixedText() ) );
                                return $status;
                        }
                }
 
+               // we need to remember the old content so we can use it to generate all deletion updates.
+               $content = $this->getContent( Revision::RAW );
+
                // Bitfields to further suppress the content
                if ( $suppress ) {
                        $bitfield = 0;
@@ -2738,11 +2804,6 @@ class WikiPage implements Page, IDBAccessObject {
                        $bitfield = 'rev_deleted';
                }
 
-               // we need to remember the old content so we can use it to generate all deletion updates.
-               $content = $this->getContent( Revision::RAW );
-
-               $dbw = wfGetDB( DB_MASTER );
-               $dbw->begin( __METHOD__ );
                // For now, shunt the revision data into the archive table.
                // Text is *not* removed from the text table; bulk storage
                // is left intact to avoid breaking block-compression or
@@ -2800,6 +2861,9 @@ class WikiPage implements Page, IDBAccessObject {
                        $dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ );
                }
 
+               // Clone the title, so we have the information we need when we log
+               $logTitle = clone $this->mTitle;
+
                $this->doDeleteUpdates( $id, $content );
 
                // Log the deletion, if the page was suppressed, log it at Oversight instead
@@ -2807,10 +2871,14 @@ class WikiPage implements Page, IDBAccessObject {
 
                $logEntry = new ManualLogEntry( $logtype, 'delete' );
                $logEntry->setPerformer( $user );
-               $logEntry->setTarget( $this->mTitle );
+               $logEntry->setTarget( $logTitle );
                $logEntry->setComment( $reason );
                $logid = $logEntry->insert();
-               $logEntry->publish( $logid );
+
+               $dbw->onTransactionPreCommitOrIdle( function() use ( $dbw, $logEntry, $logid ) {
+                       // Bug 56776: avoid deadlocks (especially from FileDeleteForm)
+                       $logEntry->publish( $logid );
+               } );
 
                if ( $commit ) {
                        $dbw->commit( __METHOD__ );
@@ -2825,8 +2893,9 @@ class WikiPage implements Page, IDBAccessObject {
         * Do some database updates after deletion
         *
         * @param int $id page_id value of the page being deleted
-        * @param Content $content Optional page content to be used when determining the required updates.
-        *   This may be needed because $this->getContent() may already return null when the page proper was deleted.
+        * @param Content $content Optional page content to be used when determining
+        *   the required updates. This may be needed because $this->getContent()
+        *   may already return null when the page proper was deleted.
         */
        public function doDeleteUpdates( $id, Content $content = null ) {
                // update site status
@@ -2963,7 +3032,9 @@ class WikiPage implements Page, IDBAccessObject {
                if ( $s === false ) {
                        // No one else ever edited this page
                        return array( array( 'cantrollback' ) );
-               } elseif ( $s->rev_deleted & Revision::DELETED_TEXT || $s->rev_deleted & Revision::DELETED_USER ) {
+               } elseif ( $s->rev_deleted & Revision::DELETED_TEXT
+                       || $s->rev_deleted & Revision::DELETED_USER
+               ) {
                        // Only admins can see this text
                        return array( array( 'notvisiblerev' ) );
                }
@@ -3031,7 +3102,13 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                // Actually store the edit
-               $status = $this->doEditContent( $target->getContent(), $summary, $flags, $target->getId(), $guser );
+               $status = $this->doEditContent(
+                       $target->getContent(),
+                       $summary,
+                       $flags,
+                       $target->getId(),
+                       $guser
+               );
 
                if ( !$status->isOK() ) {
                        return $status->getErrorsArray();
@@ -3138,7 +3215,8 @@ class WikiPage implements Page, IDBAccessObject {
         * Purge caches on page update etc
         *
         * @param Title $title
-        * @todo Verify that $title is always a Title object (and never false or null), add Title hint to parameter $title
+        * @todo Verify that $title is always a Title object (and never false or
+        *   null), add Title hint to parameter $title.
         */
        public static function onArticleEdit( $title ) {
                // Invalidate caches of articles which include this page
@@ -3220,7 +3298,8 @@ class WikiPage implements Page, IDBAccessObject {
         * @deprecated since 1.21, use ContentHandler::getAutosummary() instead
         */
        public static function getAutosummary( $oldtext, $newtext, $flags ) {
-               // NOTE: stub for backwards-compatibility. assumes the given text is wikitext. will break horribly if it isn't.
+               // NOTE: stub for backwards-compatibility. assumes the given text is
+               // wikitext. will break horribly if it isn't.
 
                ContentHandler::deprecated( __METHOD__, '1.21' );
 
@@ -3370,7 +3449,8 @@ class WikiPage implements Page, IDBAccessObject {
 
                if ( count( $links_diff ) > 0 ) {
                        // Whee, link updates time.
-                       // Note: we are only interested in links here. We don't need to get other DataUpdate items from the parser output.
+                       // Note: we are only interested in links here. We don't need to get
+                       // other DataUpdate items from the parser output.
                        $u = new LinksUpdate( $this->mTitle, $parserOutput, false );
                        $u->doUpdate();
                }
@@ -3457,10 +3537,12 @@ class WikiPage implements Page, IDBAccessObject {
        }
 
        /**
-        * Returns a list of updates to be performed when this page is deleted. The updates should remove any information
-        * about this page from secondary data stores such as links tables.
+        * Returns a list of updates to be performed when this page is deleted. The
+        * updates should remove any information about this page from secondary data
+        * stores such as links tables.
         *
-        * @param Content|null $content Optional Content object for determining the necessary updates
+        * @param Content|null $content Optional Content object for determining the
+        *   necessary updates.
         * @return array An array of DataUpdates objects
         */
        public function getDeletionUpdates( Content $content = null ) {
@@ -3483,57 +3565,42 @@ class WikiPage implements Page, IDBAccessObject {
 }
 
 class PoolWorkArticleView extends PoolCounterWork {
-
-       /**
-        * @var Page
-        */
+       /** @var Page */
        private $page;
 
-       /**
-        * @var string
-        */
+       /** @var string */
        private $cacheKey;
 
-       /**
-        * @var int
-        */
+       /** @var int */
        private $revid;
 
-       /**
-        * @var ParserOptions
-        */
+       /** @var ParserOptions */
        private $parserOptions;
 
-       /**
-        * @var Content|null
-        */
+       /** @var Content|null */
        private $content = null;
 
-       /**
-        * @var ParserOutput|bool
-        */
+       /** @var ParserOutput|bool */
        private $parserOutput = false;
 
-       /**
-        * @var bool
-        */
+       /** @var bool */
        private $isDirty = false;
 
-       /**
-        * @var Status|bool
-        */
+       /** @var Status|bool */
        private $error = false;
 
        /**
-        * Constructor
-        *
         * @param Page $page
-        * @param int $revid ID of the revision being parsed
-        * @param bool $useParserCache Whether to use the parser cache
-        * @param ParserOptions $parserOptions ParserOptions to use for the parse operation
-        * @param Content|string $content Content to parse or null to load it; may also be given as a wikitext string, for BC
-        */
-       public function __construct( Page $page, ParserOptions $parserOptions, $revid, $useParserCache, $content = null ) {
+        * @param int $revid ID of the revision being parsed.
+        * @param bool $useParserCache Whether to use the parser cache.
+        * @param ParserOptions $parserOptions ParserOptions to use for the parse
+        *   operation.
+        * @param Content|string $content Content to parse or null to load it; may
+        *   also be given as a wikitext string, for BC.
+        */
+       public function __construct( Page $page, ParserOptions $parserOptions,
+               $revid, $useParserCache, $content = null
+       ) {
                if ( is_string( $content ) ) { // BC: old style call
                        $modelId = $page->getRevision()->getContentModel();
                        $format = $page->getRevision()->getContentFormat();
@@ -3611,7 +3678,11 @@ class PoolWorkArticleView extends PoolCounterWork {
                $cacheTime = wfTimestampNow();
 
                $time = - microtime( true );
-               $this->parserOutput = $content->getParserOutput( $this->page->getTitle(), $this->revid, $this->parserOptions );
+               $this->parserOutput = $content->getParserOutput(
+                       $this->page->getTitle(),
+                       $this->revid,
+                       $this->parserOptions
+               );
                $time += microtime( true );
 
                // Timing hack