(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
This commit is contained in:
Matthew Flaschen 2013-02-23 05:35:22 -05:00
parent 3f4e273a7b
commit 375687eddb
4 changed files with 64 additions and 0 deletions

View file

@ -767,6 +767,8 @@ class Article implements Page {
$this->showViewFooter();
$this->mPage->doViewUpdates( $user );
$outputPage->addModules( 'mediawiki.action.view.postEdit' );
wfProfileOut( __METHOD__ );
}

View 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 ) {

View 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',
),

View file

@ -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 ) );