Skip ApiStashEdit if custom DataUpdates are present.
authordaniel <daniel.kinzler@wikimedia.de>
Fri, 9 Jan 2015 15:51:15 +0000 (15:51 +0000)
committerdaniel <daniel.kinzler@wikimedia.de>
Fri, 9 Jan 2015 15:51:15 +0000 (15:51 +0000)
Bug: T86305
Change-Id: I423ba39a46a08edf2862b8439169ff91338fb6eb

includes/api/ApiStashEdit.php
includes/parser/ParserOutput.php

index 938f6c0..4d181d6 100644 (file)
@@ -333,7 +333,14 @@ class ApiStashEdit extends ApiBase {
                // If an item is renewed, mind the cache TTL determined by config and parser functions
                $since = time() - wfTimestamp( TS_UNIX, $parserOutput->getTimestamp() );
                $ttl = min( $parserOutput->getCacheExpiry() - $since, 5 * 60 );
-               if ( $ttl > 0 && !$parserOutput->getFlag( 'vary-revision' ) ) {
+
+               // Note: ParserOutput with that contains secondary data update callbacks can not be
+               // stashed, since the callbacks are not serializable (see ParserOtput::__sleep).
+               // The first data update returned by getSecondaryDataUpdates() is always a LinksUpdate
+               // instance generated on the fly, so it can be ignored in this context.
+               $hasCustomDataUpdates = count( $parserOutput->getSecondaryDataUpdates() ) > 1;
+
+               if ( $ttl > 0 && !$parserOutput->getFlag( 'vary-revision' ) && !$hasCustomDataUpdates ) {
                        // Only store what is actually needed
                        $stashInfo = (object)array(
                                'pstContent' => $pstContent,
index 83f0f69..f155312 100644 (file)
@@ -53,7 +53,7 @@ class ParserOutput extends CacheTime {
                $mTOCEnabled = true;          # Whether TOC should be shown, can't override __NOTOC__
        private $mIndexPolicy = '';       # 'index' or 'noindex'?  Any other value will result in no change.
        private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys)
-       private $mSecondaryDataUpdates = array(); # List of DataUpdate, used to save info from the page somewhere else.
+       private $mSecondaryDataUpdates = null; # List of DataUpdate, used to save info from the page somewhere else.
        private $mExtensionData = array(); # extra data used by extensions
        private $mLimitReportData = array(); # Parser limit report data
        private $mParseStartTime = array(); # Timestamps for getTimeSinceStart()
@@ -70,6 +70,8 @@ class ParserOutput extends CacheTime {
                $this->mCategories = $categoryLinks;
                $this->mContainsOldMagic = $containsOldMagic;
                $this->mTitleText = $titletext;
+
+               $this->mSecondaryDataUpdates = array();
        }
 
        public function getText() {
@@ -702,6 +704,9 @@ class ParserOutput extends CacheTime {
         *    be created based on $this->getTitleText()
         * @param bool $recursive Queue jobs for recursive updates?
         *
+        * @throws MWException if called on a ParserOutput instance that was restored from serialization.
+        *         DataUpdates are generally not serializable, so after serialization, they are undefined.
+        *
         * @return array An array of instances of DataUpdate
         */
        public function getSecondaryDataUpdates( Title $title = null, $recursive = true ) {
@@ -709,6 +714,15 @@ class ParserOutput extends CacheTime {
                        $title = Title::newFromText( $this->getTitleText() );
                }
 
+               if ( $this->mSecondaryDataUpdates === null ) {
+                       //NOTE: This happens when mSecondaryDataUpdates are lost during serialization
+                       // (see __sleep below). After (un)serialization, getSecondaryDataUpdates()
+                       // has no defined behavior, and should throw an exception.
+                       throw new MWException( 'getSecondaryDataUpdates() must not be called on ParserOutput restored from serialization.' );
+               }
+
+               // NOTE: ApiStashEdit knows about this "magic" update object. If this goes away,
+               // ApiStashEdit::buildStashValue needs to be adjusted.
                $linksUpdate = new LinksUpdate( $title, $this, $recursive );
 
                return array_merge( $this->mSecondaryDataUpdates, array( $linksUpdate ) );