Index: trunk/extensions/LiquidThreads/LqtFunctions.php |
— | — | @@ -37,11 +37,6 @@ |
38 | 38 | $original_array = $new_assoc; |
39 | 39 | } |
40 | 40 | |
41 | | -function lqtFormatMoveLogEntry( $type, $action, $title, $sk, $parameters ) { |
42 | | - return wfMsgExt( 'lqt-log-action-move', 'parseinline', |
43 | | - array( $title->getPrefixedText(), $parameters[0], $parameters[1] ) ); |
44 | | -} |
45 | | - |
46 | 41 | function lqtSetupParserFunctions( &$parser ) { |
47 | 42 | global $wgLiquidThreadsAllowUserControl; |
48 | 43 | |
Index: trunk/extensions/LiquidThreads/i18n/Lqt.i18n.php |
— | — | @@ -206,6 +206,11 @@ |
207 | 207 | 'lqt-log-name' => 'Threaded discussion log', |
208 | 208 | 'lqt-log-header' => 'This log details actions taken on discussion threads.', |
209 | 209 | 'lqt-log-action-move' => 'moved [[$1]] from [[$2]] to [[$3]].', |
| 210 | + 'lqt-log-action-split' => 'split [[$1]] from under [[$3]], with the new subject "$2".', |
| 211 | + 'lqt-log-action-merge-across' => 'moved [[$1]] from under [[$2]] to under [[$3]].', |
| 212 | + 'lqt-log-action-merge-down' => 'merged [[$1]] to underneath [[$3]]', |
| 213 | + 'lqt-log-action-subjectedit' => 'changed the subject of [[$1]] from "$2" to "$3"', |
| 214 | + 'lqt-log-action-resort' => 'modified the sort order of [[$1]]. Changed sort key from $2 to $3.', |
210 | 215 | |
211 | 216 | // Preferences |
212 | 217 | 'lqt-preference-notify-talk' => 'E-mail me on replies to a thread I am watching', |
Index: trunk/extensions/LiquidThreads/LiquidThreads.php |
— | — | @@ -122,6 +122,7 @@ |
123 | 123 | $wgAutoloadClasses['ThreadHistoryPager'] = "$dir/classes/ThreadHistoryPager.php"; |
124 | 124 | $wgAutoloadClasses['TalkpageHistoryView'] = "$dir/pages/TalkpageHistoryView.php"; |
125 | 125 | $wgAutoloadClasses['LqtHotTopicsController'] = "$dir/classes/HotTopics.php"; |
| 126 | +$wgAutoloadClasses['LqtLogFormatter'] = "$dir/classes/LogFormatter.php"; |
126 | 127 | |
127 | 128 | // View classes |
128 | 129 | $wgAutoloadClasses['TalkpageView'] = $dir . 'pages/TalkpageView.php'; |
— | — | @@ -158,8 +159,11 @@ |
159 | 160 | $wgLogTypes[] = 'liquidthreads'; |
160 | 161 | $wgLogNames['liquidthreads'] = 'lqt-log-name'; |
161 | 162 | $wgLogHeaders['liquidthreads'] = 'lqt-log-header'; |
162 | | -$wgLogActionsHandlers['liquidthreads/move'] = 'lqtFormatMoveLogEntry'; |
163 | 163 | |
| 164 | +foreach( array( 'move', 'split', 'merge', 'subjectedit', 'resort' ) as $action ) { |
| 165 | + $wgLogActionsHandlers["liquidthreads/$action"] = 'LqtLogFormatter::formatLogEntry'; |
| 166 | +} |
| 167 | + |
164 | 168 | // Preferences |
165 | 169 | $wgDefaultUserOptions['lqtnotifytalk'] = false; |
166 | 170 | $wgDefaultUserOptions['lqtdisplaydepth'] = 2; |
Index: trunk/extensions/LiquidThreads/classes/LogFormatter.php |
— | — | @@ -0,0 +1,44 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +// Contains formatter functions for all log entry types. |
| 5 | +class LqtLogFormatter { |
| 6 | + protected static function isForIRC( ) { |
| 7 | + // FIXME this is a horrific hack, but it's better than spewing HTML in the wrong |
| 8 | + // language to IRC. |
| 9 | + return in_string( '/LogPage::addEntry/', wfGetAllCallers() ); |
| 10 | + } |
| 11 | + |
| 12 | + static function formatLogEntry( $type, $action, $title, $sk, $parameters ) { |
| 13 | + switch( $action ) { |
| 14 | + case 'merge': |
| 15 | + if ( $parameters[0] ) { |
| 16 | + $msg = 'lqt-log-action-merge-across'; |
| 17 | + } else { |
| 18 | + $msg = 'lqt-log-action-merge-down'; |
| 19 | + } |
| 20 | + break; |
| 21 | + default: |
| 22 | + $msg = 'lqt-log-action-'.$action; |
| 23 | + break; |
| 24 | + } |
| 25 | + |
| 26 | + $options = array('parseinline'); |
| 27 | + |
| 28 | + $forIRC = self::isForIRC(); |
| 29 | + |
| 30 | + if ($forIRC) { |
| 31 | + global $wgContLang; |
| 32 | + $options['language'] = $wgContLang->getCode(); |
| 33 | + } |
| 34 | + |
| 35 | + $replacements = array_merge( array( $title->getPrefixedText() ), $parameters ); |
| 36 | + |
| 37 | + $html = wfMsgExt( $msg, $options, $replacements ); |
| 38 | + |
| 39 | + if ($forIRC) { |
| 40 | + $html = StringUtils::delimiterReplace( '<', '>', '', $html ); |
| 41 | + } |
| 42 | + |
| 43 | + return $html; |
| 44 | + } |
| 45 | +} |
Index: trunk/extensions/LiquidThreads/classes/Thread.php |
— | — | @@ -45,6 +45,8 @@ |
46 | 46 | |
47 | 47 | protected $replies; |
48 | 48 | |
| 49 | + public $dbVersion; // A copy of the thread as it exists in the database. |
| 50 | + |
49 | 51 | static $titleCacheById = array(); |
50 | 52 | static $replyCacheById = array(); |
51 | 53 | static $articleCacheById = array(); |
— | — | @@ -133,6 +135,9 @@ |
134 | 136 | |
135 | 137 | // Touch the talk page, too. |
136 | 138 | $this->article()->getTitle()->invalidateCache(); |
| 139 | + |
| 140 | + $this->dbVersion = clone $this; |
| 141 | + unset( $this->dbVersion->dbVersion ); |
137 | 142 | } |
138 | 143 | |
139 | 144 | function setRoot( $article ) { |
— | — | @@ -157,6 +162,8 @@ |
158 | 163 | if ( $bump ) { |
159 | 164 | $this->sortkey = wfTimestamp( TS_MW ); |
160 | 165 | } |
| 166 | + |
| 167 | + $original = $this->dbVersion; |
161 | 168 | |
162 | 169 | $this->modified = wfTimestampNow(); |
163 | 170 | $this->updateEditedness( $change_type ); |
— | — | @@ -168,12 +175,51 @@ |
169 | 176 | $topmost->save(); |
170 | 177 | |
171 | 178 | ThreadRevision::create( $this, $change_type, $change_object, $reason ); |
| 179 | + $this->logChange( $change_type, $original, $change_object, $reason ); |
172 | 180 | |
173 | 181 | if ( $change_type == Threads::CHANGE_EDITED_ROOT ) { |
174 | 182 | NewMessages::writeMessageStateForUpdatedThread( $this, $change_type, $wgUser ); |
175 | 183 | } |
176 | 184 | } |
177 | 185 | |
| 186 | + function logChange( $change_type, $original, $change_object = null, $reason = '' ) { |
| 187 | + $log = new LogPage( 'liquidthreads' ); |
| 188 | + |
| 189 | + if ( is_null($reason) ) { |
| 190 | + $reason = ''; |
| 191 | + } |
| 192 | + |
| 193 | + switch( $change_type ) { |
| 194 | + case Threads::CHANGE_MOVED_TALKPAGE: |
| 195 | + $log->addEntry( 'move', $this->title(), $reason, |
| 196 | + array( $original->article()->getTitle(), |
| 197 | + $this->article()->getTitle() ) ); |
| 198 | + break; |
| 199 | + case Threads::CHANGE_SPLIT: |
| 200 | + $log->addEntry( 'split', $this->title(), $reason, |
| 201 | + array( $this->subject(), |
| 202 | + $original->superthread()->title() |
| 203 | + ) ); |
| 204 | + break; |
| 205 | + case Threads::CHANGE_EDITED_SUBJECT: |
| 206 | + $log->addEntry( 'subjectedit', $this->title(), $reason, |
| 207 | + array( $original->subject(), $this->subject() ) ); |
| 208 | + break; |
| 209 | + case Threads::CHANGE_MERGED_TO: |
| 210 | + $oldParent = $change_object->dbVersion->isTopmostThread() |
| 211 | + ? '' |
| 212 | + : $change_object->dbVersion->superthread()->title(); |
| 213 | + |
| 214 | + |
| 215 | + $log->addEntry( 'merge', $this->title(), $reason, |
| 216 | + array( $oldParent, $change_object->superthread()->title() ) ); |
| 217 | + break; |
| 218 | + case Threads::CHANGE_ADJUSTED_SORTKEY: |
| 219 | + $log->addEntry( 'resort', $this->title(), $reason, |
| 220 | + array( $original->sortkey(), $this->sortkey() ) ); |
| 221 | + } |
| 222 | + } |
| 223 | + |
178 | 224 | function updateEditedness( $change_type ) { |
179 | 225 | global $wgUser; |
180 | 226 | |
— | — | @@ -216,6 +262,9 @@ |
217 | 263 | |
218 | 264 | // Touch the talk page, too. |
219 | 265 | $this->article()->getTitle()->invalidateCache(); |
| 266 | + |
| 267 | + $this->dbVersion = clone $this; |
| 268 | + unset( $this->dbVersion->dbVersion ); |
220 | 269 | } |
221 | 270 | |
222 | 271 | function getRow() { |
— | — | @@ -329,11 +378,9 @@ |
330 | 379 | $this->articleNamespace = $new_articleNamespace; |
331 | 380 | $this->articleTitle = $new_articleTitle; |
332 | 381 | $this->articleId = $new_articleID; |
| 382 | + $this->article = null; |
| 383 | + |
333 | 384 | $this->commitRevision( Threads::CHANGE_MOVED_TALKPAGE, null, $reason ); |
334 | | - |
335 | | - # Log the move |
336 | | - $log = new LogPage( 'liquidthreads' ); |
337 | | - $log->addEntry( 'move', $this->title(), $reason, array( $oldTitle, $newTitle ) ); |
338 | 385 | |
339 | 386 | if ( $leave_trace ) { |
340 | 387 | $this->leaveTrace( $reason, $oldTitle, $newTitle ); |
— | — | @@ -355,7 +402,7 @@ |
356 | 403 | // Make the article edit. |
357 | 404 | $traceTitle = Threads::newThreadTitle( $this->subject(), new Article_LQT_Compat( $oldTitle ) ); |
358 | 405 | $redirectArticle = new Article_LQT_Compat( $traceTitle ); |
359 | | - $redirectArticle->doEdit( $redirectText, $reason, EDIT_NEW ); |
| 406 | + $redirectArticle->doEdit( $redirectText, $reason, EDIT_NEW | EDIT_SUPPRESS_RC ); |
360 | 407 | |
361 | 408 | // Add the trace thread to the tracking table. |
362 | 409 | $thread = Thread::create( $redirectArticle, new Article_LQT_Compat( $oldTitle ), null, |
— | — | @@ -478,6 +525,9 @@ |
479 | 526 | } |
480 | 527 | |
481 | 528 | $this->doLazyUpdates( $line ); |
| 529 | + |
| 530 | + $this->dbVersion = clone $this; |
| 531 | + unset( $this->dbVersion->dbVersion ); |
482 | 532 | } |
483 | 533 | |
484 | 534 | // Load a list of threads in bulk, including all subthreads. |
— | — | @@ -1210,13 +1260,13 @@ |
1211 | 1261 | |
1212 | 1262 | // On serialization, load all data because it will be different in the DB when we wake up. |
1213 | 1263 | function __sleep() { |
1214 | | - |
1215 | 1264 | $this->loadAllData(); |
1216 | 1265 | |
1217 | 1266 | $fields = array_keys( get_object_vars( $this ) ); |
1218 | 1267 | |
1219 | 1268 | // Filter out article objects, there be dragons (or unserialization problems) |
1220 | | - $fields = array_diff( $fields, array( 'root', 'article', 'summary', 'sleeping' ) ); |
| 1269 | + $fields = array_diff( $fields, array( 'root', 'article', 'summary', 'sleeping', |
| 1270 | + 'dbVersion' ) ); |
1221 | 1271 | |
1222 | 1272 | return $fields; |
1223 | 1273 | } |
— | — | @@ -1301,6 +1351,8 @@ |
1302 | 1352 | public function split( $newSubject, $reason = '', $newSortkey = null ) { |
1303 | 1353 | $oldTopThread = $this->topmostThread(); |
1304 | 1354 | $oldParent = $this->superthread(); |
| 1355 | + |
| 1356 | + $original = $this->dbVersion; |
1305 | 1357 | |
1306 | 1358 | self::recursiveSet( $this, $newSubject, $this, null ); |
1307 | 1359 | |
— | — | @@ -1312,13 +1364,18 @@ |
1313 | 1365 | $bump = false; |
1314 | 1366 | } |
1315 | 1367 | |
| 1368 | + // For logging purposes, will be reset by the time this call returns. |
| 1369 | + $this->dbVersion = $original; |
| 1370 | + |
| 1371 | + $this->commitRevision( Threads::CHANGE_SPLIT, null, $reason, $bump ); |
1316 | 1372 | $oldTopThread->commitRevision( Threads::CHANGE_SPLIT_FROM, $this, $reason ); |
1317 | | - $this->commitRevision( Threads::CHANGE_SPLIT, null, $reason, $bump ); |
1318 | 1373 | } |
1319 | 1374 | |
1320 | 1375 | public function moveToParent( $newParent, $reason = '' ) { |
1321 | 1376 | $newSubject = $newParent->subject(); |
1322 | 1377 | |
| 1378 | + $original = $this->dbVersion; |
| 1379 | + |
1323 | 1380 | $oldTopThread = $newParent->topmostThread(); |
1324 | 1381 | $oldParent = $this->superthread(); |
1325 | 1382 | |
— | — | @@ -1330,6 +1387,8 @@ |
1331 | 1388 | $oldParent->removeReply( $this ); |
1332 | 1389 | } |
1333 | 1390 | |
| 1391 | + $this->dbVersion = $original; |
| 1392 | + |
1334 | 1393 | $oldTopThread->commitRevision( Threads::CHANGE_MERGED_FROM, $this, $reason ); |
1335 | 1394 | $newParent->commitRevision( Threads::CHANGE_MERGED_TO, $this, $reason ); |
1336 | 1395 | } |