r19529 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r19528‎ | r19529 | r19530 >
Date:21:05, 20 January 2007
Author:hashar
Status:old
Tags:
Comment:
Optional feature : 'Ajax show editors' based on an idea by Tim Starling
Merge from hashar's branch.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/AjaxFunctions.php (modified) (history)
  • /trunk/phase3/includes/AjaxHooks.php (added) (history)
  • /trunk/phase3/includes/AjaxHooks.php (added) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/EditPage.php (modified) (history)
  • /trunk/phase3/includes/Setup.php (modified) (history)
  • /trunk/phase3/index.php (modified) (history)
  • /trunk/phase3/languages/messages/MessagesEn.php (modified) (history)
  • /trunk/phase3/maintenance/archives/patch-editings.sql (added) (history)
  • /trunk/phase3/maintenance/archives/patch-editings.sql (added) (history)
  • /trunk/phase3/maintenance/updaters.inc (modified) (history)
  • /trunk/phase3/skins/common/ajaxshoweditors.js (added) (history)
  • /trunk/phase3/skins/common/ajaxshoweditors.js (added) (history)
  • /trunk/phase3/skins/common/ajaxwatch.js (modified) (history)
  • /trunk/phase3/skins/monobook/main.css (modified) (history)

Diff [purge]

Index: trunk/phase3/maintenance/archives/patch-editings.sql
@@ -0,0 +1,14 @@
 2+--
 3+-- Tracks people currently editing an article
 4+-- Enabled with $wgAjaxShowEditors = true;
 5+--
 6+
 7+CREATE TABLE /*$wgDBprefix*/editings (
 8+ `editings_page` int(8) NOT NULL,
 9+ `editings_user` varchar(255) NOT NULL,
 10+ `editings_started` char(14) NOT NULL,
 11+ `editings_touched` char(14) NOT NULL,
 12+ PRIMARY KEY (`editings_page`,`editings_user`),
 13+ KEY `editings_page` (`editings_page`)
 14+ KEY `editings_page_started` (`editings_page`,`editings_user`,`editings_started`)
 15+) TYPE=InnoDB;
Property changes on: trunk/phase3/maintenance/archives/patch-editings.sql
___________________________________________________________________
Name: svn:eol-style
116 + native
Index: trunk/phase3/maintenance/updaters.inc
@@ -30,6 +30,7 @@
3131 array( 'transcache', 'patch-transcache.sql' ),
3232 array( 'trackbacks', 'patch-trackbacks.sql' ),
3333 array( 'externallinks', 'patch-externallinks.sql' ),
 34+ array( 'editings', 'patch-editings.sql' ),
3435 array( 'job', 'patch-job.sql' ),
3536 array( 'langlinks', 'patch-langlinks.sql' ),
3637 array( 'querycache_info', 'patch-querycacheinfo.sql' ),
Index: trunk/phase3/skins/monobook/main.css
@@ -1574,6 +1574,27 @@
15751575 }
15761576 tr.sv-space td { display: none; }
15771577
 1578+
 1579+/* wgAjaxShowEditors */
 1580+
 1581+#ajax-se {
 1582+ border:1px solid #aaaaaa;
 1583+ margin: 0 0 1em 0;
 1584+ padding:0.15em;
 1585+ color : #000000;
 1586+ background-color: #F0F0F0;
 1587+}
 1588+
 1589+#ajax-se-title {
 1590+ font-size:small;
 1591+ display:inline;
 1592+ margin-right:1em;
 1593+}
 1594+
 1595+#ajax-se-editors {
 1596+ display:inline;
 1597+}
 1598+
15781599 /*
15791600 Table pager (e.g. Special:Imagelist)
15801601 - remove underlines from the navigation link
@@ -1615,4 +1636,4 @@
16161637 */
16171638 #toolbar { clear: both; }
16181639 .mw-plusminus-null { color: #aaa; }
1619 -.texvc { direction: ltr; unicode-bidi: embed; }
\ No newline at end of file
 1640+.texvc { direction: ltr; unicode-bidi: embed; }
Index: trunk/phase3/skins/common/ajaxwatch.js
@@ -124,4 +124,4 @@
125125 var supportsAjax = request ? true : false;
126126 delete request;
127127 return supportsAjax;
128 -}
\ No newline at end of file
 128+}
Index: trunk/phase3/skins/common/ajaxshoweditors.js
@@ -0,0 +1,62 @@
 2+var sajax_debug_mode = false;
 3+var canRefresh = null;
 4+var ShowEditorsCounting = false;
 5+var wgAjaxShowEditors = {} ;
 6+
 7+// The loader. Look at bottom for the sajax hook registration
 8+wgAjaxShowEditors.onLoad = function() {
 9+ var elEditors = document.getElementById( 'ajax-se' );
 10+ // wgAjaxShowEditors.refresh();
 11+ elEditors.onclick = function() { wgAjaxShowEditors.refresh(); } ;
 12+
 13+ var elTextArea = document.getElementById( 'wpTextbox1' );
 14+ elTextArea.onkeypress = function() { wgAjaxShowEditors.refresh(); } ;
 15+
 16+ wgAjaxShowEditors.allowRefresh();
 17+}
 18+
 19+
 20+// Ask for new data & update UI
 21+wgAjaxShowEditors.refresh = function() {
 22+ if( !canRefresh ) { return; }
 23+
 24+ // Disable new requests for 5 seconds
 25+ canRefresh = false;
 26+ setTimeout( 'wgAjaxShowEditors.allowRefresh()', 5000 );
 27+
 28+ // Load the editors list element, it will get rewrote
 29+ var elEditorsList = document.getElementById( 'ajax-se-editors' );
 30+
 31+ if( wgUserName == null ) {
 32+ wgUserName = '';
 33+ }
 34+
 35+ // Do the ajax call to the server
 36+ sajax_do_call( "wfAjaxShowEditors", [ wgArticleId, wgUserName ], elEditorsList );
 37+ if(!ShowEditorsCounting) {
 38+ wgAjaxShowEditors.countup();
 39+ }
 40+}
 41+
 42+wgAjaxShowEditors.countup = function() {
 43+ ShowEditorsCounting = true;
 44+
 45+ var elEditorsList = document.getElementById( 'ajax-se-editors' );
 46+ for(var i=0;i<elEditorsList.childNodes.length;i++) {
 47+ var item = elEditorsList.childNodes[i];
 48+ if (item.nodeName == 'SPAN') {
 49+ var value = parseInt( item.innerHTML );
 50+ value++;
 51+ item.innerHTML = value ;
 52+ }
 53+ }
 54+ setTimeout( "wgAjaxShowEditors.countup()", 1000 );
 55+}
 56+
 57+// callback to allow refresh
 58+wgAjaxShowEditors.allowRefresh = function() {
 59+ canRefresh = true;
 60+}
 61+
 62+// Register our initialization function.
 63+hookEvent( "load", wgAjaxShowEditors.onLoad);
Property changes on: trunk/phase3/skins/common/ajaxshoweditors.js
___________________________________________________________________
Name: svn:eol-style
164 + native
Index: trunk/phase3/includes/Setup.php
@@ -198,6 +198,7 @@
199199
200200 if ( $wgAjaxSearch ) $wgAjaxExportList[] = 'wfSajaxSearch';
201201 if ( $wgAjaxWatch ) $wgAjaxExportList[] = 'wfAjaxWatch';
 202+if ( $wgAjaxShowEditors ) $wgAjaxExportList[] = 'wfAjaxShowEditors';
202203
203204 wfSeedRandom();
204205
Index: trunk/phase3/includes/EditPage.php
@@ -1113,6 +1113,19 @@
11141114 $templates = ($this->preview || $this->section) ? $this->mPreviewTemplates : $this->mArticle->getUsedTemplates();
11151115 $formattedtemplates = $sk->formatTemplates( $templates, $this->preview, $this->section != '');
11161116
 1117+
 1118+ global $wgAjaxShowEditors ;
 1119+ if ( $wgAjaxShowEditors && isset( $this->mArticle )
 1120+ && isset( $this->mArticle->mRevision ) ) {
 1121+ global $wgJsMimeType, $wgStylePath, $wgStyleVersion;
 1122+ $wgOut->addScript( "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/ajaxshoweditors.js?$wgStyleVersion\"></script>\n" );
 1123+ $wgOut->addWikiText(
 1124+ '<div id="ajax-se"><p id="ajax-se-title">'.wfMsg('ajax-se-title').'</p>'
 1125+ . '<p id="ajax-se-editors">'. wfMsg('ajax-se-pending') . '</p>'
 1126+ . '</div>'
 1127+ );
 1128+ }
 1129+
11171130 global $wgUseMetadataEdit ;
11181131 if ( $wgUseMetadataEdit ) {
11191132 $metadata = $this->mMetaData ;
Index: trunk/phase3/includes/AjaxHooks.php
@@ -0,0 +1,29 @@
 2+<?php
 3+if( !defined( 'MEDIAWIKI' ) )
 4+ die( 1 );
 5+
 6+/**
 7+ $article: the article (object) saved
 8+ $user: the user (object) who saved the article
 9+ $text: the new article text
 10+ $summary: the article summary (comment)
 11+ $isminor: minor flag
 12+ $iswatch: watch flag
 13+ $section: section #
 14+*/
 15+function wfAjaxShowEditorsCleanup( $article, $user ) {
 16+ $articleId = $article->getID();
 17+ $userId = $user->getName();
 18+
 19+ $dbw =& wfGetDB(DB_MASTER);
 20+ $dbw->delete('editings',
 21+ array(
 22+ 'editings_page' => $articleId,
 23+ 'editings_user' => $userId,
 24+ ),
 25+ __METHOD__
 26+ );
 27+}
 28+
 29+$wgHooks['ArticleSaveComplete'][] = 'wfAjaxShowEditorsCleanup';
 30+?>
Property changes on: trunk/phase3/includes/AjaxHooks.php
___________________________________________________________________
Name: svn:eol-style
131 + native
Index: trunk/phase3/includes/AjaxFunctions.php
@@ -168,4 +168,102 @@
169169
170170 return $watch ? '<w#>' : '<u#>';
171171 }
 172+
 173+/**
 174+ * Return a list of Editors currently editing the article.
 175+ * Based on an idea by Tim Starling.
 176+ *
 177+ * @author Ashar Voultoiz <hashar@altern.org>
 178+ * @author Tim Starling
 179+ */
 180+function wfAjaxShowEditors( $articleId, $username ) {
 181+ global $wgOut;
 182+ $articleId = intval($articleId);
 183+
 184+ // Validate request
 185+ $title = Title::newFromID( $articleId );
 186+ if( !($title) ) { return 'ERR: page id invalid'; }
 187+
 188+ $user = User::newFromSession() ;
 189+ if( !$user ) { return 'ERR: user invalid'; }
 190+
 191+ $username = $user->getName();
 192+ if( !( $user->isLoggedIn() or User::isIP( $username ) ) ) { return 'ERR: user not found'; }
 193+
 194+
 195+ // When did the user started editing ?
 196+ $dbr =& wfGetDB(DB_SLAVE);
 197+ $userStarted = $dbr->selectField( 'editings',
 198+ 'editings_started',
 199+ array(
 200+ 'editings_user' => $username,
 201+ 'editings_page' => $title->getArticleID(),
 202+ ),
 203+ __METHOD__
 204+ );
 205+
 206+ // He just started editing, assume NOW
 207+ if(!$userStarted) { $userStarted = $dbr->timestamp(); }
 208+
 209+ # Either create a new entry or update the touched timestamp.
 210+ # This is done using a unique index on the database :
 211+ # `editings_page_started` (`editings_page`,`editings_user`,`editings_started`)
 212+
 213+ $dbw =& wfGetDB(DB_MASTER);
 214+ $dbw->replace( 'editings',
 215+ array( 'editings_page', 'editings_user', 'editings_started' ),
 216+ array(
 217+ 'editings_page' => $title->getArticleID() ,
 218+ 'editings_user' => $username,
 219+ 'editings_started' => $userStarted ,
 220+ 'editings_touched' => $dbw->timestamp(),
 221+ ), __METHOD__
 222+ );
 223+
 224+ // Now we get the list of all watching users
 225+ $dbr = & wfGetDB(DB_SLAVE);
 226+ $res = $dbr->select( 'editings',
 227+ array( 'editings_user','editings_started','editings_touched' ),
 228+ array( 'editings_page' => $title->getArticleID() ),
 229+ __METHOD__
 230+ );
 231+
 232+ $l = new Linker();
 233+
 234+ $wikitext = '';
 235+ $unix_now = wfTimestamp(TS_UNIX);
 236+ $first = 1;
 237+ while( $editor = $dbr->fetchObject( $res ) ) {
 238+
 239+ // Check idling time
 240+ $idle = $unix_now - wfTimestamp( TS_UNIX, $editor->editings_touched );
 241+
 242+ global $wgAjaxShowEditorsTimeout ;
 243+ if( $idle >= $wgAjaxShowEditorsTimeout ) {
 244+ $dbw->delete('editings',
 245+ array(
 246+ 'editings_page' => $title->getArticleID(),
 247+ 'editings_user' => $editor->editings_user,
 248+ ),
 249+ __METHOD__
 250+ );
 251+ continue; // we will not show the user
 252+ }
 253+
 254+ if( $first ) { $first = 0; }
 255+ else { $wikitext .= ' ~ '; }
 256+
 257+ $since = wfTimestamp( TS_DB, $editor->editings_started );
 258+ $wikitext .= $since;
 259+
 260+ $wikitext .= ' ' . $l->makeLinkObj(
 261+ Title::makeTitle( NS_USER, $editor->editings_user ),
 262+ $editor->editings_user
 263+ );
 264+
 265+
 266+ $wikitext .= ' ' . wfMsg( 'ajax-se-idling', '<span>'.$idle.'</span>' );
 267+ }
 268+ return $wikitext ;
 269+}
172270 ?>
Index: trunk/phase3/includes/DefaultSettings.php
@@ -1109,7 +1109,7 @@
11101110 * to ensure that client-side caches don't keep obsolete copies of global
11111111 * styles.
11121112 */
1113 -$wgStyleVersion = '51';
 1113+$wgStyleVersion = '52';
11141114
11151115
11161116 # Server-side caching:
@@ -2351,6 +2351,15 @@
23522352 $wgAjaxWatch = false;
23532353
23542354 /**
 2355+ * Let you show other peoples editing an article.
 2356+ */
 2357+$wgAjaxShowEditors = false;
 2358+/**
 2359+ * Number of seconds before an user is considered as no more editing
 2360+ */
 2361+$wgAjaxShowEditorsTimeout = 60;
 2362+
 2363+/**
23552364 * Allow DISPLAYTITLE to change title display
23562365 */
23572366 $wgAllowDisplayTitle = false ;
Index: trunk/phase3/index.php
@@ -22,13 +22,17 @@
2323 #
2424 # Send Ajax requests to the Ajax dispatcher.
2525 #
26 -if ( $wgUseAjax && $action == 'ajax' ) {
27 - require_once( $IP . '/includes/AjaxDispatcher.php' );
 26+if ( $wgUseAjax ) {
 27+ if( $action == 'ajax' ) {
 28+ require_once( $IP . '/includes/AjaxDispatcher.php' );
2829
29 - $dispatcher = new AjaxDispatcher();
30 - $dispatcher->performAction();
31 - $mediaWiki->restInPeace( $wgLoadBalancer );
32 - exit;
 30+ $dispatcher = new AjaxDispatcher();
 31+ $dispatcher->performAction();
 32+ $mediaWiki->restInPeace( $wgLoadBalancer );
 33+ exit;
 34+ } else {
 35+ require_once( $IP . '/includes/AjaxHooks.php' );
 36+ }
3337 }
3438
3539
Index: trunk/phase3/languages/messages/MessagesEn.php
@@ -2759,6 +2759,11 @@
27602760 'size-megabytes' => '$1 MB',
27612761 'size-gigabytes' => '$1 GB',
27622762
 2763+# Ajax show editors
 2764+'ajax-se-title' => 'Currently editing:',
 2765+'ajax-se-pending' => 'pending refresh ... (click this box or start editing)',
 2766+'ajax-se-idling' => '($1s ago)',
 2767+
27632768 );
27642769
27652770 ?>
Index: trunk/phase3/RELEASE-NOTES
@@ -28,6 +28,9 @@
2929
3030 == Major new features ==
3131
 32+$wgAjaxShowEditors will let your users see who else is editing the page
 33+they are currently editing.
 34+
3235 == Changes since 1.9 ==
3336
3437 * (bug 7292) Fix site statistics when moving pages in/out of content namespaces

Follow-up revisions

RevisionCommit summaryAuthorDate
r19545Revert r19529 ('ajax editors list'); per chat w/ hashar I recommend working o...brion03:14, 21 January 2007
r19555The 'Ajax show editors' based on an idea by Tim Starling. This is...hashar16:55, 21 January 2007