From 375687eddb95b159f99f1826eeb6a8a6713bb10b Mon Sep 17 00:00:00 2001 From: Matthew Flaschen Date: Sat, 23 Feb 2013 05:35:22 -0500 Subject: [PATCH] (bug 43270) Add wgPostEdit to show if user just saved this page * 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 | 2 + includes/EditPage.php | 48 +++++++++++++++++++ resources/Resources.php | 4 ++ .../mediawiki.action.view.postEdit.js | 10 ++++ 4 files changed, 64 insertions(+) create mode 100644 resources/mediawiki.action/mediawiki.action.view.postEdit.js diff --git a/includes/Article.php b/includes/Article.php index ed9c305d4b..812bbae842 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -767,6 +767,8 @@ class Article implements Page { $this->showViewFooter(); $this->mPage->doViewUpdates( $user ); + $outputPage->addModules( 'mediawiki.action.view.postEdit' ); + wfProfileOut( __METHOD__ ); } diff --git a/includes/EditPage.php b/includes/EditPage.php index 5434dabd4f..c05d6e5db7 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -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 ) { diff --git a/resources/Resources.php b/resources/Resources.php index 51bf05f896..a0cefe9ad8 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -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 index 0000000000..c70791c36e --- /dev/null +++ b/resources/mediawiki.action/mediawiki.action.view.postEdit.js @@ -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 ) ); -- 2.20.1