(bug 43270) Add wgPostEdit to show if user just saved this page
authorMatthew Flaschen <mflaschen@wikimedia.org>
Sat, 23 Feb 2013 10:35:22 +0000 (05:35 -0500)
committerMatthew Flaschen <mflaschen@wikimedia.org>
Mon, 25 Feb 2013 21:32:21 +0000 (16:32 -0500)
* Sets short-lived cookie in EditPage
* Adds JS module, 'mediawiki.action.view.postEdit', to all views to
  convert cookie to wgPostEdit.  This avoids caching the variable in the
  HTML.
* Based in part on PostEdit extension

Change-Id: Ie89507f8e98c365df9d93a7633223103b9025790

includes/Article.php
includes/EditPage.php
resources/Resources.php
resources/mediawiki.action/mediawiki.action.view.postEdit.js [new file with mode: 0644]

index ed9c305..812bbae 100644 (file)
@@ -767,6 +767,8 @@ class Article implements Page {
                $this->showViewFooter();
                $this->mPage->doViewUpdates( $user );
 
+               $outputPage->addModules( 'mediawiki.action.view.postEdit' );
+
                wfProfileOut( __METHOD__ );
        }
 
index 5434dab..c05d6e5 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
         */
@@ -1127,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
@@ -1142,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 ) {
index 51bf05f..a0cefe9 100644 (file)
@@ -735,6 +735,10 @@ return array(
                        'metadata-collapse',
                ),
        ),
+       'mediawiki.action.view.postEdit' => array(
+               'scripts' => 'resources/mediawiki.action/mediawiki.action.view.postEdit.js',
+               'dependencies' => 'jquery.cookie'
+       ),
        'mediawiki.action.view.rightClickEdit' => array(
                'scripts' => 'resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js',
        ),
diff --git a/resources/mediawiki.action/mediawiki.action.view.postEdit.js b/resources/mediawiki.action/mediawiki.action.view.postEdit.js
new file mode 100644 (file)
index 0000000..c70791c
--- /dev/null
@@ -0,0 +1,10 @@
+( function ( mw, $ ) {
+       // Matches EditPage::POST_EDIT_COOKIE_KEY_PREFIX
+       var cookieKey = mw.config.get( 'wgCookiePrefix' ) + 'PostEditRevision' + mw.config.get( 'wgCurRevisionId' );
+
+       if ( $.cookie( cookieKey ) === '1' ) {
+               // We just saved this page
+               $.cookie( cookieKey, null, { path: '/' } );
+               mw.config.set( 'wgPostEdit', true );
+       }
+} ( mediaWiki, jQuery ) );