MediaWiki r18598 - Code Review

Jump to: navigation, search
Repository:MediaWiki
Revision:r18597‎ | r18598 (on ViewVC)‎ | r18599 >
Date:23:53, 26 December 2006
Author:simetrical
Status:old
Tags:
Comment:
(bug 7169) Use Ajax to watch/unwatch articles. Patch by Dan Li with some modification by me.
Modified paths:

Diff [purge]

Index: trunk/phase3/skins/common/ajaxwatch.js
@@ -0,0 +1,127 @@
 2+// dependencies:
 3+// * ajax.js:
 4+ /*extern sajax_init_object, sajax_do_call */
 5+// * wikibits.js:
 6+ /*extern changeText, akeytt, hookEvent */
 7+
 8+// These should have been initialized in the generated js
 9+/*extern wgAjaxWatch, wgArticleId */
 10+
 11+if(typeof wgAjaxWatch === "undefined" || !wgAjaxWatch) {
 12+ var wgAjaxWatch = {
 13+ watchMsg: "Watch",
 14+ unwatchMsg: "Unwatch",
 15+ watchingMsg: "Watching...",
 16+ unwatchingMsg: "Unwatching..."
 17+ };
 18+}
 19+
 20+wgAjaxWatch.supported = true; // supported on current page and by browser
 21+wgAjaxWatch.watching = false; // currently watching page
 22+wgAjaxWatch.inprogress = false; // ajax request in progress
 23+wgAjaxWatch.timeoutID = null; // see wgAjaxWatch.ajaxCall
 24+wgAjaxWatch.watchLink1 = null; // "watch"/"unwatch" link
 25+wgAjaxWatch.watchLink2 = null; // second one, for (some?) non-Monobook-based
 26+wgAjaxWatch.oldHref = null; // url for action=watch/action=unwatch
 27+
 28+wgAjaxWatch.setLinkText = function(newText) {
 29+ changeText(wgAjaxWatch.watchLink1, newText);
 30+ if (wgAjaxWatch.watchLink2) {
 31+ changeText(wgAjaxWatch.watchLink2, newText);
 32+ }
 33+};
 34+
 35+wgAjaxWatch.setLinkID = function(newId) {
 36+ wgAjaxWatch.watchLink1.id = newId;
 37+ akeytt(newId); // update tooltips for Monobook
 38+};
 39+
 40+wgAjaxWatch.ajaxCall = function() {
 41+ if(!wgAjaxWatch.supported || wgAjaxWatch.inprogress) {
 42+ return;
 43+ }
 44+ wgAjaxWatch.inprogress = true;
 45+ wgAjaxWatch.setLinkText(wgAjaxWatch.watching ? wgAjaxWatch.unwatchingMsg : wgAjaxWatch.watchingMsg);
 46+ sajax_do_call("wfAjaxWatch", [wgArticleId, (wgAjaxWatch.watching ? "u" : "w")], wgAjaxWatch.processResult);
 47+ // if the request isn't done in 10 seconds, allow user to try again
 48+ wgAjaxWatch.timeoutID = window.setTimeout(function() { wgAjaxWatch.inprogress = false; }, 10000);
 49+ return;
 50+};
 51+
 52+wgAjaxWatch.processResult = function(request) {
 53+ if(!wgAjaxWatch.supported) {
 54+ return;
 55+ }
 56+ var response = request.responseText;
 57+ if(response == "<err#>") {
 58+ window.location.href = wgAjaxWatch.oldHref;
 59+ return;
 60+ } else if(response == "<w#>") {
 61+ wgAjaxWatch.watching = true;
 62+ wgAjaxWatch.setLinkText(wgAjaxWatch.unwatchMsg);
 63+ wgAjaxWatch.setLinkID("ca-unwatch");
 64+ wgAjaxWatch.oldHref = wgAjaxWatch.oldHref.replace(/action=watch/, "action=unwatch");
 65+ } else if(response == "<u#>") {
 66+ wgAjaxWatch.watching = false;
 67+ wgAjaxWatch.setLinkText(wgAjaxWatch.watchMsg);
 68+ wgAjaxWatch.setLinkID("ca-watch");
 69+ wgAjaxWatch.oldHref = wgAjaxWatch.oldHref.replace(/action=unwatch/, "action=watch");
 70+ }
 71+ wgAjaxWatch.inprogress = false;
 72+ if(wgAjaxWatch.timeoutID) {
 73+ window.clearTimeout(wgAjaxWatch.timeoutID);
 74+ }
 75+ return;
 76+};
 77+
 78+wgAjaxWatch.onLoad = function() {
 79+ var el1 = document.getElementById("ca-unwatch");
 80+ var el2 = null;
 81+ if (!el1) {
 82+ el1 = document.getElementById("mw-unwatch-link1");
 83+ el2 = document.getElementById("mw-unwatch-link2");
 84+ }
 85+ if(el1) {
 86+ wgAjaxWatch.watching = true;
 87+ } else {
 88+ wgAjaxWatch.watching = false;
 89+ el1 = document.getElementById("ca-watch");
 90+ if (!el1) {
 91+ el1 = document.getElementById("mw-watch-link1");
 92+ el2 = document.getElementById("mw-watch-link2");
 93+ }
 94+ if(!el1) {
 95+ wgAjaxWatch.supported = false;
 96+ return;
 97+ }
 98+ }
 99+
 100+ if(!wfSupportsAjax()) {
 101+ wgAjaxWatch.supported = false;
 102+ return;
 103+ }
 104+
 105+ // The id can be either for the parent (Monobook-based) or the element
 106+ // itself (non-Monobook)
 107+ wgAjaxWatch.watchLink1 = el1.tagName.toLowerCase() == "a" ? el1 : el1.firstChild;
 108+ wgAjaxWatch.watchLink2 = el2 ? el2 : null;
 109+
 110+ wgAjaxWatch.oldHref = wgAjaxWatch.watchLink1.getAttribute("href");
 111+ wgAjaxWatch.watchLink1.setAttribute("href", "javascript:wgAjaxWatch.ajaxCall()");
 112+ if (wgAjaxWatch.watchLink2) {
 113+ wgAjaxWatch.watchLink2.setAttribute("href", "javascript:wgAjaxWatch.ajaxCall()");
 114+ }
 115+ return;
 116+};
 117+
 118+hookEvent("load", wgAjaxWatch.onLoad);
 119+
 120+/**
 121+ * @return boolean whether the browser supports XMLHttpRequest
 122+ */
 123+function wfSupportsAjax() {
 124+ var request = sajax_init_object();
 125+ var supportsAjax = request ? true : false;
 126+ delete request;
 127+ return supportsAjax;
 128+}
\ No newline at end of file
Property changes on: trunk/phase3/skins/common/ajaxwatch.js
___________________________________________________________________
Name: svn:eol-style
1129 + native
Index: trunk/phase3/skins/common/wikibits.js
@@ -473,11 +473,16 @@
474474 }
475475 }
476476
477 -function akeytt() {
 477+/**
 478+ * Set up accesskeys/tooltips. If doId is specified, only set up for that id.
 479+ *
 480+ * @param mixed doId string or null
 481+ */
 482+function akeytt( doId ) {
478483 if (typeof ta == "undefined" || !ta) {
479484 return;
480485 }
481 -
 486+
482487 var pref;
483488 if (is_safari || navigator.userAgent.toLowerCase().indexOf('mac') + 1
484489 || navigator.userAgent.toLowerCase().indexOf('konqueror') + 1 ) {
@@ -492,6 +497,10 @@
493498 pref = 'alt-';
494499 }
495500
 501+ if ( doId ) {
 502+ ta = [ta[doId]];
 503+ }
 504+
496505 for (var id in ta) {
497506 var n = document.getElementById(id);
498507 if (n) {
@@ -881,7 +890,7 @@
882891 histrowinit();
883892 unhidetzbutton();
884893 tabbedprefs();
885 - akeytt();
 894+ akeytt( null );
886895 scrollEditBox();
887896 setupCheckboxShiftClick();
888897 sortableTables();
Index: trunk/phase3/includes/AjaxDispatcher.php
@@ -15,7 +15,7 @@
1616 var $args;
1717
1818 function AjaxDispatcher() {
19 - wfProfileIn( 'AjaxDispatcher::AjaxDispatcher' );
 19+ wfProfileIn( __METHOD__ );
2020
2121 $this->mode = "";
2222
@@ -42,7 +42,7 @@
4343 $this->args = array();
4444 }
4545 }
46 - wfProfileOut( 'AjaxDispatcher::AjaxDispatcher' );
 46+ wfProfileOut( __METHOD__ );
4747 }
4848
4949 function performAction() {
@@ -51,7 +51,7 @@
5252 if ( empty( $this->mode ) ) {
5353 return;
5454 }
55 - wfProfileIn( 'AjaxDispatcher::performAction' );
 55+ wfProfileIn( __METHOD__ );
5656
5757 if (! in_array( $this->func_name, $wgAjaxExportList ) ) {
5858 header( 'Status: 400 Bad Request', true, 400 );
@@ -72,7 +72,7 @@
7373 $result->sendHeaders();
7474 $result->printText();
7575 }
76 -
 76+
7777 } catch (Exception $e) {
7878 if (!headers_sent()) {
7979 header( 'Status: 500 Internal Error', true, 500 );
@@ -83,7 +83,7 @@
8484 }
8585 }
8686
87 - wfProfileOut( 'AjaxDispatcher::performAction' );
 87+ wfProfileOut( __METHOD__ );
8888 $wgOut = null;
8989 }
9090 }
Index: trunk/phase3/includes/Setup.php
@@ -171,6 +171,7 @@
172172 $wgPostCommitUpdateList = array();
173173
174174 if ( $wgAjaxSearch ) $wgAjaxExportList[] = 'wfSajaxSearch';
 175+if ( $wgAjaxWatch ) $wgAjaxExportList[] = 'wfAjaxWatch';
175176
176177 wfSeedRandom();
177178
Index: trunk/phase3/includes/OutputPage.php
@@ -524,8 +524,8 @@
525525 public function output() {
526526 global $wgUser, $wgOutputEncoding, $wgRequest;
527527 global $wgContLanguageCode, $wgDebugRedirects, $wgMimeType;
528 - global $wgJsMimeType, $wgStylePath, $wgUseAjax, $wgAjaxSearch, $wgServer;
529 - global $wgStyleVersion;
 528+ global $wgJsMimeType, $wgStylePath, $wgUseAjax, $wgAjaxSearch, $wgAjaxWatch;
 529+ global $wgServer, $wgStyleVersion;
530530
531531 if( $this->mDoNothing ){
532532 return;
@@ -536,11 +536,14 @@
537537
538538 if ( $wgUseAjax ) {
539539 $this->addScript( "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/ajax.js?$wgStyleVersion\"></script>\n" );
540 - }
 540+ if( $wgAjaxSearch ) {
 541+ $this->addScript( "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/ajaxsearch.js\"></script>\n" );
 542+ $this->addScript( "<script type=\"{$wgJsMimeType}\">hookEvent(\"load\", sajax_onload);</script>\n" );
 543+ }
541544
542 - if ( $wgUseAjax && $wgAjaxSearch ) {
543 - $this->addScript( "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/ajaxsearch.js?$wgStyleVersion\"></script>\n" );
544 - $this->addScript( "<script type=\"{$wgJsMimeType}\">hookEvent(\"load\", sajax_onload);</script>\n" );
 545+ if( $wgAjaxWatch && $wgUser->isLoggedIn() ) {
 546+ $this->addScript( "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/ajaxwatch.js\"></script>\n" );
 547+ }
545548 }
546549
547550 if ( '' != $this->mRedirect ) {
Index: trunk/phase3/includes/AjaxFunctions.php
@@ -129,4 +129,43 @@
130130 return $response;
131131 }
132132
 133+/**
 134+ * Called for AJAX watch/unwatch requests.
 135+ * @param $pageID Integer ID of the page to be watched/unwatched
 136+ * @param $watch String 'w' to watch, 'u' to unwatch
 137+ * @return String '<w#>' or '<u#>' on successful watch or unwatch, respectively, or '<err#>' on error (invalid XML in case we want to add HTML sometime)
 138+ */
 139+function wfAjaxWatch($pageID, $watch) {
 140+ if(wfReadOnly())
 141+ return '<err#>'; // redirect to action=(un)watch, which will display the database lock message
 142+
 143+ if(('w' !== $watch && 'u' !== $watch) || !is_numeric($pageID))
 144+ return '<err#>';
 145+ $watch = 'w' === $watch;
 146+ $pageID = intval($pageID);
 147+
 148+ $title = Title::newFromID($pageID);
 149+ if(!$title)
 150+ return '<err#>';
 151+ $article = new Article($title);
 152+ $watching = $title->userIsWatching();
 153+
 154+ if($watch) {
 155+ if(!$watching) {
 156+ $dbw =& wfGetDB(DB_MASTER);
 157+ $dbw->begin();
 158+ $article->doWatch();
 159+ $dbw->commit();
 160+ }
 161+ } else {
 162+ if($watching) {
 163+ $dbw =& wfGetDB(DB_MASTER);
 164+ $dbw->begin();
 165+ $article->doUnwatch();
 166+ $dbw->commit();
 167+ }
 168+ }
 169+
 170+ return $watch ? '<w#>' : '<u#>';
 171+}
133172 ?>
Index: trunk/phase3/includes/DefaultSettings.php
@@ -1042,7 +1042,7 @@
10431043 * to ensure that client-side caches don't keep obsolete copies of global
10441044 * styles.
10451045 */
1046 -$wgStyleVersion = '37';
 1046+$wgStyleVersion = '38';
10471047
10481048
10491049 # Server-side caching:
@@ -2254,6 +2254,13 @@
22552255 $wgAjaxExportList = array( );
22562256
22572257 /**
 2258+ * Enable watching/unwatching pages using AJAX.
 2259+ * Requires $wgUseAjax to be true too.
 2260+ * Causes wfAjaxWatch to be added to $wgAjaxExportList
 2261+ */
 2262+$wgAjaxWatch = false;
 2263+
 2264+/**
22582265 * Allow DISPLAYTITLE to change title display
22592266 */
22602267 $wgAllowDisplayTitle = false ;
Index: trunk/phase3/includes/Skin.php
@@ -23,6 +23,7 @@
2424 var $rc_cache ; # Cache for Enhanced Recent Changes
2525 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
2626 var $rcMoveIndex;
 27+ var $mWatchLinkNum = 0; // Appended to end of watch link id's
2728 /**#@-*/
2829
2930 /** Constructor, call parent constructor */
@@ -392,7 +393,7 @@
393394 */
394395 function getUserJs() {
395396 $fname = 'Skin::getUserJs';
396 - wfProfileIn( $fname );
 397+ wfProfileIn( __METHOD__ );
397398
398399 global $wgStylePath;
399400 $s = "/* generated javascript */\n";
@@ -403,7 +404,20 @@
404405 $s .= $commonJs;
405406 }
406407
407 - wfProfileOut( $fname );
 408+ global $wgUseAjax, $wgAjaxWatch;
 409+ if($wgUseAjax && $wgAjaxWatch) {
 410+ $s .= "
 411+
 412+/* AJAX (un)watch (see /skins/common/ajaxwatch.js) */
 413+var wgAjaxWatch = {
 414+ watchMsg: '". str_replace( array("'", "\n"), array("\\'", ' '), wfMsgExt( 'watch', array() ) )."',
 415+ unwatchMsg: '". str_replace( array("'", "\n"), array("\\'", ' '), wfMsgExt( 'unwatch', array() ) )."',
 416+ watchingMsg: '". str_replace( array("'", "\n"), array("\\'", ' '), wfMsgExt( 'watching', array() ) )."',
 417+ unwatchingMsg: '". str_replace( array("'", "\n"), array("\\'", ' '), wfMsgExt( 'unwatching', array() ) )."'
 418+};";
 419+ }
 420+
 421+ wfProfileOut( __METHOD__ );
408422 return $s;
409423 }
410424
@@ -1272,16 +1286,19 @@
12731287
12741288 function watchThisPage() {
12751289 global $wgOut, $wgTitle;
 1290+ ++$this->mWatchLinkNum;
12761291
12771292 if ( $wgOut->isArticleRelated() ) {
12781293 if ( $wgTitle->userIsWatching() ) {
12791294 $t = wfMsg( 'unwatchthispage' );
12801295 $q = 'action=unwatch';
 1296+ $id = "mw-unwatch-link".$this->mWatchLinkNum;
12811297 } else {
12821298 $t = wfMsg( 'watchthispage' );
12831299 $q = 'action=watch';
 1300+ $id = 'mw-watch-link'.$this->mWatchLinkNum;
12841301 }
1285 - $s = $this->makeKnownLinkObj( $wgTitle, $t, $q );
 1302+ $s = $this->makeKnownLinkObj( $wgTitle, $t, $q, '', '', " id=\"$id\"" );
12861303 } else {
12871304 $s = wfMsg( 'notanarticle' );
12881305 }
Index: trunk/phase3/languages/messages/MessagesEn.php
@@ -1633,6 +1633,9 @@
16341634 'wlhideshowown' => '$1 my edits',
16351635 'wlhideshowbots' => '$1 bot edits',
16361636 'wldone' => 'Done.',
 1637+# Displayed when you click the "watch" button and it's in the process of watching
 1638+'watching' => 'Watching...',
 1639+'unwatching' => 'Unwatching...',
16371640
16381641 'enotif_mailer' => '{{SITENAME}} Notification Mailer',
16391642 'enotif_reset' => 'Mark all pages visited',