Perform edit stashing when the edit preview or diff form is requested
[lhc/web/wiklou.git] / includes / api / ApiStashEdit.php
index 814a111..67939a0 100644 (file)
@@ -122,7 +122,7 @@ class ApiStashEdit extends ApiBase {
                if ( $user->pingLimiter( 'stashedit' ) ) {
                        $status = 'ratelimited';
                } elseif ( $dbw->lock( $key, __METHOD__, 1 ) ) {
-                       $status = self::parseAndStash( $page, $content, $user );
+                       $status = self::parseAndStash( $page, $content, $user, $params['summary'] );
                        $dbw->unlock( $key, __METHOD__ );
                } else {
                        $status = 'busy';
@@ -135,12 +135,13 @@ class ApiStashEdit extends ApiBase {
 
        /**
         * @param WikiPage $page
-        * @param Content $content
+        * @param Content $content Edit content
         * @param User $user
+        * @param string $summary Edit summary
         * @return integer ApiStashEdit::ERROR_* constant
         * @since 1.25
         */
-       public static function parseAndStash( WikiPage $page, Content $content, User $user ) {
+       public static function parseAndStash( WikiPage $page, Content $content, User $user, $summary ) {
                $cache = ObjectCache::getLocalClusterInstance();
                $logger = LoggerFactory::getInstance( 'StashEdit' );
 
@@ -152,9 +153,10 @@ class ApiStashEdit extends ApiBase {
                        $key = self::getStashKey( $title, $content, $user );
 
                        // Let extensions add ParserOutput metadata or warm other caches
-                       Hooks::run( 'ParserOutputStashForEdit', [ $page, $content, $editInfo->output ] );
+                       Hooks::run( 'ParserOutputStashForEdit',
+                               [ $page, $content, $editInfo->output, $summary, $user ] );
 
-                       list( $stashInfo, $ttl ) = self::buildStashValue(
+                       list( $stashInfo, $ttl, $code ) = self::buildStashValue(
                                $editInfo->pstContent,
                                $editInfo->output,
                                $editInfo->timestamp,
@@ -171,7 +173,7 @@ class ApiStashEdit extends ApiBase {
                                        return self::ERROR_CACHE;
                                }
                        } else {
-                               $logger->info( "Uncacheable parser output for key '$key' ('$title')." );
+                               $logger->info( "Uncacheable parser output for key '$key' ('$title') [$code]." );
                                return self::ERROR_UNCACHEABLE;
                        }
                }
@@ -179,77 +181,6 @@ class ApiStashEdit extends ApiBase {
                return self::ERROR_PARSE;
        }
 
-       /**
-        * Attempt to cache PST content and corresponding parser output in passing
-        *
-        * This method can be called when the output was already generated for other
-        * reasons. Parsing should not be done just to call this method, however.
-        * $pstOpts must be that of the user doing the edit preview. If $pOpts does
-        * not match the options of WikiPage::makeParserOptions( 'canonical' ), this
-        * will do nothing. Provided the values are cacheable, they will be stored
-        * in memcached so that final edit submission might make use of them.
-        *
-        * @param Page|Article|WikiPage $page Page title
-        * @param Content $content Proposed page content
-        * @param Content $pstContent The result of preSaveTransform() on $content
-        * @param ParserOutput $pOut The result of getParserOutput() on $pstContent
-        * @param ParserOptions $pstOpts Options for $pstContent (MUST be for prospective author)
-        * @param ParserOptions $pOpts Options for $pOut
-        * @param string $timestamp TS_MW timestamp of parser output generation
-        * @return bool Success
-        */
-       public static function stashEditFromPreview(
-               Page $page, Content $content, Content $pstContent, ParserOutput $pOut,
-               ParserOptions $pstOpts, ParserOptions $pOpts, $timestamp
-       ) {
-               $cache = ObjectCache::getLocalClusterInstance();
-               $logger = LoggerFactory::getInstance( 'StashEdit' );
-
-               // getIsPreview() controls parser function behavior that references things
-               // like user/revision that don't exists yet. The user/text should already
-               // be set correctly by callers, just double check the preview flag.
-               if ( !$pOpts->getIsPreview() ) {
-                       return false; // sanity
-               } elseif ( $pOpts->getIsSectionPreview() ) {
-                       return false; // short-circuit (need the full content)
-               }
-
-               // PST parser options are for the user (handles signatures, etc...)
-               $user = $pstOpts->getUser();
-               // Get a key based on the source text, format, and user preferences
-               $title = $page->getTitle();
-               $key = self::getStashKey( $title, $content, $user );
-
-               // Parser output options must match cannonical options.
-               // Treat some options as matching that are different but don't matter.
-               $canonicalPOpts = $page->makeParserOptions( 'canonical' );
-               $canonicalPOpts->setIsPreview( true ); // force match
-               $canonicalPOpts->setTimestamp( $pOpts->getTimestamp() ); // force match
-               if ( !$pOpts->matches( $canonicalPOpts ) ) {
-                       $logger->info( "Uncacheable preview output for key '$key' ('$title') [options]." );
-                       return false;
-               }
-
-               // Set the time the output was generated
-               $pOut->setCacheTime( wfTimestampNow() );
-
-               // Build a value to cache with a proper TTL
-               list( $stashInfo, $ttl ) = self::buildStashValue( $pstContent, $pOut, $timestamp, $user );
-               if ( !$stashInfo ) {
-                       $logger->info( "Uncacheable parser output for key '$key' ('$title') [rev/TTL]." );
-                       return false;
-               }
-
-               $ok = $cache->set( $key, $stashInfo, $ttl );
-               if ( !$ok ) {
-                       $logger->error( "Failed to cache preview parser output for key '$key' ('$title')." );
-               } else {
-                       $logger->debug( "Cached preview output for key '$key'." );
-               }
-
-               return $ok;
-       }
-
        /**
         * Check that a prepared edit is in cache and still up-to-date
         *
@@ -376,7 +307,7 @@ class ApiStashEdit extends ApiBase {
         * @param ParserOutput $parserOutput
         * @param string $timestamp TS_MW
         * @param User $user
-        * @return array (stash info array, TTL in seconds) or (null, 0)
+        * @return array (stash info array, TTL in seconds, info code) or (null, 0, info code)
         */
        private static function buildStashValue(
                Content $pstContent, ParserOutput $parserOutput, $timestamp, User $user
@@ -385,19 +316,21 @@ class ApiStashEdit extends ApiBase {
                // Put an upper limit on the TTL for sanity to avoid extreme template/file staleness.
                $since = time() - wfTimestamp( TS_UNIX, $parserOutput->getTimestamp() );
                $ttl = min( $parserOutput->getCacheExpiry() - $since, self::MAX_CACHE_TTL );
-
-               if ( $ttl > 0 && !$parserOutput->getFlag( 'vary-revision' ) ) {
-                       // Only store what is actually needed
-                       $stashInfo = (object)[
-                               'pstContent' => $pstContent,
-                               'output'     => $parserOutput,
-                               'timestamp'  => $timestamp,
-                               'edits'      => $user->getEditCount()
-                       ];
-                       return [ $stashInfo, $ttl ];
+               if ( $ttl <= 0 ) {
+                       return [ null, 0, 'no_ttl' ];
+               } elseif ( $parserOutput->getFlag( 'vary-revision' ) ) {
+                       return [ null, 0, 'vary_revision' ];
                }
 
-               return [ null, 0 ];
+               // Only store what is actually needed
+               $stashInfo = (object)[
+                       'pstContent' => $pstContent,
+                       'output'     => $parserOutput,
+                       'timestamp'  => $timestamp,
+                       'edits'      => $user->getEditCount()
+               ];
+
+               return [ $stashInfo, $ttl, 'ok' ];
        }
 
        public function getAllowedParams() {
@@ -416,6 +349,9 @@ class ApiStashEdit extends ApiBase {
                                ApiBase::PARAM_TYPE => 'text',
                                ApiBase::PARAM_REQUIRED => true
                        ],
+                       'summary' => [
+                               ApiBase::PARAM_TYPE => 'string',
+                       ],
                        'contentmodel' => [
                                ApiBase::PARAM_TYPE => ContentHandler::getContentModels(),
                                ApiBase::PARAM_REQUIRED => true