http://www.mediawiki.org/wiki/Special:Code/MediaWiki/54942
Revision: 54942 Author: werdna Date: 2009-08-13 15:58:17 +0000 (Thu, 13 Aug 2009) Log Message: ----------- * Implement re-merging of threads (opposite operation to "split") (bug 19787) * Fix history display for a large number of actions. * Fix some cases where history logs would be spammed with CHANGE_PARENT_DELETED actions. Modified Paths: -------------- trunk/extensions/LiquidThreads/LiquidThreads.php trunk/extensions/LiquidThreads/classes/DeletionController.php trunk/extensions/LiquidThreads/classes/Thread.php trunk/extensions/LiquidThreads/classes/Threads.php trunk/extensions/LiquidThreads/classes/View.php trunk/extensions/LiquidThreads/i18n/Lqt.alias.php trunk/extensions/LiquidThreads/i18n/Lqt.i18n.php trunk/extensions/LiquidThreads/pages/SpecialSplitThread.php trunk/extensions/LiquidThreads/pages/ThreadActionPage.php trunk/extensions/LiquidThreads/pages/ThreadHistoricalRevisionView.php trunk/extensions/LiquidThreads/pages/ThreadHistoryListingView.php Modified: trunk/extensions/LiquidThreads/LiquidThreads.php =================================================================== --- trunk/extensions/LiquidThreads/LiquidThreads.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/LiquidThreads.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -78,6 +78,7 @@ $wgSpecialPages['MoveThread'] = 'SpecialMoveThread'; $wgSpecialPages['NewMessages'] = 'SpecialNewMessages'; $wgSpecialPages['SplitThread'] = 'SpecialSplitThread'; +$wgSpecialPages['MergeThread'] = 'SpecialMergeThread'; $wgSpecialPageGroups['NewMessages'] = 'wiki'; // Classes @@ -111,6 +112,7 @@ $wgAutoloadClasses['SpecialMoveThread'] = $dir . 'pages/SpecialMoveThread.php'; $wgAutoloadClasses['SpecialNewMessages'] = $dir . 'pages/SpecialNewMessages.php'; $wgAutoloadClasses['SpecialSplitThread'] = "$dir/pages/SpecialSplitThread.php"; +$wgAutoloadClasses['SpecialMergeThread'] = "$dir/pages/SpecialMergeThread.php"; // Backwards-compatibility $wgAutoloadClasses['Article_LQT_Compat'] = $dir . 'compat/LqtCompatArticle.php'; @@ -130,6 +132,9 @@ /** CONFIGURATION SECTION */ +$wgGroupPermissions['user']['lqt-split'] = true; +$wgGroupPermissions['user']['lqt-merge'] = true; + /* Number of days a thread needs to have existed to be considered for summarizing and archival */ $wgLqtThreadArchiveStartDays = 14; Modified: trunk/extensions/LiquidThreads/classes/DeletionController.php =================================================================== --- trunk/extensions/LiquidThreads/classes/DeletionController.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/classes/DeletionController.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -25,7 +25,7 @@ // Avoid orphaning subthreads, update their parentage. foreach( $thread->replies() as $reply ) { $reply->setSuperthread( $thread->superthread() ); - $reply->commitRevision( Threads::CHANGE_PARENT_DELETED, null, $reason ); + $reply->save( ); } return true; Modified: trunk/extensions/LiquidThreads/classes/Thread.php =================================================================== --- trunk/extensions/LiquidThreads/classes/Thread.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/classes/Thread.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -598,13 +598,23 @@ $thread->setSuperThread( $this ); if ( is_array($this->replies) ) { - $this->replies[] = $thread; + $this->replies[$thread->id()] = $thread; } else { $this->replies(); - $this->replies[] = $thread; + $this->replies[$thread->id()] = $thread; } } + function removeReply( $thread ) { + if ( is_object($thread) ) { + $thread = $thread->id(); + } + + $this->replies(); + + unset( $thread->replies[$thread] ); + } + function replies() { if ( !is_null($this->replies) ) { return $this->replies; @@ -945,10 +955,7 @@ function __sleep() { $this->loadAllData(); - // Mark as historical. - $this->isHistorical = true; - $fields = array_keys( get_object_vars( $this ) ); // Filter out article objects, there be dragons (or unserialization problems) @@ -957,6 +964,11 @@ return $fields; } + function __wakeup() { + // Mark as historical. + $this->isHistorical = true; + } + // This is a safety valve that makes sure that the DB is NEVER touched by a historical // thread (even for reading, because the data will be out of date). function dieIfHistorical() { Modified: trunk/extensions/LiquidThreads/classes/Threads.php =================================================================== --- trunk/extensions/LiquidThreads/classes/Threads.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/classes/Threads.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -18,11 +18,15 @@ const CHANGE_SPLIT = 7; const CHANGE_EDITED_SUBJECT = 8; const CHANGE_PARENT_DELETED = 9; + const CHANGE_MERGED_FROM = 10; + const CHANGE_MERGED_TO = 11; + const CHANGE_SPLIT_FROM = 12; static $VALID_CHANGE_TYPES = array( self::CHANGE_EDITED_SUMMARY, self::CHANGE_EDITED_ROOT, self::CHANGE_REPLY_CREATED, self::CHANGE_NEW_THREAD, self::CHANGE_DELETED, self::CHANGE_UNDELETED, self::CHANGE_MOVED_TALKPAGE, self::CHANGE_SPLIT, self::CHANGE_EDITED_SUBJECT, - self::CHANGE_PARENT_DELETED); + self::CHANGE_PARENT_DELETED, self::CHANGE_MERGED_FROM, self::CHANGE_MERGED_TO, + self::CHANGE_SPLIT_FROM ); // Possible values of Thread->editedness. const EDITED_NEVER = 0; Modified: trunk/extensions/LiquidThreads/classes/View.php =================================================================== --- trunk/extensions/LiquidThreads/classes/View.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/classes/View.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -514,12 +514,22 @@ 'enabled' => true ); } - if ( !$thread->isTopmostThread() ) { + if ( !$thread->isTopmostThread() && $this->user->isAllowed( 'lqt-split' ) ) { $splitUrl = SpecialPage::getTitleFor( 'SplitThread', $thread->title()->getPrefixedText() )->getFullURL(); $commands['split'] = array( 'label' => wfMsgExt( 'lqt-thread-split', 'parseinline' ), 'href' => $splitUrl, 'enabled' => true ); } + + if ( $this->user->isAllowed( 'lqt-merge' ) ) { + $mergeParams = $_GET; + $mergeParams['lqt_merge_from'] = $thread->id(); + $mergeUrl = $thread->title()->getFullURL( wfArrayToCGI( $mergeParams ) ); + $label = wfMsgExt( 'lqt-thread-merge', 'parseinline' ); + + $commands['merge'] = array( 'label' => $label, + 'href' => $mergeUrl, 'enabled' => true ); + } return $commands; } @@ -529,12 +539,24 @@ wfLoadExtensionMessages( 'LiquidThreads' ); if ($thread->isHistorical() ) { - // No reply link for historical threads. + // No links for historical threads. return array(); } $commands = array(); + if ( $this->user->isAllowed( 'lqt-merge' ) && + $this->request->getCheck( 'lqt_merge_from' ) ) { + $srcThread = Threads::withId( $this->request->getVal( 'lqt_merge_from' ) ); + $par = $srcThread->title()->getPrefixedText(); + $mergeTitle = SpecialPage::getTitleFor( 'MergeThread', $par ); + $mergeUrl = $mergeTitle->getFullURL( 'dest='.$thread->id() ); + $label = wfMsgExt( 'lqt-thread-merge-to', 'parseinline' ); + + $commands['merge-to'] = array( 'label' => $label, 'href' => $mergeUrl, + 'enabled' => true ); + } + $commands['reply'] = array( 'label' => wfMsgExt( 'lqt_reply', 'parseinline' ), 'href' => $this->talkpageUrl( $this->title, 'reply', $thread ), 'enabled' => true, Modified: trunk/extensions/LiquidThreads/i18n/Lqt.alias.php =================================================================== --- trunk/extensions/LiquidThreads/i18n/Lqt.alias.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/i18n/Lqt.alias.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -14,6 +14,7 @@ 'MoveThread' => array( 'MoveThread' ), 'NewMessages' => array( 'NewMessages' ), 'SplitThread' => array( 'SplitThread' ), + 'MergeThread' => array( 'MergeThread' ), ); /** Arabic (العربية) Modified: trunk/extensions/LiquidThreads/i18n/Lqt.i18n.php =================================================================== --- trunk/extensions/LiquidThreads/i18n/Lqt.i18n.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/i18n/Lqt.i18n.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -48,6 +48,7 @@ 'lqt_from_talk' => 'from $1', 'lqt_newer' => '← newer', 'lqt_older' => 'older →', + 'lqt-history-title' => 'Thread history', 'lqt_hist_comment_edited' => 'Comment text edited', 'lqt_hist_summary_changed' => 'Summary changed', @@ -62,12 +63,27 @@ 'lqt_hist_past_last_page_error' => 'You are beyond the number of pages of history that exist.', 'lqt_hist_tooltip_newer_disabled' => 'This link is disabled because you are on the first page.', 'lqt_hist_tooltip_older_disabled' => 'This link is disabled because you are on the last page.', - 'lqt_hist_split' => 'Split thread', + 'lqt_hist_split' => 'Reply split to a new thread', 'lqt_hist_edited_subject' => 'Edited subject', + 'lqt_hist_merged_from' => 'Reply moved to another thread', + 'lqt_hist_merged_to' => 'Reply moved from another thread', + 'lqt_hist_split_from' => 'Split to a new thread', + 'lqt_revision_as_of' => "Revision as of $2 at $3.", + 'lqt_change_new_thread' => 'This is the thread\'s initial revision.', 'lqt_change_reply_created' => 'The highlighted comment was created in this revision.', 'lqt_change_edited_root' => 'The highlighted comment was edited in this revision.', + 'lqt_change_edited_summary' => "The thread's summary was edited", + 'lqt_change_deleted' => 'This thread or a reply to it was deleted', + 'lqt_change_undeleted' => 'The highlighted post was undeleted', + 'lqt_change_moved' => 'This thread was moved to another discussion page', + 'lqt_change_split' => 'This thread was split from another thread', + 'lqt_change_subject_edited' => 'The subject of this thread was changed', + 'lqt_change_merged_from' => 'A reply to this thread was moved to another thread', + 'lqt_change_merged_to' => 'The highlighted reply was moved from another thread', + 'lqt_change_split_from' => 'A subthread of this thread was split into its own thread', + 'lqt_youhavenewmessages' => 'You have [$1 new messages].', 'lqt_protectedfromreply' => 'This thread has been $1 from being replied to.', 'lqt_protectedfromreply_link' => 'protected', @@ -172,6 +188,19 @@ 'lqt_split_badsubject' => 'The subject you entered is invalid.', 'lqt-no-threads' => 'There are no threads on this page yet.', + // Rights + 'right-lqt-split' => 'Split threads', + 'right-lqt-merge' => 'Merge threads', + + // Merging + 'lqt-thread-merge' => 'Merge into another thread', + 'lqt-thread-merge-to' => 'Merge into this thread', + 'lqt_merge_thread' => 'Merge thread', + 'lqt-thread-merge-source' => 'Source thread:', + 'lqt-thread-merge-dest' => 'Destination thread:', + 'lqt-merge-submit' => 'Merge', + 'lqt-merge-success' => 'You have successfully merged the thread $1 to underneath $2.', + // Logging 'lqt-log-name' => 'Threaded discussion log', 'lqt-log-header' => 'This log details actions taken on discussion threads.', Modified: trunk/extensions/LiquidThreads/pages/SpecialSplitThread.php =================================================================== --- trunk/extensions/LiquidThreads/pages/SpecialSplitThread.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/pages/SpecialSplitThread.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -28,13 +28,23 @@ return wfMsg( 'lqt_split_thread' ); } + protected function getRightRequirement() { return 'lqt-split'; } + function trySubmit( $data ) { // Load data $newSubject = $data['subject']; $reason = $data['reason']; + + $oldTopThread = $this->mThread->topmostThread(); + $oldParent = $this->mThread->superthread(); - $this->recursiveSet( $this->mThread, $newSubject, $this->mThread, $reason, 'first' ); + $this->recursiveSet( $this->mThread, $newSubject, $this->mThread, 'first' ); + $oldParent->removeReply( $this->mThread ); + + $oldTopThread->commitRevision( Threads::CHANGE_SPLIT_FROM, $this->mThread, $reason ); + $this->mThread->commitRevision( Threads::CHANGE_SPLIT, null, $reason ); + $title = clone $this->mThread->article()->getTitle(); $title->setFragment( '#'.$this->mThread->getAnchorName() ); @@ -47,7 +57,7 @@ return true; } - function recursiveSet( $thread, $subject, $ancestor, $reason, $first = false ) { + function recursiveSet( $thread, $subject, $ancestor, $first = false ) { $thread->setSubject( $subject ); $thread->setAncestor( $ancestor->id() ); @@ -55,7 +65,7 @@ $thread->setSuperThread( null ); } - $thread->commitRevision( Threads::CHANGE_SPLIT, null, $reason ); + $thread->save( ); foreach( $thread->replies() as $subThread ) { $this->recursiveSet( $subThread, $subject, $ancestor, $reason ); Modified: trunk/extensions/LiquidThreads/pages/ThreadActionPage.php =================================================================== --- trunk/extensions/LiquidThreads/pages/ThreadActionPage.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/pages/ThreadActionPage.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -4,7 +4,7 @@ protected $user, $output, $request, $title, $mThread; function __construct() { - parent::__construct( $this->getPageName() ); + parent::__construct( $this->getPageName(), $this->getRightRequirement() ); $this->includable( false ); global $wgOut, $wgUser, $wgRequest; @@ -16,31 +16,49 @@ abstract function getPageName(); abstract function getFormFields(); + + protected function getRightRequirement() { return ''; } function execute( $par ) { wfLoadExtensionMessages( 'LiquidThreads' ); - global $wgOut; + global $wgOut, $wgUser; + if ( !$this->userCanExecute( $wgUser ) ) { + $this->displayRestrictionError(); + return; + } + // Page title $wgOut->setPageTitle( $this->getDescription() ); + if ( !$this->checkParameters($par) ) { + return; + } + + $form = $this->buildForm(); + $form->show(); + } + + // Loads stuff like the thread and so on + function checkParameters( $par ) { // Handle parameter $this->mTarget = $par; if ( $par === null || $par === "" ) { wfLoadExtensionMessages( 'LiquidThreads' ); $this->output->addHTML( wfMsg( 'lqt_threadrequired' ) ); - return; + return false; } + $thread = Threads::withRoot( new Article( Title::newFromURL( $par ) ) ); if ( !$thread ) { $this->output->addHTML( wfMsg( 'lqt_nosuchthread' ) ); - return; + return false; } + $this->mThread = $thread; - $form = $this->buildForm(); - $form->show(); + return true; } abstract function getSubmitText(); Modified: trunk/extensions/LiquidThreads/pages/ThreadHistoricalRevisionView.php =================================================================== --- trunk/extensions/LiquidThreads/pages/ThreadHistoricalRevisionView.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/pages/ThreadHistoricalRevisionView.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -21,6 +21,27 @@ return $class; } } + + function getMessageForChangeType( $ct ) { + static $messages = array( + Threads::CHANGE_NEW_THREAD => 'lqt_change_new_thread', + Threads::CHANGE_REPLY_CREATED => 'lqt_change_reply_created', + Threads::CHANGE_DELETED => 'lqt_change_deleted', + Threads::CHANGE_UNDELETED => 'lqt_change_undeleted', + Threads::CHANGE_MOVED_TALKPAGE => 'lqt_change_moved', + Threads::CHANGE_SPLIT => 'lqt_change_split', + Threads::CHANGE_EDITED_SUBJECT => 'lqt_change_edited_subject', + Threads::CHANGE_MERGED_FROM => 'lqt_change_merged_from', + Threads::CHANGE_MERGED_TO => 'lqt_change_merged_to', + Threads::CHANGE_SPLIT_FROM => 'lqt_change_split_from', + ); + + if ( isset($messages[$ct]) ) { + return $messages[$ct]; + } + + return ''; + } function showHistoryInfo() { global $wgLang; @@ -38,17 +59,18 @@ $html .= '<br/>'; $ct = $this->mDisplayRevision->getChangeType(); - if ( $ct == Threads::CHANGE_NEW_THREAD ) { - $msg = wfMsgExt( 'lqt_change_new_thread', 'parseinline' ); - } else if ( $ct == Threads::CHANGE_REPLY_CREATED ) { - $msg = wfMsgExt( 'lqt_change_reply_created', 'parseinline' ); - } else if ( $ct == Threads::CHANGE_EDITED_ROOT ) { + + $msg = ''; + if ( $ct == Threads::CHANGE_EDITED_ROOT ) { $diff_link = $this->diffPermalink( $this->thread, wfMsgExt( 'diff', 'parseinline' ), $this->mDisplayRevision ); $msg = wfMsgExt( 'lqt_change_edited_root', 'parseinline' ) . " [$diff_link]"; + } else { + $msg = wfMsgExt( $this->getMessageForChangeType($ct), 'parseinline' ); } + $html .= $msg; $html = Xml::tags( 'div', array( 'class' => 'lqt_history_info' ), $html ); Modified: trunk/extensions/LiquidThreads/pages/ThreadHistoryListingView.php =================================================================== --- trunk/extensions/LiquidThreads/pages/ThreadHistoryListingView.php 2009-08-13 15:04:43 UTC (rev 54941) +++ trunk/extensions/LiquidThreads/pages/ThreadHistoryListingView.php 2009-08-13 15:58:17 UTC (rev 54942) @@ -56,6 +56,9 @@ Threads::CHANGE_MOVED_TALKPAGE => wfMsgNoTrans( 'lqt_hist_moved_talkpage' ), Threads::CHANGE_EDITED_SUBJECT => wfMsgNoTrans( 'lqt_hist_edited_subject' ), Threads::CHANGE_SPLIT => wfMsgNoTrans( 'lqt_hist_split' ), + Threads::CHANGE_MERGED_FROM => wfMsgNoTrans( 'lqt_hist_merged_from' ), + Threads::CHANGE_MERGED_TO => wfMsgNoTrans( 'lqt_hist_merged_to' ), + Threads::CHANGE_SPLIT_FROM => wfMsgNoTrans( 'lqt_hist_split_from' ), ); } @@ -113,7 +116,7 @@ return $sk->userLink( $row->th_user, $row->th_user_text ) . ' ' . $sk->userToolLinks( $row->th_user, $row->th_user_text ); case 'th_change_type': - return self::$change_names[$value]; + return $wgOut->parseInline( self::$change_names[$value] ); case 'th_change_comment': return $sk->commentBlock( $value ); default: _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs