r46751 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r46750‎ | r46751 | r46752 >
Date:00:36, 3 February 2009
Author:tparscal
Status:ok
Tags:
Comment:
Lots of formatting changes in the source code. Moved some things in Draft to Drafts. Cleaned up JavaScript code a ton! Added new message durring saving.
Modified paths:
  • /trunk/extensions/Drafts/Drafts.classes.php (modified) (history)
  • /trunk/extensions/Drafts/Drafts.hooks.php (modified) (history)
  • /trunk/extensions/Drafts/Drafts.i18n.php (modified) (history)
  • /trunk/extensions/Drafts/Drafts.js (modified) (history)
  • /trunk/extensions/Drafts/Drafts.pages.php (modified) (history)
  • /trunk/extensions/Drafts/Drafts.php (modified) (history)

Diff [purge]

Index: trunk/extensions/Drafts/Drafts.classes.php
@@ -5,220 +5,47 @@
66 * @file
77 * @ingroup Extensions
88 */
9 -
10 -// Draft Class
11 -class Draft {
12 -
13 - /* Fields */
149
15 - private $_exists = false;
16 - private $_id;
17 - private $_token;
18 - private $_userID;
19 - private $_title;
20 - private $_section;
21 - private $_starttime;
22 - private $_edittime;
23 - private $_savetime;
24 - private $_scrolltop ;
25 - private $_text;
26 - private $_summary;
27 - private $_minoredit;
 10+abstract class Drafts {
2811
29 - /* Functions */
 12+ /* Static Functions */
3013
31 - public function __construct( $id = null, $autoload = true ) {
32 - // If an ID is a number the existence is actually checked on load
33 - // If an ID is false the existance is always false durring load
34 - $this->_id = $id;
35 -
36 - # Load automatically
37 - if ( $autoload ) {
38 - $this->load();
39 - }
40 - }
41 -
42 - private function load() {
 14+ public static function num(
 15+ &$title = null,
 16+ $userID = null
 17+ ) {
4318 global $wgUser;
44 -
45 - // Verify the ID has been set
46 - if ( $this->_id === null ) {
47 - return;
48 - }
49 -
50 - // Get db connection
51 - $dbw = wfGetDB( DB_MASTER );
52 -
53 - // Select drafts from the database matching ID - can be 0 or 1 results
54 - $result = $dbw->select( 'drafts',
55 - array( '*' ),
56 - array(
57 - 'draft_id' => (int) $this->_id,
58 - 'draft_user' => (int) $wgUser->getID()
59 - ),
60 - __METHOD__
61 - );
62 - if ( $result === false ) {
63 - return;
64 - }
65 -
66 - // Get the row
67 - $row = $dbw->fetchRow( $result );
68 - if ( !is_array( $row ) || count( $row ) == 0 ) {
69 - return;
70 - }
71 -
72 - // Synchronize data
73 - $this->_token = $row['draft_token'];
74 - $this->_title = Title::makeTitle( $row['draft_namespace'], $row['draft_title'] );
75 - $this->_section = $row['draft_section'];
76 - $this->_starttime = $row['draft_starttime'];
77 - $this->_edittime = $row['draft_edittime'];
78 - $this->_savetime = $row['draft_savetime'];
79 - $this->_scrolltop = $row['draft_scrolltop'];
80 - $this->_text = $row['draft_text'];
81 - $this->_summary = $row['draft_summary'];
82 - $this->_minoredit = $row['draft_minoredit'];
83 -
84 - // Update state
85 - $this->_exists = true;
86 -
87 - return;
88 - }
89 -
90 - public function save() {
91 - global $wgUser, $wgRequest;
92 -
93 - // Get db connection
94 - $dbw = wfGetDB( DB_MASTER );
95 - $dbw->begin();
96 -
97 - // Build data
98 - $data = array(
99 - 'draft_token' => (int) $this->getToken(),
100 - 'draft_user' => (int) $wgUser->getID(),
101 - 'draft_namespace' => (int) $this->_title->getNamespace(),
102 - 'draft_title' => (string) $this->_title->getDBKey(),
103 - 'draft_page' => (int) $this->_title->getArticleId(),
104 - 'draft_section' => $this->_section == '' ? null : (int) $this->_section,
105 - 'draft_starttime' => $dbw->timestamp( $this->_starttime ),
106 - 'draft_edittime' => $dbw->timestamp( $this->_edittime ),
107 - 'draft_savetime' => $dbw->timestamp( $this->_savetime ),
108 - 'draft_scrolltop' => (int) $this->_scrolltop,
109 - 'draft_text' => (string) $this->_text,
110 - 'draft_summary' => (string) $this->_summary,
111 - 'draft_minoredit' => (int) $this->_minoredit
112 - );
113 -
114 - // Save data
115 - if ( $this->_exists === true ) {
116 - $dbw->update( 'drafts',
117 - $data,
118 - array(
119 - 'draft_id' => (int) $this->_id,
120 - 'draft_user' => (int) $wgUser->getID()
121 - ),
122 - __METHOD__
123 - );
124 - } else {
125 - $existingRow = $dbw->selectField( 'drafts', 'draft_token',
126 - array(
127 - 'draft_namespace' => $data['draft_namespace'],
128 - 'draft_title' => $data['draft_title'],
129 - 'draft_user' => $data['draft_user'],
130 - 'draft_token' => $data['draft_token']
131 - ),
132 - __METHOD__
133 - );
134 -
135 - // Check if token has been used already for this article
136 - if ( $existingRow === false ) {
137 - $dbw->insert( 'drafts', $data, __METHOD__ );
138 - $this->_id = $dbw->insertId();
139 - // Update state
140 - $this->_exists = true;
141 - }
142 - }
143 -
144 - $dbw->commit();
145 -
146 - // Return success
147 - return true;
148 - }
149 -
150 - public function discard( $user = null ) {
151 - global $wgUser;
152 -
153 - // Use $wgUser as a fallback
154 - $user = $user === null ? $wgUser : $user;
155 -
156 - // Get db connection
157 - $dbw = wfGetDB( DB_MASTER );
158 -
159 - // Delete data
160 - $dbw->delete( 'drafts',
161 - array(
162 - 'draft_id' => $this->_id,
163 - // FIXME: ID is already a primary key
164 - 'draft_user' => $user->getID()
165 - ),
166 - __METHOD__
167 - );
168 -
169 - $this->_exists = false;
170 - }
171 -
172 - public static function newFromID( $id, $autoload = true ) {
173 - return new Draft( $id, $autoload );
174 - }
175 -
176 - public static function newFromRow( $row ) {
177 - $draft = new Draft( $row['draft_id'], false );
178 - $draft->setToken( $row['draft_token'] );
179 - $draft->setTitle( Title::makeTitle( $row['draft_namespace'], $row['draft_title'] ) );
180 - $draft->setSection( $row['draft_section'] );
181 - $draft->setStartTime( $row['draft_starttime'] );
182 - $draft->setEditTime( $row['draft_edittime'] );
183 - $draft->setSaveTime( $row['draft_savetime'] );
184 - $draft->setScrollTop( $row['draft_scrolltop'] );
185 - $draft->setText( $row['draft_text'] );
186 - $draft->setSummary( $row['draft_summary'] );
187 - $draft->setMinorEdit( $row['draft_minoredit'] );
188 - return $draft;
189 - }
190 -
191 - public static function countDrafts( &$title = null, $userID = null ) {
192 - global $wgUser;
193 -
194 - Draft::cleanDrafts();
195 -
196 - // Get db connection
 19+ // Removes expired drafts for a more accurate count
 20+ self::clean();
 21+ // Get database connection
19722 $dbr = wfGetDB( DB_SLAVE );
198 -
199 - // Build where clause
 23+ // Builds where clause
20024 $where = array();
 25+ // Checks if a specific title was given
20126 if ( $title !== null ) {
 27+ // Adds specific title to conditions
20228 $where['draft_namespace'] = $title->getNamespace();
20329 $where['draft_title'] = $title->getDBKey();
20430 }
 31+ // Checks if specific user was given
20532 if ( $userID !== null ) {
 33+ // Adds specific user to condition
20634 $where['draft_user'] = $userID;
20735 } else {
 36+ // Adds current user as condition
20837 $where['draft_user'] = $wgUser->getID();
20938 }
210 -
21139 // Get a list of matching drafts
21240 return $dbr->selectField( 'drafts', 'count(*)', $where, __METHOD__ );
21341 }
214 -
215 - public static function cleanDrafts() {
 42+
 43+ public static function clean() {
21644 global $egDraftsLifeSpan;
217 -
218 - // Get db connection
 45+ // Get database connection
21946 $dbw = wfGetDB( DB_MASTER );
220 -
221 - // Remove drafts that are more than $wgDraftsLifeSpan days old
 47+ // Sets cuttoff as age longer than $wgDraftsLifeSpan days old
22248 $cutoff = wfTimestamp( TS_UNIX ) - ( $egDraftsLifeSpan * 60 * 60 * 24 );
 49+ // Removes expired drafts from database
22350 $dbw->delete( 'drafts',
22451 array(
22552 'draft_savetime < ' . $dbw->addQuotes( $dbw->timestamp( $cutoff ) )
@@ -226,66 +53,78 @@
22754 __METHOD__
22855 );
22956 }
230 -
231 - public static function getDrafts( $title = null, $userID = null ) {
 57+
 58+ public static function get(
 59+ $title = null,
 60+ $userID = null
 61+ ) {
23262 global $wgUser;
233 -
234 - Draft::cleanDrafts();
235 -
236 - // Get db connection
 63+ // Removes expired drafts for a more accurate list
 64+ Drafts::clean();
 65+ // Gets database connection
23766 $dbw = wfGetDB( DB_MASTER );
238 -
239 - // Build where clause
 67+ // Builds where clause
24068 $where = array();
 69+ // Checks if specific title was given
24170 if ( $title !== null ) {
 71+ // Gets page id from title
24272 $pageId = $title->getArticleId();
 73+ // Checks if page id exists
24374 if ( $pageId ) {
 75+ // Adds specific page id to conditions
24476 $where['draft_page'] = $pageId;
24577 } else {
 78+ // Adds new page information to conditions
24679 $where['draft_page'] = 0; // page not created yet
24780 $where['draft_namespace'] = $title->getNamespace();
24881 $where['draft_title'] = $title->getDBKey();
24982 }
25083 }
 84+ // Checks if a specific user was given
25185 if ( $userID !== null ) {
 86+ // Adds specific user to conditions
25287 $where['draft_user'] = $userID;
25388 } else {
 89+ // Adds current user to conditions
25490 $where['draft_user'] = $wgUser->getID();
25591 }
256 -
257 - // Create an array of matching drafts
258 - $drafts = array();
 92+ // Gets matching drafts from database
25993 $result = $dbw->select( 'drafts', '*', $where, __METHOD__ );
26094 if ( $result ) {
 95+ // Creates an array of matching drafts
 96+ $drafts = array();
26197 while ( $row = $dbw->fetchRow( $result ) ) {
262 - // Add a new draft to the list from the row
 98+ // Adds a new draft to the list from the row
26399 $drafts[] = Draft::newFromRow( $row );
264100 }
265101 }
266 -
267 - // Return array of matching drafts
 102+ // Returns array of matching drafts or null id there were none
268103 return count( $drafts ) ? $drafts : null;
269104 }
270 -
271 - public static function listDrafts( &$title = null, $user = null ) {
 105+
 106+ public static function display(
 107+ &$title = null,
 108+ $user = null
 109+ ) {
272110 global $wgOut, $wgRequest, $wgUser, $wgLang;
273 -
274 - // Get draftID
 111+ // Gets draftID
275112 $currentDraft = Draft::newFromID( $wgRequest->getIntOrNull( 'draft' ) );
276 -
277113 // Output HTML for list of drafts
278 - $drafts = Draft::getDrafts( $title, $user );
 114+ $drafts = Drafts::get( $title, $user );
279115 if ( count( $drafts ) > 0 ) {
280116 global $egDraftsLifeSpan;
281 -
282117 // Internationalization
283118 wfLoadExtensionMessages( 'Drafts' );
284 -
285119 // Add a summary, on Special:Drafts only
286120 if( !$title || $title->getNamespace() == NS_SPECIAL ) {
287 - $wgOut->wrapWikiMsg( '<div class="mw-drafts-summary">$1</div>', array( 'drafts-view-summary', $wgLang->formatNum( $egDraftsLifeSpan ) ) );
 121+ $wgOut->wrapWikiMsg(
 122+ '<div class="mw-drafts-summary">$1</div>',
 123+ array(
 124+ 'drafts-view-summary',
 125+ $wgLang->formatNum( $egDraftsLifeSpan )
 126+ )
 127+ );
288128 }
289 -
290129 // Build XML
291130 $wgOut->addHTML(
292131 Xml::openElement( 'table',
@@ -320,15 +159,14 @@
321160 );
322161 $wgOut->addHTML( Xml::element( 'th' ) );
323162 $wgOut->addHTML( Xml::closeElement( 'tr' ) );
324 -
325163 // Add existing drafts for this page and user
326164 foreach ( $drafts as $draft ) {
327165 // Get article title text
328166 $htmlTitle = $draft->getTitle()->getEscapedText();
329 -
330167 // Build Article Load link
331 - $urlLoad = $draft->getTitle()->getFullUrl( 'action=edit&draft=' . urlencode( $draft->getID() ) );
332 -
 168+ $urlLoad = $draft->getTitle()->getFullUrl( 'action=edit&draft=' .
 169+ urlencode( $draft->getID() )
 170+ );
333171 // Build discard link
334172 $urlDiscard = sprintf( '%s?discard=%s&token=%s',
335173 SpecialPage::getTitleFor( 'Drafts' )->getFullUrl(),
@@ -336,27 +174,28 @@
337175 urlencode( $wgUser->editToken() )
338176 );
339177 // If in edit mode, return to editor
340 - if ( $wgRequest->getText( 'action' ) == 'edit' || $wgRequest->getText( 'action' ) == 'submit' ) {
 178+ if (
 179+ $wgRequest->getText( 'action' ) == 'edit' ||
 180+ $wgRequest->getText( 'action' ) == 'submit'
 181+ ) {
341182 $urlDiscard .= '&returnto=' . urlencode( 'edit' );
342183 }
343 -
344184 // Append section to titles and links
345185 if ( $draft->getSection() !== null ) {
346186 // Detect section name
347187 $lines = explode( "\n", $draft->getText() );
348 -
 188+
349189 // If there is any content in the section
350190 if ( count( $lines ) > 0 ) {
351191 $htmlTitle .= '#' . htmlspecialchars(
352192 trim( trim( substr( $lines[0], 0, 255 ), '=' ) )
353193 );
354194 }
355 -
356195 // Modify article link and title
357196 $urlLoad .= '&section=' . urlencode( $draft->getSection() );
358 - $urlDiscard .= '&section=' . urlencode( $draft->getSection() );
 197+ $urlDiscard .= '&section=' .
 198+ urlencode( $draft->getSection() );
359199 }
360 -
361200 // Build XML
362201 $wgOut->addHTML( Xml::openElement( 'tr' ) );
363202 $wgOut->addHTML(
@@ -371,7 +210,11 @@
372211 Xml::element( 'a',
373212 array(
374213 'href' => $urlLoad,
375 - 'style' => 'font-weight:' . ( $currentDraft->getID() == $draft->getID() ? 'bold' : 'normal' )
 214+ 'style' => 'font-weight:' .
 215+ (
 216+ $currentDraft->getID() == $draft->getID() ?
 217+ 'bold' : 'normal'
 218+ )
376219 ),
377220 $htmlTitle
378221 )
@@ -394,11 +237,15 @@
395238 )
396239 )
397240 );
 241+ $jsClick = "if( wgDraft.getState() !== 'unchanged' )" .
 242+ "return confirm('" .
 243+ Xml::escapeJsString( wfMsgHTML( 'drafts-view-warn' ) ) .
 244+ "')";
398245 $wgOut->addHTML(
399246 Xml::element( 'a',
400247 array(
401248 'href' => $urlDiscard,
402 - 'onclick' => "if( !wgAjaxSaveDraft.insync ) return confirm('" . Xml::escapeJsString( wfMsgHTML( 'drafts-view-warn' ) ) . "')"
 249+ 'onclick' => $jsClick
403250 ),
404251 wfMsg( 'drafts-view-discard' )
405252 )
@@ -407,102 +254,310 @@
408255 $wgOut->addHTML( Xml::closeElement( 'tr' ) );
409256 }
410257 $wgOut->addHTML( Xml::closeElement( 'table' ) );
411 -
412258 // Return number of drafts
413259 return count( $drafts );
414260 }
415261 return 0;
416262 }
417 -
 263+}
 264+
 265+class Draft {
 266+
 267+ /* Members */
 268+
 269+ private $exists = false;
 270+ private $id;
 271+ private $token;
 272+ private $userID;
 273+ private $title;
 274+ private $section;
 275+ private $starttime;
 276+ private $edittime;
 277+ private $savetime;
 278+ private $scrolltop ;
 279+ private $text;
 280+ private $summary;
 281+ private $minoredit;
 282+
 283+ /* Static Functions */
 284+
 285+ public static function newFromID(
 286+ $id,
 287+ $autoload = true
 288+ ) {
 289+ return new Draft( $id, $autoload );
 290+ }
 291+
 292+ public static function newFromRow(
 293+ $row
 294+ ) {
 295+ $draft = new Draft( $row['draft_id'], false );
 296+ $draft->setToken( $row['draft_token'] );
 297+ $draft->setTitle( Title::makeTitle( $row['draft_namespace'], $row['draft_title'] ) );
 298+ $draft->setSection( $row['draft_section'] );
 299+ $draft->setStartTime( $row['draft_starttime'] );
 300+ $draft->setEditTime( $row['draft_edittime'] );
 301+ $draft->setSaveTime( $row['draft_savetime'] );
 302+ $draft->setScrollTop( $row['draft_scrolltop'] );
 303+ $draft->setText( $row['draft_text'] );
 304+ $draft->setSummary( $row['draft_summary'] );
 305+ $draft->setMinorEdit( $row['draft_minoredit'] );
 306+ return $draft;
 307+ }
 308+
418309 public static function newToken() {
419310 return wfGenerateToken();
420311 }
421 -
422 - /* States */
 312+
 313+ /* Properties */
 314+
423315 public function exists() {
424 - return $this->_exists;
 316+ return $this->exists;
425317 }
426318
427 - /* Properties */
428 -
429319 public function getID() {
430 - return $this->_id;
 320+ return $this->id;
431321 }
432322
433 - public function setToken( $token ) {
434 - $this->_token = $token;
 323+ public function setToken(
 324+ $token
 325+ ) {
 326+ $this->token = $token;
435327 }
436328 public function getToken() {
437 - return $this->_token;
 329+ return $this->token;
438330 }
439331
440 - public function getUserID( $userID ) {
441 - $this->_userID = $userID;
 332+ public function getUserID(
 333+ $userID
 334+ ) {
 335+ $this->userID = $userID;
442336 }
443337 public function setUserID() {
444 - return $this->_userID;
 338+ return $this->userID;
445339 }
446340
447341 public function getTitle() {
448 - return $this->_title;
 342+ return $this->title;
449343 }
450 - public function setTitle( $title ) {
451 - $this->_title = $title;
 344+ public function setTitle(
 345+ $title
 346+ ) {
 347+ $this->title = $title;
452348 }
453349
454350 public function getSection() {
455 - return $this->_section;
 351+ return $this->section;
456352 }
457 - public function setSection( $section ) {
458 - $this->_section = $section;
 353+ public function setSection(
 354+ $section
 355+ ) {
 356+ $this->section = $section;
459357 }
460358
461359 public function getStartTime() {
462 - return $this->_starttime;
 360+ return $this->starttime;
463361 }
464 - public function setStartTime( $starttime ) {
465 - $this->_starttime = $starttime;
 362+ public function setStartTime(
 363+ $starttime
 364+ ) {
 365+ $this->starttime = $starttime;
466366 }
467367
468368 public function getEditTime() {
469 - return $this->_edittime;
 369+ return $this->edittime;
470370 }
471 - public function setEditTime( $edittime ) {
472 - $this->_edittime = $edittime;
 371+ public function setEditTime(
 372+ $edittime
 373+ ) {
 374+ $this->edittime = $edittime;
473375 }
474376
475377 public function getSaveTime() {
476 - return $this->_savetime;
 378+ return $this->savetime;
477379 }
478 - public function setSaveTime( $savetime ) {
479 - $this->_savetime = $savetime;
 380+ public function setSaveTime(
 381+ $savetime
 382+ ) {
 383+ $this->savetime = $savetime;
480384 }
481385
482386 public function getScrollTop() {
483 - return $this->_scrolltop;
 387+ return $this->scrolltop;
484388 }
485 - public function setScrollTop( $scrolltop ) {
486 - $this->_scrolltop = $scrolltop;
 389+ public function setScrollTop(
 390+ $scrolltop
 391+ ) {
 392+ $this->scrolltop = $scrolltop;
487393 }
488394
489395 public function getText() {
490 - return $this->_text;
 396+ return $this->text;
491397 }
492 - public function setText( $text ) {
493 - $this->_text = $text;
 398+ public function setText(
 399+ $text
 400+ ) {
 401+ $this->text = $text;
494402 }
495403
496404 public function getSummary() {
497 - return $this->_summary;
 405+ return $this->summary;
498406 }
499 - public function setSummary( $summary ) {
500 - $this->_summary = $summary;
 407+ public function setSummary(
 408+ $summary
 409+ ) {
 410+ $this->summary = $summary;
501411 }
502412
503413 public function getMinorEdit() {
504 - return $this->_minoredit;
 414+ return $this->minoredit;
505415 }
506 - public function setMinorEdit( $minoredit ) {
507 - $this->_minoredit = $minoredit;
 416+ public function setMinorEdit(
 417+ $minoredit
 418+ ) {
 419+ $this->minoredit = $minoredit;
508420 }
 421+
 422+ /* Functions */
 423+
 424+ public function __construct(
 425+ $id = null,
 426+ $autoload = true
 427+ ) {
 428+ // If an ID is a number the existence is actually checked on load
 429+ // If an ID is false the existance is always false durring load
 430+ $this->id = $id;
 431+ // Load automatically
 432+ if ( $autoload ) {
 433+ $this->load();
 434+ }
 435+ }
 436+
 437+ private function load() {
 438+ global $wgUser;
 439+ // Checks if the ID of the draft was set
 440+ if ( $this->id === null ) {
 441+ // Exists immediately
 442+ return;
 443+ }
 444+ // Gets database connection
 445+ $dbw = wfGetDB( DB_MASTER );
 446+ // Gets drafts for this article and user from database
 447+ $result = $dbw->select( 'drafts',
 448+ array( '*' ),
 449+ array(
 450+ 'draft_id' => (int) $this->id,
 451+ 'draft_user' => (int) $wgUser->getID()
 452+ ),
 453+ __METHOD__
 454+ );
 455+ // Checks if query returned any results
 456+ if ( $result === false ) {
 457+ // Exists immediately
 458+ return;
 459+ }
 460+ // Fetches the row of the draft from the result
 461+ $row = $dbw->fetchRow( $result );
 462+ // Checks if the row is not an array or is an empty array
 463+ if ( !is_array( $row ) || count( $row ) == 0 ) {
 464+ // Exists immediately
 465+ return;
 466+ }
 467+ // Synchronizes data
 468+ $this->token = $row['draft_token'];
 469+ $this->title = Title::makeTitle(
 470+ $row['draft_namespace'], $row['draft_title']
 471+ );
 472+ $this->section = $row['draft_section'];
 473+ $this->starttime = $row['draft_starttime'];
 474+ $this->edittime = $row['draft_edittime'];
 475+ $this->savetime = $row['draft_savetime'];
 476+ $this->scrolltop = $row['draft_scrolltop'];
 477+ $this->text = $row['draft_text'];
 478+ $this->summary = $row['draft_summary'];
 479+ $this->minoredit = $row['draft_minoredit'];
 480+ // Updates state
 481+ $this->exists = true;
 482+ }
 483+
 484+ public function save() {
 485+ global $wgUser, $wgRequest;
 486+ // Gets database connection
 487+ $dbw = wfGetDB( DB_MASTER );
 488+ $dbw->begin();
 489+ // Builds insert/update information
 490+ $data = array(
 491+ 'draft_token' => (int) $this->getToken(),
 492+ 'draft_user' => (int) $wgUser->getID(),
 493+ 'draft_namespace' => (int) $this->title->getNamespace(),
 494+ 'draft_title' => (string) $this->title->getDBKey(),
 495+ 'draft_page' => (int) $this->title->getArticleId(),
 496+ 'draft_section' =>
 497+ $this->section == '' ? null : (int) $this->section,
 498+ 'draft_starttime' => $dbw->timestamp( $this->starttime ),
 499+ 'draft_edittime' => $dbw->timestamp( $this->edittime ),
 500+ 'draft_savetime' => $dbw->timestamp( $this->savetime ),
 501+ 'draft_scrolltop' => (int) $this->scrolltop,
 502+ 'draft_text' => (string) $this->text,
 503+ 'draft_summary' => (string) $this->summary,
 504+ 'draft_minoredit' => (int) $this->minoredit
 505+ );
 506+ // Checks if draft already exists
 507+ if ( $this->exists === true ) {
 508+ // Updates draft information
 509+ $dbw->update( 'drafts',
 510+ $data,
 511+ array(
 512+ 'draft_id' => (int) $this->id,
 513+ 'draft_user' => (int) $wgUser->getID()
 514+ ),
 515+ __METHOD__
 516+ );
 517+ } else {
 518+ // Gets a draft token exists for the current user and article
 519+ $existingRow = $dbw->selectField( 'drafts', 'draft_token',
 520+ array(
 521+ 'draft_namespace' => $data['draft_namespace'],
 522+ 'draft_title' => $data['draft_title'],
 523+ 'draft_user' => $data['draft_user'],
 524+ 'draft_token' => $data['draft_token']
 525+ ),
 526+ __METHOD__
 527+ );
 528+ // Checks if token existed, meaning it has been used already for
 529+ // this article
 530+ if ( $existingRow === false ) {
 531+ // Inserts row in the database
 532+ $dbw->insert( 'drafts', $data, __METHOD__ );
 533+ // Gets the id of the newly inserted row
 534+ $this->id = $dbw->insertId();
 535+ // Updates state
 536+ $this->exists = true;
 537+ }
 538+ }
 539+ // Commits any processed changes
 540+ $dbw->commit();
 541+ // Returns success
 542+ return true;
 543+ }
 544+
 545+ public function discard(
 546+ $user = null
 547+ ) {
 548+ global $wgUser;
 549+ // Uses $wgUser as a fallback
 550+ $user = $user === null ? $wgUser : $user;
 551+ // Gets database connection
 552+ $dbw = wfGetDB( DB_MASTER );
 553+ // Deletes draft from database (verifying propper user to avoid hacking!)
 554+ $dbw->delete( 'drafts',
 555+ array(
 556+ 'draft_id' => $this->id,
 557+ 'draft_user' => $user->getID()
 558+ ),
 559+ __METHOD__
 560+ );
 561+ // Updates state
 562+ $this->exists = false;
 563+ }
509564 }
Index: trunk/extensions/Drafts/Drafts.i18n.php
@@ -29,6 +29,7 @@
3030 'drafts-save' => 'Save this as a draft',
3131 'drafts-save-save' => 'Save draft',
3232 'drafts-save-saved' => 'Saved',
 33+ 'drafts-save-saving' => 'Saving',
3334 'drafts-save-error' => 'Error saving draft',
3435 'tooltip-drafts-save' => 'Save as a draft',
3536 'accesskey-drafts-save' => 'g', # do not translate or duplicate this message to other languages
@@ -845,7 +846,7 @@
846847 'drafts-view-nonesaved' => 'Nie masz obecnie zapisanych żadnych wersji roboczych.',
847848 'drafts-view-notice' => 'Posiadasz $1 dla tej strony.',
848849 'drafts-view-notice-link' => '$1 {{PLURAL:$1|wersja robocza|wersje robocze|wersji roboczych}}',
849 - 'drafts-view-warn' => 'Opuszczenie tej strony spowoduje utratę wszystkich niezapisanych zmian w jej treści.
 850+ 'drafts-view-warn' => 'Opuszczenie tej strony spowoduje utratę wszystkich niezapisanych zmian w jej treści.
850851 Czy chcesz kontynuować?',
851852 'drafts-save' => 'Zapisz jako wersję roboczą',
852853 'drafts-save-save' => 'Zapisz wersję roboczą',
Index: trunk/extensions/Drafts/Drafts.pages.php
@@ -14,49 +14,46 @@
1515 public function __construct() {
1616 // Initialize special page
1717 SpecialPage::SpecialPage( 'Drafts' );
18 -
1918 // Internationalization
2019 wfLoadExtensionMessages( 'Drafts' );
2120 }
2221
2322 public function execute( $par ) {
2423 global $wgRequest, $wgOut, $wgUser;
25 -
2624 // Begin output
2725 $this->setHeaders();
28 -
2926 // Make sure the user is logged in
3027 if ( !$wgUser->isLoggedIn() ) {
3128 // If not, let them know they need to
3229 $wgOut->loginToUse();
33 -
3430 // Continue
3531 return true;
3632 }
37 -
3833 // Handle discarding
3934 $draft = Draft::newFromID( $wgRequest->getIntOrNull( 'discard' ) );
4035 if ( $draft->exists() ) {
4136 // Discard draft
4237 $draft->discard();
43 -
4438 // Redirect to the article editor or view if returnto was set
4539 $section = $wgRequest->getIntOrNull( 'section' );
4640 $urlSection = $section !== null ? "&section={$section}" : '';
4741 switch( $wgRequest->getText( 'returnto' ) ) {
4842 case 'edit':
4943 $title = Title::newFromDBKey( $draft->getTitle() );
50 - $wgOut->redirect( wfExpandURL( $title->getEditURL() . $urlSection ) );
 44+ $wgOut->redirect(
 45+ wfExpandURL( $title->getEditURL() . $urlSection )
 46+ );
5147 break;
5248 case 'view':
5349 $title = Title::newFromDBKey( $draft->getTitle() );
54 - $wgOut->redirect( wfExpandURL( $title->getFullURL() . $urlSection ) );
 50+ $wgOut->redirect(
 51+ wfExpandURL( $title->getFullURL() . $urlSection )
 52+ );
5553 break;
5654 }
5755 }
58 -
5956 // Show list of drafts, or a message that there are none
60 - if ( Draft::listDrafts() == 0 ) {
 57+ if ( Drafts::display() == 0 ) {
6158 $wgOut->addHTML( wfMsgHTML( 'drafts-view-nonesaved' ) );
6259 }
6360 }
Index: trunk/extensions/Drafts/Drafts.php
@@ -4,7 +4,7 @@
55 *
66 * @file
77 * @ingroup Extensions
8 - *
 8+ *
99 * This file contains the main include file for the Drafts extension of
1010 * MediaWiki.
1111 *
@@ -45,10 +45,15 @@
4646 // Use the value 0 to disable autosave
4747 $egDraftsAutoSaveWait = 120;
4848
 49+// Seconds to wait until giving up on a response from the server
 50+// Use the value 0 to disable autosave
 51+$egDraftsAutoSaveTimeout = 10;
 52+
4953 // Days to keep drafts around before automatic deletion
5054 $egDraftsLifeSpan = 30;
5155
5256 // Save and View components
 57+$wgAutoloadClasses['Drafts'] = $dir . 'Drafts.classes.php';
5358 $wgAutoloadClasses['Draft'] = $dir . 'Drafts.classes.php';
5459 $wgAutoloadClasses['DraftHooks'] = $dir . 'Drafts.hooks.php';
5560
@@ -74,7 +79,7 @@
7580 $wgHooks['EditPage::showEditForm:initial'][] = 'DraftHooks::loadForm';
7681
7782 // Register ajax response hook
78 -$wgAjaxExportList[] = 'DraftHooks::AjaxSave';
 83+$wgAjaxExportList[] = 'DraftHooks::save';
7984
8085 // Register ajax add script hook
8186 $wgHooks['AjaxAddScript'][] = 'DraftHooks::addJS';
Index: trunk/extensions/Drafts/Drafts.hooks.php
@@ -5,13 +5,23 @@
66 * @file
77 * @ingroup Extensions
88 */
9 -
 9+
1010 // Drafts hooks
1111 class DraftHooks {
1212 /**
1313 * ArticleSaveComplete hook
1414 */
15 - public static function discard( &$article, &$user, &$text, &$summary, &$m, &$watchthis, &$section, &$flags, $rev ) {
 15+ public static function discard(
 16+ &$article,
 17+ &$user,
 18+ &$text,
 19+ &$summary,
 20+ &$m,
 21+ &$watchthis,
 22+ &$section,
 23+ &$flags,
 24+ $rev
 25+ ) {
1626 global $wgRequest;
1727 // Check if the save occured from a draft
1828 $draft = Draft::newFromID( $wgRequest->getIntOrNull( 'wpDraftID' ) );
@@ -22,19 +32,19 @@
2333 // Continue
2434 return true;
2535 }
26 -
 36+
2737 /**
2838 * EditPage::showEditForm:initial hook
2939 * Load draft...
3040 */
31 - public static function loadForm( &$editpage ) {
 41+ public static function loadForm(
 42+ &$editpage
 43+ ) {
3244 global $wgUser, $wgRequest, $wgOut, $wgTitle, $wgLang;
33 -
3445 // Check permissions
3546 if ( $wgUser->isAllowed( 'edit' ) && $wgUser->isLoggedIn() ) {
3647 // Get draft
3748 $draft = Draft::newFromID( $wgRequest->getIntOrNull( 'draft' ) );
38 -
3949 // Load form values
4050 if ( $draft->exists() ) {
4151 // Override initial values in the form with draft data
@@ -43,18 +53,21 @@
4454 $editpage->scrolltop = $draft->getScrollTop();
4555 $editpage->minoredit = $draft->getMinorEdit() ? true : false;
4656 }
47 -
 57+
4858 // Save draft on non-save submission
4959 if ( $wgRequest->getVal( 'action' ) == 'submit' &&
5060 $wgUser->editToken() == $wgRequest->getText( 'wpEditToken' ) )
5161 {
5262 // If the draft wasn't specified in the url, try using a form-submitted one
5363 if ( !$draft->exists() ) {
54 - $draft = Draft::newFromID( $wgRequest->getIntOrNull( 'wpDraftID' ) );
 64+ $draft = Draft::newFromID(
 65+ $wgRequest->getIntOrNull( 'wpDraftID' )
 66+ );
5567 }
56 -
5768 // Load draft with info
58 - $draft->setTitle( Title::newFromText( $wgRequest->getText( 'wpDraftTitle' ) ) );
 69+ $draft->setTitle( Title::newFromText(
 70+ $wgRequest->getText( 'wpDraftTitle' ) )
 71+ );
5972 $draft->setSection( $wgRequest->getInt( 'wpSection' ) );
6073 $draft->setStartTime( $wgRequest->getText( 'wpStarttime' ) );
6174 $draft->setEditTime( $wgRequest->getText( 'wpEdittime' ) );
@@ -63,73 +76,83 @@
6477 $draft->setText( $wgRequest->getText( 'wpTextbox1' ) );
6578 $draft->setSummary( $wgRequest->getText( 'wpSummary' ) );
6679 $draft->setMinorEdit( $wgRequest->getInt( 'wpMinoredit', 0 ) );
67 -
6880 // Save draft
6981 $draft->save();
70 -
7182 // Use the new draft id
7283 $wgRequest->setVal( 'draft', $draft->getID() );
7384 }
7485 }
75 -
7686 // Internationalization
7787 wfLoadExtensionMessages( 'Drafts' );
78 -
79 - $numDrafts = Draft::countDrafts( $wgTitle );
80 -
 88+ $numDrafts = Drafts::num( $wgTitle );
8189 // Show list of drafts
8290 if ( $numDrafts > 0 ) {
8391 if ( $wgRequest->getText( 'action' ) !== 'submit' ) {
84 - $wgOut->addHTML( Xml::openElement( 'div', array( 'id' => 'drafts-list-box' ) ) );
85 - $wgOut->addHTML( Xml::element( 'h3', null, wfMsg( 'drafts-view-existing' ) ) );
86 - Draft::ListDrafts( $wgTitle );
 92+ $wgOut->addHTML( Xml::openElement(
 93+ 'div', array( 'id' => 'drafts-list-box' ) )
 94+ );
 95+ $wgOut->addHTML( Xml::element(
 96+ 'h3', null, wfMsg( 'drafts-view-existing' ) )
 97+ );
 98+ Drafts::display( $wgTitle );
8799 $wgOut->addHTML( Xml::closeElement( 'div' ) );
88100 } else {
 101+ $jsWarn = "if( !wgAjaxSaveDraft.insync ) return confirm('" .
 102+ Xml::escapeJsString( wfMsgHTML( 'drafts-view-warn' ) ) .
 103+ "')";
89104 $link = Xml::element( 'a',
90105 array(
91106 'href' => $wgTitle->getFullURL( 'action=edit' ),
92 - 'onclick' => "if( !wgAjaxSaveDraft.insync ) return confirm('" . Xml::escapeJsString( wfMsgHTML( 'drafts-view-warn' ) ) . "')"
 107+ 'onclick' => $jsWarn
93108 ),
94 - wfMsgExt( 'drafts-view-notice-link', array( 'parsemag' ), $wgLang->formatNum( $numDrafts ) )
 109+ wfMsgExt(
 110+ 'drafts-view-notice-link',
 111+ array( 'parsemag' ),
 112+ $wgLang->formatNum( $numDrafts )
 113+ )
95114 );
96115 $wgOut->addHTML( wfMsgHTML( 'drafts-view-notice', $link ) );
97116 }
98117 }
99 -
100118 // Continue
101119 return true;
102120 }
103 -
 121+
104122 /**
105123 * EditFilter hook
106124 * Intercept the saving of an article to detect if the submission was from the non-javascript
107125 * save draft button
108126 */
109 - public static function interceptSave( $editor, $text, $section, &$error ) {
 127+ public static function interceptSave(
 128+ $editor,
 129+ $text,
 130+ $section,
 131+ &$error
 132+ ) {
110133 global $wgRequest;
111 -
112134 // Don't save if the save draft button caused the submit
113135 if ( $wgRequest->getText( 'wpDraftSave' ) !== '' ) {
114136 // Modify the error so it's clear we want to remain in edit mode
115137 $error = ' ';
116138 }
117 -
118139 // Continue
119140 return true;
120141 }
121 -
 142+
122143 /**
123144 * EditPageBeforeEditButtons hook
124145 * Add draft saving controls
125146 */
126 - public static function controls( &$editpage, &$buttons ) {
127 - global $wgUser, $wgTitle, $wgRequest, $egDraftsAutoSaveWait;
128 -
 147+ public static function controls(
 148+ &$editpage,
 149+ &$buttons
 150+ ) {
 151+ global $wgUser, $wgTitle, $wgRequest;
 152+ global $egDraftsAutoSaveWait, $egDraftsAutoSaveTimeout;
129153 // Check permissions
130154 if ( $wgUser->isAllowed( 'edit' ) && $wgUser->isLoggedIn() ) {
131155 // Internationalization
132156 wfLoadExtensionMessages( 'Drafts' );
133 -
134157 // Build XML
135158 $buttons['savedraft'] = Xml::openElement( 'script',
136159 array(
@@ -137,23 +160,22 @@
138161 'language' => 'javascript'
139162 )
140163 );
141 -
142164 $buttonAttribs = array(
143165 'id' => 'wpDraftSave',
144166 'name' => 'wpDraftSave',
145167 'tabindex' => 8,
146168 'value' => wfMsg( 'drafts-save-save' ),
147169 );
148 -
149170 $accesskey = $wgUser->getSkin()->accesskey( 'drafts-save' );
150171 if ( $accesskey !== false ) {
151172 $buttonAttribs['accesskey'] = $accesskey;
152173 }
153 - $tooltip = $wgUser->getSkin()->titleAttrib( 'drafts-save', 'withaccess' );
 174+ $tooltip = $wgUser->getSkin()->titleAttrib(
 175+ 'drafts-save', 'withaccess'
 176+ );
154177 if ( $tooltip !== false ) {
155178 $buttonAttribs['title'] = $tooltip;
156179 }
157 -
158180 $ajaxButton = Xml::escapeJsString(
159181 Xml::element( 'input',
160182 array( 'type' => 'button' ) + $buttonAttribs
@@ -180,6 +202,13 @@
181203 $buttons['savedraft'] .= Xml::element( 'input',
182204 array(
183205 'type' => 'hidden',
 206+ 'name' => 'wpDraftAutoSaveTimeout',
 207+ 'value' => $egDraftsAutoSaveTimeout
 208+ )
 209+ );
 210+ $buttons['savedraft'] .= Xml::element( 'input',
 211+ array(
 212+ 'type' => 'hidden',
184213 'name' => 'wpDraftToken',
185214 'value' => Draft::newToken()
186215 )
@@ -208,6 +237,13 @@
209238 $buttons['savedraft'] .= Xml::element( 'input',
210239 array(
211240 'type' => 'hidden',
 241+ 'name' => 'wpMsgSaving',
 242+ 'value' => wfMsg( 'drafts-save-saving' )
 243+ )
 244+ );
 245+ $buttons['savedraft'] .= Xml::element( 'input',
 246+ array(
 247+ 'type' => 'hidden',
212248 'name' => 'wpMsgSaveDraft',
213249 'value' => wfMsg( 'drafts-save-save' )
214250 )
@@ -220,62 +256,81 @@
221257 )
222258 );
223259 }
224 -
225260 // Continue
226261 return true;
227262 }
228 -
 263+
229264 /**
230265 * AjaxAddScript hook
231266 * Add ajax support script
232267 */
233 - public static function addJS( $out ) {
 268+ public static function addJS(
 269+ $out
 270+ ) {
234271 global $wgScriptPath, $wgJsMimeType, $wgDraftsStyleVersion;
235 -
236272 // FIXME: assumes standard dir structure
237273 // Add javascript to support ajax draft saving
238 - $out->addInlineScript( "var wgDraftsStyleVersion = \"$wgDraftsStyleVersion\";\n" );
239 - $out->addScript( "<script type=\"$wgJsMimeType\" src=\"$wgScriptPath/extensions/Drafts/Drafts.js?$wgDraftsStyleVersion\"></script>\n" );
240 -
 274+ $out->addInlineScript(
 275+ "var wgDraftsStyleVersion = \"$wgDraftsStyleVersion\";\n"
 276+ );
 277+ $out->addScript(
 278+ Xml::element(
 279+ 'script',
 280+ array(
 281+ 'type' => $wgJsMimeType,
 282+ 'src' => $wgScriptPath . '/extensions/Drafts/Drafts.js?' .
 283+ $wgDraftsStyleVersion
 284+ )
 285+ )
 286+ );
241287 // Continue
242288 return true;
243289 }
244 -
 290+
245291 /**
246292 * BeforePageDisplay hook
247 - * Add ajax support script
 293+ * Add css style sheet
248294 */
249 - public static function addCSS( $out ) {
 295+ public static function addCSS(
 296+ $out
 297+ ) {
250298 global $wgScriptPath, $wgDraftsStyleVersion;
251 -
252299 // FIXME: assumes standard dir structure
253300 // Add css for various styles
254301 $out->addLink(
255302 array(
256303 'rel' => 'stylesheet',
257304 'type' => 'text/css',
258 - 'href' => "$wgScriptPath/extensions/Drafts/Drafts.css?$wgDraftsStyleVersion",
 305+ 'href' => $wgScriptPath . '/extensions/Drafts/Drafts.css?' .
 306+ $wgDraftsStyleVersion,
259307 )
260308 );
261 -
262309 // Continue
263310 return true;
264311 }
265 -
 312+
266313 /**
267314 * AJAX function export DraftHooks::AjaxSave
268315 * Respond to ajax queries
269316 */
270 - public static function AjaxSave( $dtoken, $etoken, $id, $title, $section, $starttime, $edittime,
271 - $scrolltop, $text, $summary, $minoredit )
272 - {
 317+ public static function save(
 318+ $dtoken,
 319+ $etoken,
 320+ $id,
 321+ $title,
 322+ $section,
 323+ $starttime,
 324+ $edittime,
 325+ $scrolltop,
 326+ $text,
 327+ $summary,
 328+ $minoredit
 329+ ) {
273330 global $wgUser, $wgRequest;
274 -
275331 // Verify token
276332 if ( $wgUser->editToken() == $etoken ) {
277333 // Create Draft
278334 $draft = Draft::newFromID( $id );
279 -
280335 // Load draft with info
281336 $draft->setToken( $dtoken );
282337 $draft->setTitle( Title::newFromText( $title ) );
@@ -287,10 +342,8 @@
288343 $draft->setText( $text );
289344 $draft->setSummary( $summary );
290345 $draft->setMinorEdit( $minoredit );
291 -
292346 // Save draft
293347 $draft->save();
294 -
295348 // Return draft id to client (used for next save)
296349 return (string) $draft->getID();
297350 } else {
Index: trunk/extensions/Drafts/Drafts.js
@@ -1,128 +1,167 @@
22 /* JavaScript for Drafts extension */
33
4 -/* Classes */
5 -
6 -var wgAjaxSaveDraft = {};
7 -
8 -// Fields
9 -
10 -wgAjaxSaveDraft.inprogress = false;
11 -wgAjaxSaveDraft.insync = true;
12 -wgAjaxSaveDraft.autosavetimer = null;
13 -wgAjaxSaveDraft.autosavewait = null;
14 -
15 -// Actions
16 -
17 -wgAjaxSaveDraft.save = function() {
18 - wgAjaxSaveDraft.call(
19 - document.editform.wpDraftToken.value,
20 - document.editform.wpEditToken.value,
21 - document.editform.wpDraftID.value,
22 - document.editform.wpDraftTitle.value,
23 - document.editform.wpSection.value,
24 - document.editform.wpStarttime.value,
25 - document.editform.wpEdittime.value,
26 - document.editform.wpTextbox1.scrollTop,
27 - document.editform.wpTextbox1.value,
28 - document.editform.wpSummary.value,
29 - document.editform.wpMinoredit.checked ? 1 : 0
30 - );
31 -
32 - // Ensure timer is cleared in case we saved manually before it expired
33 - clearTimeout( wgAjaxSaveDraft.autosavetimer );
34 -}
35 -
36 -wgAjaxSaveDraft.change = function() {
37 - wgAjaxSaveDraft.insync = false;
38 - wgAjaxSaveDraft.setControlsUnsaved();
39 -
40 - // Clear if timer is pending
41 - if( wgAjaxSaveDraft.autosavetimer ) {
42 - clearTimeout( wgAjaxSaveDraft.autosavetimer );
 4+function Draft() {
 5+
 6+ /* Private Members */
 7+
 8+ // Reference to object's self
 9+ var self = this;
 10+ // Configuration settings
 11+ var configuration = null;
 12+ // Language specific messages
 13+ var messages = null;
 14+ // State of the draft as it pertains to asynchronous saving
 15+ var state = 'unchanged';
 16+ // Timer handle for auto-saving
 17+ var timer = null;
 18+ // Reference to edit form draft is being edited with
 19+ var form = null;
 20+
 21+ /* Functions */
 22+
 23+ this.setState = function(
 24+ newState
 25+ ) {
 26+ // Stores state information
 27+ state = newState;
 28+ // Updates UI elements
 29+ switch ( state ) {
 30+ case 'unchanged':
 31+ form.wpDraftSave.disabled = true;
 32+ form.wpDraftSave.value = messages.saveDraft;
 33+ break;
 34+ case 'changed':
 35+ form.wpDraftSave.disabled = false;
 36+ form.wpDraftSave.value = messages.saveDraft;
 37+ break;
 38+ case 'saved':
 39+ form.wpDraftSave.disabled = true;
 40+ form.wpDraftSave.value = messages.saved;
 41+ break;
 42+ case 'saving':
 43+ form.wpDraftSave.disabled = true;
 44+ form.wpDraftSave.value = messages.saving;
 45+ break;
 46+ case 'error':
 47+ form.wpDraftSave.disabled = true;
 48+ form.wpDraftSave.value = messages.error;
 49+ break;
 50+ default: break;
 51+ }
4352 }
44 - // Set timer to save automatically
45 - if( wgAjaxSaveDraft.autosavewait && wgAjaxSaveDraft.autosavewait > 0 ) {
46 - wgAjaxSaveDraft.autosavetimer = setTimeout(
47 - "wgAjaxSaveDraft.save()",
48 - wgAjaxSaveDraft.autosavewait * 1000
 53+
 54+ this.getState = function() {
 55+ return state;
 56+ }
 57+
 58+ this.save = function() {
 59+ // Checks if a save is already taking place
 60+ if ( state == 'saving' ) {
 61+ // Exits function immediately
 62+ return;
 63+ }
 64+ // Sets state to saving
 65+ self.setState( 'saving' );
 66+ // Saves current request type
 67+ var oldRequestType = sajax_request_type;
 68+ // Changes request type to post
 69+ sajax_request_type = "POST";
 70+ // Performs asynchronous save on server
 71+ sajax_do_call(
 72+ "DraftHooks::save",
 73+ [
 74+ form.wpDraftToken.value,
 75+ form.wpEditToken.value,
 76+ form.wpDraftID.value,
 77+ form.wpDraftTitle.value,
 78+ form.wpSection.value,
 79+ form.wpStarttime.value,
 80+ form.wpEdittime.value,
 81+ form.wpTextbox1.scrollTop,
 82+ form.wpTextbox1.value,
 83+ form.wpSummary.value,
 84+ form.wpMinoredit.checked ? 1 : 0
 85+ ],
 86+ new Function( "request", "wgDraft.respond( request )" )
4987 );
 88+ // Restores current request type
 89+ sajax_request_type = oldRequestType;
 90+ // Re-allow request if it is not done in 10 seconds
 91+ self.timeoutID = window.setTimeout(
 92+ "wgDraft.setState( 'changed' )", 10000
 93+ );
 94+ // Ensure timer is cleared in case we saved manually before it expired
 95+ clearTimeout( timer );
5096 }
51 -}
5297
53 -wgAjaxSaveDraft.setControlsSaved = function() {
54 - document.editform.wpDraftSave.disabled = true;
55 - document.editform.wpDraftSave.value = document.editform.wpMsgSaved.value;
56 -}
57 -wgAjaxSaveDraft.setControlsUnsaved = function() {
58 - document.editform.wpDraftSave.disabled = false;
59 - document.editform.wpDraftSave.value = document.editform.wpMsgSaveDraft.value;
60 -}
61 -wgAjaxSaveDraft.setControlsError = function() {
62 - document.editform.wpDraftSave.disabled = true;
63 - document.editform.wpDraftSave.value = document.editform.wpMsgError.value;
64 -}
65 -
66 -// Events
67 -
68 -wgAjaxSaveDraft.onLoad = function() {
69 - // Check to see that the form and controls exist
70 - if ( document.editform && document.editform.wpDraftSave ) {
71 - // Handle saving
72 - addHandler(document.editform.wpDraftSave, 'click', wgAjaxSaveDraft.save);
73 -
74 - // Detect changes
75 - addHandler(document.editform.wpTextbox1, 'keypress', wgAjaxSaveDraft.change);
76 - addHandler(document.editform.wpTextbox1, 'keyup', wgAjaxSaveDraft.change);
77 - addHandler(document.editform.wpTextbox1, 'keydown', wgAjaxSaveDraft.change);
78 - addHandler(document.editform.wpTextbox1, 'paste', wgAjaxSaveDraft.change);
79 - addHandler(document.editform.wpTextbox1, 'cut', wgAjaxSaveDraft.change);
80 - addHandler(document.editform.wpSummary, 'keypress', wgAjaxSaveDraft.change);
81 - addHandler(document.editform.wpSummary, 'keyup', wgAjaxSaveDraft.change);
82 - addHandler(document.editform.wpSummary, 'keydown', wgAjaxSaveDraft.change);
83 - addHandler(document.editform.wpSummary, 'paste', wgAjaxSaveDraft.change);
84 - addHandler(document.editform.wpSummary, 'cut', wgAjaxSaveDraft.change);
85 - addHandler(document.editform.wpMinoredit, 'change', wgAjaxSaveDraft.change);
 98+ this.change = function() {
 99+ // Sets state to changed
 100+ self.setState( 'changed' );
 101+ // Checks if timer is pending
 102+ if ( timer ) {
 103+ // Clears pending timer
 104+ clearTimeout( timer );
 105+ }
 106+ // Checks if auto-save wait time was set, and that it's greater than 0
 107+ if ( configuration.autoSaveWait && configuration.autoSaveWait > 0 ) {
 108+ // Sets timer to save automatically after a period of time
 109+ timer = setTimeout(
 110+ "wgDraft.save()", configuration.autoSaveWait * 1000
 111+ );
 112+ }
 113+ }
86114
87 - // Use the configured autosave wait time
88 - wgAjaxSaveDraft.autosavewait = document.editform.wpDraftAutoSaveWait.value;
 115+ this.initialize = function() {
 116+ // Cache edit form reference
 117+ form = document.editform;
 118+ // Check to see that the form and controls exist
 119+ if ( form && form.wpDraftSave ) {
 120+ // Handle manual draft saving through clicking the save draft button
 121+ addHandler( form.wpDraftSave, 'click', self.save );
 122+ // Handle keeping track of state by watching for changes to fields
 123+ addHandler( form.wpTextbox1, 'keypress', self.change );
 124+ addHandler( form.wpTextbox1, 'keyup', self.change );
 125+ addHandler( form.wpTextbox1, 'keydown', self.change );
 126+ addHandler( form.wpTextbox1, 'paste', self.change );
 127+ addHandler( form.wpTextbox1, 'cut', self.change );
 128+ addHandler( form.wpSummary, 'keypress', self.change );
 129+ addHandler( form.wpSummary, 'keyup', self.change );
 130+ addHandler( form.wpSummary, 'keydown', self.change );
 131+ addHandler( form.wpSummary, 'paste', self.change );
 132+ addHandler( form.wpSummary, 'cut', self.change );
 133+ addHandler( form.wpMinoredit, 'change', self.change );
 134+ // Gets configured specific values
 135+ configuration = {
 136+ autoSaveWait: form.wpDraftAutoSaveWait.value,
 137+ autoSaveTimeout: form.wpDraftAutoSaveTimeout.value
 138+ };
 139+ // Gets language-specific messages
 140+ messages = {
 141+ saveDraft: form.wpMsgSaveDraft.value,
 142+ saving: form.wpMsgSaving.value,
 143+ saved: form.wpMsgSaved.value,
 144+ error: form.wpMsgError.value
 145+ };
 146+ }
89147 }
90 -}
91148
92 -wgAjaxSaveDraft.call = function( dtoken, etoken, id, title, section, starttime, edittime, scrolltop, text, summary, minoredit ) {
93 - // If in progress, exit now
94 - if( wgAjaxSaveDraft.inprogress )
95 - return;
96 -
97 - // Otherwise, declare we are now in progress
98 - wgAjaxSaveDraft.inprogress = true;
99 -
100 - // Perform Ajax call
101 - var old = sajax_request_type;
102 - sajax_request_type = "POST";
103 - sajax_do_call(
104 - "DraftHooks::AjaxSave",
105 - [ dtoken, etoken, id, title, section, starttime, edittime, scrolltop, text, summary, minoredit ],
106 - wgAjaxSaveDraft.processResult
107 - );
108 - sajax_request_type = old;
109 -
110 - // Reallow request if it is not done in 2 seconds
111 - wgAjaxSaveDraft.timeoutID = window.setTimeout( function() {
112 - wgAjaxSaveDraft.inprogress = false;
113 - }, 2000 );
114 -}
115 -
116 -wgAjaxSaveDraft.processResult = function( request ) {
117 - // Change UI state
118 - if( request.responseText > -1 ) {
119 - wgAjaxSaveDraft.setControlsSaved();
120 - document.editform.wpDraftID.value = request.responseText;
121 - } else {
122 - wgAjaxSaveDraft.setControlsError();
 149+ this.respond = function(
 150+ request
 151+ ) {
 152+ // Checks that an error did not occur
 153+ if ( request.responseText > -1 ) {
 154+ // Changes state to saved
 155+ self.setState( 'saved' );
 156+ // Gets id of newly inserted draft (or updates if it already exists)
 157+ // and stores it in a hidden form field
 158+ form.wpDraftID.value = request.responseText;
 159+ } else {
 160+ // Changes state to error
 161+ self.setState( 'error' );
 162+ }
123163 }
124 -
125 - // Change object state
126 - wgAjaxSaveDraft.inprogress = false;
127164 }
128 -
129 -hookEvent( "load", wgAjaxSaveDraft.onLoad );
 165+// Instantiates a draft object
 166+var wgDraft = new Draft();
 167+// Registers hooks
 168+hookEvent( "load", wgDraft.initialize );

Status & tagging log