Index: trunk/extensions/Drafts/Drafts.sql |
— | — | @@ -1,5 +1,6 @@ |
2 | 2 | create table /*$wgDBPrefix*/drafts ( |
3 | 3 | draft_id INTEGER AUTO_INCREMENT PRIMARY KEY, |
| 4 | + draft_token INTEGER, |
4 | 5 | draft_user INTEGER, |
5 | 6 | draft_namespace INTEGER, |
6 | 7 | draft_title VARBINARY(255), |
Index: trunk/extensions/Drafts/Drafts.classes.php |
— | — | @@ -10,6 +10,7 @@ |
11 | 11 | private $_db; |
12 | 12 | private $_exists = false; |
13 | 13 | private $_id; |
| 14 | + private $_token; |
14 | 15 | private $_userID; |
15 | 16 | private $_title; |
16 | 17 | private $_section; |
— | — | @@ -65,6 +66,7 @@ |
66 | 67 | } |
67 | 68 | |
68 | 69 | // Synchronize data |
| 70 | + $this->_token = $row['draft_token']; |
69 | 71 | $this->_title = Title::makeTitle( $row['draft_namespace'], $row['draft_title'] ); |
70 | 72 | $this->_section = $row['draft_section']; |
71 | 73 | $this->_starttime = $row['draft_starttime']; |
— | — | @@ -82,13 +84,14 @@ |
83 | 85 | } |
84 | 86 | |
85 | 87 | public function save() { |
86 | | - global $wgUser; |
| 88 | + global $wgUser, $wgRequest; |
87 | 89 | |
88 | 90 | // Get db connection |
89 | 91 | $this->getDB(); |
90 | 92 | |
91 | 93 | // Build data |
92 | 94 | $data = array( |
| 95 | + 'draft_token' => (int) $this->getToken(), |
93 | 96 | 'draft_user' => (int) $wgUser->getID(), |
94 | 97 | 'draft_namespace' => (int) $this->_title->getNamespace(), |
95 | 98 | 'draft_title' => (string) $this->_title->getDBKey(), |
— | — | @@ -112,13 +115,26 @@ |
113 | 116 | ), |
114 | 117 | __METHOD__ |
115 | 118 | ); |
| 119 | + } else { |
| 120 | + // Before creating a new draft record, lets check if we have already |
| 121 | + $token = $wgRequest->getIntOrNull( 'wpDraftToken' ); |
| 122 | + if( $token !== null) { |
| 123 | + // Check if token has been used already for this article |
| 124 | + if( $this->_db->selectField( 'drafts', 'draft_token', |
| 125 | + array( |
| 126 | + 'draft_namespace' => $data['draft_namespace'], |
| 127 | + 'draft_title' => $data['draft_title'], |
| 128 | + 'draft_user' => $data['draft_user'], |
| 129 | + ), |
| 130 | + __METHOD__ |
| 131 | + ) === false ) { |
| 132 | + $this->_db->insert( 'drafts', $data, __METHOD__ ); |
| 133 | + $this->_id = $this->_db->insertId(); |
| 134 | + // Update state |
| 135 | + $this->_exists = true; |
| 136 | + } |
| 137 | + } |
116 | 138 | } |
117 | | - else { |
118 | | - $this->_db->insert( 'drafts', $data, __METHOD__ ); |
119 | | - $this->_id = $this->_db->insertId(); |
120 | | - // Update state |
121 | | - $this->_exists = true; |
122 | | - } |
123 | 139 | |
124 | 140 | // Return success |
125 | 141 | return true; |
— | — | @@ -148,6 +164,7 @@ |
149 | 165 | |
150 | 166 | public static function newFromRow( $row ) { |
151 | 167 | $draft = new Draft( $row['draft_id'], false); |
| 168 | + $draft->setToken( $row['draft_token'] ); |
152 | 169 | $draft->setTitle( Title::makeTitle( $row['draft_namespace'], $row['draft_title'] ) ); |
153 | 170 | $draft->setSection( $row['draft_section'] ); |
154 | 171 | $draft->setStartTime( $row['draft_starttime'] ); |
— | — | @@ -339,7 +356,7 @@ |
340 | 357 | Xml::element( 'a', |
341 | 358 | array( |
342 | 359 | 'href' => $urlDiscard, |
343 | | - 'onclick' => htmlspecialchars( "if( !wgAjaxSaveDraft.insync ) return confirm('" . Xml::escapeJsString( wfMsgHTML( 'drafts-view-warn' ) ) . "')" ) |
| 360 | + 'onclick' => "if( !wgAjaxSaveDraft.insync ) return confirm('" . Xml::escapeJsString( wfMsgHTML( 'drafts-view-warn' ) ) . "')" |
344 | 361 | ), |
345 | 362 | wfMsg( 'drafts-view-discard' ) |
346 | 363 | ) |
— | — | @@ -355,6 +372,10 @@ |
356 | 373 | return 0; |
357 | 374 | } |
358 | 375 | |
| 376 | + public static function newToken() { |
| 377 | + return time(); |
| 378 | + } |
| 379 | + |
359 | 380 | private function getDB() { |
360 | 381 | // Get database connection if we don't already have one |
361 | 382 | if ( $this->_db === null ) { |
— | — | @@ -375,6 +396,13 @@ |
376 | 397 | return $this->_id; |
377 | 398 | } |
378 | 399 | |
| 400 | + public function setToken( $token ) { |
| 401 | + $this->_token = $token; |
| 402 | + } |
| 403 | + public function getToken() { |
| 404 | + return $this->_token; |
| 405 | + } |
| 406 | + |
379 | 407 | public function getUserID( $userID ) { |
380 | 408 | $this->_userID = $userID; |
381 | 409 | } |
Index: trunk/extensions/Drafts/Drafts.hooks.php |
— | — | @@ -164,6 +164,13 @@ |
165 | 165 | $buttons['savedraft'] .= Xml::element( 'input', |
166 | 166 | array( |
167 | 167 | 'type' => 'hidden', |
| 168 | + 'name' => 'wpDraftToken', |
| 169 | + 'value' => Draft::newToken() |
| 170 | + ) |
| 171 | + ); |
| 172 | + $buttons['savedraft'] .= Xml::element( 'input', |
| 173 | + array( |
| 174 | + 'type' => 'hidden', |
168 | 175 | 'name' => 'wpDraftID', |
169 | 176 | 'value' => $wgRequest->getInt( 'draft', '' ) |
170 | 177 | ) |