Merge "Made runJobs.php wait for slave lag."
[lhc/web/wiklou.git] / includes / EditPage.php
index 4e3ea49..d42edd7 100644 (file)
@@ -165,6 +165,26 @@ class EditPage {
         */
        const EDITFORM_ID                  = 'editform';
 
+       /**
+        * Prefix of key for cookie used to pass post-edit state.
+        * The revision id edited is added after this
+        */
+       const POST_EDIT_COOKIE_KEY_PREFIX = 'PostEditRevision';
+
+       /**
+        * Duration of PostEdit cookie, in seconds.
+        * The cookie will be removed instantly if the JavaScript runs.
+        *
+        * Otherwise, though, we don't want the cookies to accumulate.
+        * RFC 2109 ( https://www.ietf.org/rfc/rfc2109.txt ) specifies a possible limit of only 20 cookies per domain.
+        * This still applies at least to some versions of IE without full updates:
+        * https://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx
+        *
+        * A value of 20 minutes should be enough to take into account slow loads and minor
+        * clock skew while still avoiding cookie accumulation when JavaScript is turned off.
+        */
+       const POST_EDIT_COOKIE_DURATION = 1200;
+
        /**
         * @var Article
         */
@@ -624,11 +644,8 @@ class EditPage {
                                wfProfileOut( get_class( $this ) . "::importContentFormData" );
                        }
 
-                       # Trim spaces on user supplied text
-                       $summary = trim( $request->getText( 'wpSummary' ) );
-
                        # Truncate for whole multibyte characters
-                       $this->summary = $wgContLang->truncate( $summary, 255 );
+                       $this->summary = $wgContLang->truncate( $request->getText( 'wpSummary' ), 255 );
 
                        # If the summary consists of a heading, e.g. '==Foobar==', extract the title from the
                        # header syntax, e.g. 'Foobar'. This is mainly an issue when we are using wpSummary for
@@ -1130,6 +1147,33 @@ class EditPage {
                return $this->mTokenOk;
        }
 
+       /**
+        * Sets post-edit cookie indicating the user just saved a particular revision.
+        *
+        * This uses a temporary cookie for each revision ID so separate saves will never
+        * interfere with each other.
+        *
+        * The cookie is deleted in the mediawiki.action.view.postEdit JS module after
+        * the redirect.  It must be clearable by JavaScript code, so it must not be
+        * marked HttpOnly. The JavaScript code converts the cookie to a wgPostEdit config
+        * variable.
+        *
+        * Since WebResponse::setcookie does not allow forcing HttpOnly for a single
+        * cookie, we have to use PHP's setcookie() directly.
+        *
+        * We use a path of '/' since wgCookiePath is not exposed to JS
+        *
+        * If the variable were set on the server, it would be cached, which is unwanted
+        * since the post-edit state should only apply to the load right after the save.
+        */
+       protected function setPostEditCookie() {
+               global $wgCookiePrefix, $wgCookieDomain;
+               $revisionId = $this->mArticle->getLatest();
+               $postEditKey = self::POST_EDIT_COOKIE_KEY_PREFIX . $revisionId;
+
+               setcookie( $wgCookiePrefix . $postEditKey, '1', time() + self::POST_EDIT_COOKIE_DURATION, '/', $wgCookieDomain );
+       }
+
        /**
         * Attempt submission
         * @throws UserBlockedError|ReadOnlyError|ThrottledError|PermissionsError
@@ -1145,6 +1189,7 @@ class EditPage {
                // FIXME: once the interface for internalAttemptSave() is made nicer, this should use the message in $status
                if ( $status->value == self::AS_SUCCESS_UPDATE || $status->value == self::AS_SUCCESS_NEW_ARTICLE ) {
                        $this->didSave = true;
+                       $this->setPostEditCookie();
                }
 
                switch ( $status->value ) {
@@ -1564,43 +1609,40 @@ class EditPage {
                                return $status;
                        }
 
-                       # Handle the user preference to force summaries here, but not for null edits
-                       if ( $this->section != 'new' && !$this->allowBlankSummary
-                               && !$content->equals( $this->getOriginalContent() )
-                               && !$content->isRedirect() ) # check if it's not a redirect
-                       {
-                               if ( md5( $this->summary ) == $this->autoSumm ) {
+                       if ( $this->section == 'new' ) {
+                               // Handle the user preference to force summaries here
+                               if ( !$this->allowBlankSummary && trim( $this->summary ) == '' ) {
                                        $this->missingSummary = true;
-                                       $status->fatal( 'missingsummary' );
+                                       $status->fatal( 'missingsummary' ); // or 'missingcommentheader' if $section == 'new'. Blegh
                                        $status->value = self::AS_SUMMARY_NEEDED;
                                        wfProfileOut( __METHOD__ );
                                        return $status;
                                }
-                       }
 
-                       # And a similar thing for new sections
-                       if ( $this->section == 'new' && !$this->allowBlankSummary ) {
-                               if ( trim( $this->summary ) == '' ) {
-                                       $this->missingSummary = true;
-                                       $status->fatal( 'missingsummary' ); // or 'missingcommentheader' if $section == 'new'. Blegh
-                                       $status->value = self::AS_SUMMARY_NEEDED;
+                               // Do not allow the user to post an empty comment
+                               if ( $this->textbox1 == '' ) {
+                                       $this->missingComment = true;
+                                       $status->fatal( 'missingcommenttext' );
+                                       $status->value = self::AS_TEXTBOX_EMPTY;
                                        wfProfileOut( __METHOD__ );
                                        return $status;
                                }
+                       } elseif ( !$this->allowBlankSummary
+                               && !$content->equals( $this->getOriginalContent() )
+                               && !$content->isRedirect()
+                               && md5( $this->summary ) == $this->autoSumm
+                       ) {
+                               $this->missingSummary = true;
+                               $status->fatal( 'missingsummary' );
+                               $status->value = self::AS_SUMMARY_NEEDED;
+                               wfProfileOut( __METHOD__ );
+                               return $status;
                        }
 
                        # All's well
                        wfProfileIn( __METHOD__ . '-sectionanchor' );
                        $sectionanchor = '';
                        if ( $this->section == 'new' ) {
-                               if ( $this->textbox1 == '' ) {
-                                       $this->missingComment = true;
-                                       $status->fatal( 'missingcommenttext' );
-                                       $status->value = self::AS_TEXTBOX_EMPTY;
-                                       wfProfileOut( __METHOD__ . '-sectionanchor' );
-                                       wfProfileOut( __METHOD__ );
-                                       return $status;
-                               }
                                if ( $this->sectiontitle !== '' ) {
                                        $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
                                        // If no edit summary was specified, create one automatically from the section
@@ -2453,6 +2495,8 @@ class EditPage {
         * @return String
         */
        protected function getSummaryPreview( $isSubjectPreview, $summary = "" ) {
+               // avoid spaces in preview, gets always trimmed on save
+               $summary = trim( $summary );
                if ( !$summary || ( !$this->preview && !$this->diff ) ) {
                        return "";
                }