r90033 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r90032‎ | r90033 | r90034 >
Date:03:41, 14 June 2011
Author:aaron
Status:resolved
Tags:
Comment:
*Added API to set "currently reviewing" flag for pages and diffs
*(bug 25295) Added "You are being advertised as reviewing" message to review form. Currently removes flag when user leaves the page or it times out. A [stop] button and/or heartbeats could also be used with the API (with minor tweaks).
*Added JS TODO note
Modified paths:
  • /trunk/extensions/FlaggedRevs/FlaggedRevs.php (modified) (history)
  • /trunk/extensions/FlaggedRevs/api/actions/ApiReviewActivity.php (added) (history)
  • /trunk/extensions/FlaggedRevs/dataclasses/FRUserActivity.php (modified) (history)
  • /trunk/extensions/FlaggedRevs/presentation/RevisionReviewFormUI.php (modified) (history)
  • /trunk/extensions/FlaggedRevs/presentation/language/RevisionReview.i18n.php (modified) (history)
  • /trunk/extensions/FlaggedRevs/presentation/modules/review.js (modified) (history)

Diff [purge]

Index: trunk/extensions/FlaggedRevs/FlaggedRevs.php
@@ -329,6 +329,9 @@
330330 # Page review module for API
331331 $wgAutoloadClasses['ApiReview'] = $apiActionDir . 'ApiReview.php';
332332 $wgAPIModules['review'] = 'ApiReview';
 333+# Page review activity module for API
 334+$wgAutoloadClasses['ApiReviewActivity'] = $apiActionDir . 'ApiReviewActivity.php';
 335+$wgAPIModules['reviewactivity'] = 'ApiReviewActivity';
333336 # Stability config module for API
334337 $wgAutoloadClasses['ApiStabilize'] = $apiActionDir . 'ApiStabilize.php';
335338 $wgAutoloadClasses['ApiStabilizeGeneral'] = $apiActionDir . 'ApiStabilize.php';
Index: trunk/extensions/FlaggedRevs/dataclasses/FRUserActivity.php
@@ -90,19 +90,25 @@
9191 * Clear the flag for who is reviewing a page
9292 * @param User $user
9393 * @param int $pageId
 94+ * @return bool flag unset
9495 */
9596 public static function clearUserReviewingPage( $user, $pageId ) {
9697 global $wgMemc;
9798 $key = wfMemcKey( 'flaggedrevs', 'userReviewingPage', $pageId );
9899 $wgMemc->lock( $key, 4 ); // 4 sec timeout
99100 $val = $wgMemc->get( $key );
 101+ $wasSet = false;
 102+
100103 if ( is_array( $val ) && count( $val ) == 2 ) { // flag set
101104 list( $u, $ts ) = $val;
102105 if ( $u === $user->getName() ) {
103106 $wgMemc->delete( $key );
 107+ $wasSet = true;
104108 }
105109 }
106110 $wgMemc->unlock( $key );
 111+
 112+ return $wasSet;
107113 }
108114
109115 /*
@@ -159,18 +165,24 @@
160166 * @param User $user
161167 * @param int $oldId
162168 * @param int $newId
 169+ * @return bool flag unset
163170 */
164171 public static function clearUserReviewingDiff( $user, $oldId, $newId ) {
165172 global $wgMemc;
166173 $key = wfMemcKey( 'flaggedrevs', 'userReviewingDiff', $oldId, $newId );
167174 $wgMemc->lock( $key, 4 ); // 4 sec timeout
168175 $val = $wgMemc->get( $key );
 176+ $wasSet = false;
 177+
169178 if ( is_array( $val ) && count( $val ) == 2 ) { // flag set
170179 list( $u, $ts ) = $val;
171180 if ( $u === $user->getName() ) {
172181 $wgMemc->delete( $key );
 182+ $wasSet = true;
173183 }
174184 }
175185 $wgMemc->unlock( $key );
 186+
 187+ return $wasSet;
176188 }
177189 }
Index: trunk/extensions/FlaggedRevs/api/actions/ApiReviewActivity.php
@@ -0,0 +1,147 @@
 2+<?php
 3+
 4+/*
 5+ * Created on June 13, 2011
 6+ *
 7+ * API module for MediaWiki's FlaggedRevs extension
 8+ *
 9+ * This program is free software; you can redistribute it and/or modify
 10+ * it under the terms of the GNU General Public License as published by
 11+ * the Free Software Foundation; either version 2 of the License, or
 12+ * (at your option) any later version.
 13+ *
 14+ * This program is distributed in the hope that it will be useful,
 15+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 17+ * GNU General Public License for more details.
 18+ *
 19+ * You should have received a copy of the GNU General Public License along
 20+ * with this program; if not, write to the Free Software Foundation, Inc.,
 21+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 22+ * http://www.gnu.org/copyleft/gpl.html
 23+ */
 24+
 25+/**
 26+ * API module to set the "currently reviewing" status of revisions
 27+ *
 28+ * @ingroup FlaggedRevs
 29+ */
 30+class ApiReviewActivity extends ApiBase {
 31+
 32+ /**
 33+ * This function does essentially the same as RevisionReview::AjaxReview,
 34+ * except that it generates the template and image parameters itself.
 35+ */
 36+ public function execute() {
 37+ global $wgUser;
 38+ $params = $this->extractRequestParams();
 39+ // Check basic permissions
 40+ if ( !$wgUser->isAllowed( 'review' ) ) {
 41+ $this->dieUsage( "You don't have the right to review revisions.",
 42+ 'permissiondenied' );
 43+ } elseif ( $wgUser->isBlocked( false ) ) {
 44+ $this->dieUsageMsg( array( 'blockedtext' ) );
 45+ }
 46+
 47+ $newRev = Revision::newFromId( $params['newid'] );
 48+ if ( !$newRev || !$newRev->getTitle() ) {
 49+ $this->dieUsage( "Cannot find a revision with the specified ID.", 'notarget' );
 50+ }
 51+ $title = $newRev->getTitle();
 52+
 53+ $fa = FlaggedPage::getTitleInstance( $title );
 54+ if ( !$fa->isReviewable() ) {
 55+ $this->dieUsage( "Provided page is not reviewable.", 'notreviewable' );
 56+ }
 57+
 58+ $status = false;
 59+ if ( $params['oldid'] ) { // changes
 60+ $oldRev = Revision::newFromId( $params['oldid'] );
 61+ if ( !$oldRev || $oldRev->getPage() != $newRev->getPage() ) {
 62+ $this->dieUsage( "Revisions do not belong to the same page.", 'notarget' );
 63+ }
 64+ // Mark as reviewing...
 65+ if ( $params['reviewing'] ) {
 66+ $status = FRUserActivity::setUserReviewingDiff(
 67+ $wgUser, $params['oldid'], $params['newid'] );
 68+ // Unmark as reviewing...
 69+ } else {
 70+ $status = FRUserActivity::clearUserReviewingDiff(
 71+ $wgUser, $params['oldid'], $params['newid'] );
 72+ }
 73+ } else {
 74+ // Mark as reviewing...
 75+ if ( $params['reviewing'] ) {
 76+ $status = FRUserActivity::setUserReviewingPage( $wgUser, $newRev->getPage() );
 77+ // Unmark as reviewing...
 78+ } else {
 79+ $status = FRUserActivity::clearUserReviewingPage( $wgUser, $newRev->getPage() );
 80+ }
 81+ }
 82+
 83+ # Success in setting flag...
 84+ if ( $status === true ) {
 85+ $this->getResult()->addValue(
 86+ null, $this->getModuleName(), array( 'result' => 'Success' ) );
 87+ # Failure...
 88+ } else {
 89+ $this->getResult()->addValue(
 90+ null, $this->getModuleName(), array( 'result' => 'Failure' ) );
 91+ }
 92+ }
 93+
 94+ public function mustBePosted() {
 95+ return true;
 96+ }
 97+
 98+ public function isWriteMode() {
 99+ return true;
 100+ }
 101+
 102+ public function getAllowedParams() {
 103+ return array(
 104+ 'oldid' => null,
 105+ 'newid' => null,
 106+ 'reviewing' => array( ApiBase::PARAM_TYPE => array( 0, 1 ) )
 107+ );
 108+ }
 109+
 110+ public function getParamDescription() {
 111+ return array(
 112+ 'oldid' => 'The old revision ID (for reviewing changes or pages)',
 113+ 'newid' => 'The new revision ID (for reviewing changes only)',
 114+ 'reviewing' => 'Whether to advertising as reviewing or no longer reviewing',
 115+ );
 116+ }
 117+
 118+ public function getDescription() {
 119+ return 'Advertise or de-advertise yourself as reviewing an unreviewed page or unreviewed changes';
 120+ }
 121+
 122+ public function getPossibleErrors() {
 123+ return array_merge( parent::getPossibleErrors(), array(
 124+ array( 'code' => 'notarget',
 125+ 'info' => 'Provided revision or page can not be found.' ),
 126+ array( 'code' => 'notreviewable',
 127+ 'info' => 'Provided page is not reviewable.' ),
 128+ array( 'code' => 'permissiondenied',
 129+ 'info' => 'Insufficient rights to set the activity flag.' ),
 130+ ) );
 131+ }
 132+
 133+ public function needsToken() {
 134+ return false;
 135+ }
 136+
 137+ public function getTokenSalt() {
 138+ return false;
 139+ }
 140+
 141+ protected function getExamples() {
 142+ return 'api.php?action=reviewactivity&pageid=12345&reviewing=1';
 143+ }
 144+
 145+ public function getVersion() {
 146+ return __CLASS__ . ': $Id$';
 147+ }
 148+}
Property changes on: trunk/extensions/FlaggedRevs/api/actions/ApiReviewActivity.php
___________________________________________________________________
Added: svn:eol-style
1149 + native
Added: svn:keywords
2150 + Id
Index: trunk/extensions/FlaggedRevs/presentation/language/RevisionReview.i18n.php
@@ -63,6 +63,8 @@
6464 'revreview-successful2' => '\'\'\'Revision of [[:$1|$1]] successfully unflagged.\'\'\'',
6565 'revreview-poss-conflict-p' => '\'\'\'Warning: [[User:$1|$1]] started reviewing this page on $2 at $3.\'\'\'',
6666 'revreview-poss-conflict-c' => '\'\'\'Warning: [[User:$1|$1]] started reviewing these changes on $2 at $3.\'\'\'',
 67+ 'revreview-adv-reviewing-p' => '\'\'\'Notice: You are being advertised as having started reviewing this page on $1 at $2.\'\'\'',
 68+ 'revreview-adv-reviewing-c' => '\'\'\'Notice: You are being advertised as having started reviewing these changes on $1 at $2.\'\'\'',
6769 'revreview-toolow' => '\'\'\'You must rate each of the attributes higher than "inadequate" in order for a revision to be considered reviewed.\'\'\'
6870
6971 To remove the review status of a revision, click "unaccept".
Index: trunk/extensions/FlaggedRevs/presentation/RevisionReviewFormUI.php
@@ -121,12 +121,22 @@
122122 } else {
123123 list( $u, $ts ) = FRUserActivity::getUserReviewingPage( $this->rev->getPage() );
124124 }
125 - if ( $u !== null && $u != $this->user->getName() ) {
126 - $msg = $priorRevId ? 'revreview-poss-conflict-c' : 'revreview-poss-conflict-p';
127 - $form .= '<p><span class="fr-under-review">' .
128 - wfMsgExt( $msg, 'parseinline',
129 - $u, $wgLang->date( $ts, true ), $wgLang->time( $ts, true ) ) .
130 - '</span></p>';
 125+ if ( $u !== null ) { // page under review...
 126+ $form .= '<p><span class="fr-under-review">';
 127+ if ( $u != $this->user->getName() ) { // by another user...
 128+ $msg = $priorRevId
 129+ ? 'revreview-poss-conflict-c'
 130+ : 'revreview-poss-conflict-p';
 131+ $form .= wfMsgExt( $msg, 'parseinline',
 132+ $u, $wgLang->date( $ts, true ), $wgLang->time( $ts, true ) );
 133+ } else { // by this user...
 134+ $msg = $priorRevId
 135+ ? 'revreview-adv-reviewing-c'
 136+ : 'revreview-adv-reviewing-p';
 137+ $form .= wfMsgExt( $msg, 'parseinline',
 138+ $wgLang->date( $ts, true ), $wgLang->time( $ts, true ) );
 139+ }
 140+ $form .= '</span></p>';
131141 }
132142
133143 if ( $disabled ) {
@@ -178,8 +188,8 @@
179189 # Hidden params
180190 $form .= Html::hidden( 'title', $reviewTitle->getPrefixedText() ) . "\n";
181191 $form .= Html::hidden( 'target', $article->getTitle()->getPrefixedDBKey() ) . "\n";
182 - $form .= Html::hidden( 'refid', $priorRevId ) . "\n";
183 - $form .= Html::hidden( 'oldid', $revId ) . "\n";
 192+ $form .= Html::hidden( 'refid', $priorRevId, array( 'id' => 'mw-fr-input-refid' ) ) . "\n";
 193+ $form .= Html::hidden( 'oldid', $revId, array( 'id' => 'mw-fr-input-oldid' ) ) . "\n";
184194 $form .= Html::hidden( 'action', 'submit' ) . "\n";
185195 $form .= Html::hidden( 'wpEditToken', $this->user->editToken() ) . "\n";
186196 $form .= Html::hidden( 'changetime', $reviewTime,
Index: trunk/extensions/FlaggedRevs/presentation/modules/review.js
@@ -217,6 +217,9 @@
218218 return false; // don't do normal non-AJAX submit
219219 },
220220
 221+ /*
 222+ * Update form elements after AJAX review.
 223+ */
221224 'updateReviewForm': function( form, response ) {
222225 var msg = response.substr(6); // remove <err#> or <suc#>
223226 // Read new "last change time" timestamp for conflict handling
@@ -313,6 +316,37 @@
314317 if( diffHeaderItems && response != '' ) {
315318 diffHeaderItems.innerHTML = response;
316319 }
 320+ },
 321+
 322+ /*
 323+ * Flag users as "no longer reviewing"
 324+ */
 325+ 'deadvertiseReviewing': function() {
 326+ var form = document.getElementById('mw-fr-reviewform');
 327+ if( form ) {
 328+ var oRevId = document.getElementById('mw-fr-input-refid').value;
 329+ var nRevId = document.getElementById('mw-fr-input-oldid').value;
 330+ } else if( location.href.indexOf('&reviewing=1') != -1 ) {
 331+ var oRevId = 0;
 332+ var nRevId = mw.config.get('wgCurRevisionId');
 333+ }
 334+ if ( nRevId > 0 ) {
 335+ // Send GET request via AJAX!
 336+ var call = jQuery.ajax({
 337+ url : wgScriptPath + '/api.php',
 338+ data : {
 339+ action : 'reviewactivity',
 340+ oldid : oRevId,
 341+ newid : nRevId,
 342+ reviewing : 0
 343+ },
 344+ type : "POST",
 345+ dataType: "html", // response type
 346+ timeout : 2500, // don't delay user exiting
 347+ async : false
 348+ });
 349+ }
 350+ return;
317351 }
318352 };
319353
@@ -320,3 +354,8 @@
321355 FlaggedRevsReview.maybeDisableAcceptButton();
322356 FlaggedRevsReview.updateRatingFormColors();
323357 FlaggedRevsReview.enableAjaxReview();
 358+
 359+// Flag users as "no longer reviewing" on navigate-away
 360+// @TODO: This doesn't handle a user having the same diff open twice,
 361+// closing one, but reviewing in the other very well...
 362+window.onbeforeunload = FlaggedRevsReview.deadvertiseReviewing;

Follow-up revisions

RevisionCommit summaryAuthorDate
r90052Tweaked r90033: Improved API param names. Also decreased deadvertiseReviewing...aaron14:57, 14 June 2011
r90100* Reduce the amount of reviewactivity API hits...aaron23:46, 14 June 2011
r90143FRUserActivity (r90033) improvements:...aaron20:39, 15 June 2011

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r84383* Moved "users watching"/"user currently reviewing" functions to FRUserActivi...aaron14:42, 20 March 2011

Status & tagging log