r57815 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r57814‎ | r57815 | r57816 >
Date:16:17, 16 October 2009
Author:werdna
Status:deferred
Tags:
Comment:
LiquidThreads: Implement Split / Merge operations in the API. Includes some minor refactoring in core.
Modified paths:
  • /trunk/extensions/LiquidThreads/api/ApiThreadAction.php (modified) (history)
  • /trunk/extensions/LiquidThreads/classes/Thread.php (modified) (history)
  • /trunk/extensions/LiquidThreads/classes/View.php (modified) (history)
  • /trunk/extensions/LiquidThreads/pages/SpecialMergeThread.php (modified) (history)
  • /trunk/extensions/LiquidThreads/pages/SpecialSplitThread.php (modified) (history)

Diff [purge]

Index: trunk/extensions/LiquidThreads/classes/View.php
@@ -341,27 +341,16 @@
342342 } elseif ( !$thread ) {
343343 $t = null;
344344
345 - $title_subject = $subject;
346 - while ( !$t ) {
347 - try {
348 - if ( $edit_type == 'new' && $title_subject ) {
349 - $t = $this->newThreadTitle( $title_subject );
350 - } elseif ( $edit_type == 'reply' ) {
351 - $t = $this->newReplyTitle( $title_subject, $edit_applies_to );
352 - }
353 -
354 - if ( $t )
355 - break;
356 - } catch ( Exception $e ) { }
357 -
358 - $title_subject = md5( mt_rand() ); // Just a random title
 345+ $subjectOk = Thread::validateSubject( $subject, &$t,
 346+ $edit_applies_to, $this->article );
 347+ if ( ! $subjectOk ) {
359348 $subject = false;
360349 }
361 -
 350+
362351 if ( !$subject && $subject_expected ) {
363352 // Dodgy title
364353 $valid_subject = false;
365 - } else {
 354+ } elseif ( ! $t ) {
366355 try {
367356 if ( $edit_type == 'new' ) {
368357 $t = $this->newThreadTitle( $subject );
Index: trunk/extensions/LiquidThreads/classes/Thread.php
@@ -57,9 +57,9 @@
5858 static function create( $root, $article, $superthread = null,
5959 $type = Threads::TYPE_NORMAL, $subject = '' ) {
6060
61 - $dbw = wfGetDB( DB_MASTER );
62 -
63 - $thread = new Thread( null );
 61+ $dbw = wfGetDB( DB_MASTER );
 62+
 63+ $thread = new Thread( null );
6464
6565 if ( !in_array( $type, self::$VALID_TYPES ) ) {
6666 throw new MWException( __METHOD__ . ": invalid change type $type." );
@@ -808,7 +808,7 @@
809809
810810 $this->replies();
811811
812 - unset( $thread->replies[$thread] );
 812+ unset( $this->replies[$thread] );
813813
814814 // Also, decrement the reply count.
815815 $threadObj = Threads::withId( $thread );
@@ -1047,6 +1047,10 @@
10481048
10491049 function setSubject( $subject ) {
10501050 $this->subject = $subject;
 1051+
 1052+ foreach( $this->replies() as $reply ) {
 1053+ $reply->setSubject( $subject );
 1054+ }
10511055 }
10521056
10531057 // Deprecated, use subject().
@@ -1246,4 +1250,76 @@
12471251 return -1;
12481252 }
12491253 }
 1254+
 1255+ public function split( $newSubject, $reason = '' ) {
 1256+ $oldTopThread = $this->topmostThread();
 1257+ $oldParent = $this->superthread();
 1258+
 1259+ self::recursiveSet( $this, $newSubject, $this, null );
 1260+
 1261+ $oldParent->removeReply( $this );
 1262+
 1263+ $oldTopThread->commitRevision( Threads::CHANGE_SPLIT_FROM, $this, $reason );
 1264+ $this->commitRevision( Threads::CHANGE_SPLIT, null, $reason );
 1265+ }
 1266+
 1267+ public function moveToParent( $newParent, $reason = '' ) {
 1268+ $newSubject = $newParent->subject();
 1269+
 1270+ $oldTopThread = $newParent->topmostThread();
 1271+ $oldParent = $newParent->superthread();
 1272+
 1273+ Thread::recursiveSet( $this, $newSubject, $newParent, $newParent );
 1274+
 1275+ $newParent->addReply( $this );
 1276+
 1277+ if ( $oldParent ) {
 1278+ $oldParent->removeReply( $this );
 1279+ }
 1280+
 1281+ $oldTopThread->commitRevision( Threads::CHANGE_MERGED_FROM, $this, $reason );
 1282+ $newParent->commitRevision( Threads::CHANGE_MERGED_TO, $this, $reason );
 1283+ }
 1284+
 1285+ static function recursiveSet( $thread, $subject, $ancestor, $superthread = false ) {
 1286+ $thread->setSubject( $subject );
 1287+ $thread->setAncestor( $ancestor->id() );
 1288+
 1289+ if ( $superthread !== false ) {
 1290+ $thread->setSuperThread( $superthread );
 1291+ }
 1292+
 1293+ $thread->save();
 1294+
 1295+ foreach ( $thread->replies() as $subThread ) {
 1296+ self::recursiveSet( $subThread, $subject, $ancestor );
 1297+ }
 1298+ }
 1299+
 1300+ static function validateSubject( $subject, &$title, $replyTo, $article ) {
 1301+ $t = null;
 1302+ $ok = true;
 1303+
 1304+ while ( !$t ) {
 1305+ try {
 1306+ global $wgUser;
 1307+
 1308+ if ( !$replyTo && $subject ) {
 1309+ $t = Threads::newThreadTitle( $subject, $article );
 1310+ } elseif ( $replyTo ) {
 1311+ $t = Threads::newReplyTitle( $replyTo, $wgUser );
 1312+ }
 1313+
 1314+ if ( $t )
 1315+ break;
 1316+ } catch ( Exception $e ) { }
 1317+
 1318+ $subject = md5( mt_rand() ); // Just a random title
 1319+ $ok = false;
 1320+ }
 1321+
 1322+ $title = $t;
 1323+
 1324+ return $ok;
 1325+ }
12501326 }
Index: trunk/extensions/LiquidThreads/pages/SpecialSplitThread.php
@@ -42,21 +42,10 @@
4343 $newSubject = $data['subject'];
4444 $reason = $data['reason'];
4545
46 - $oldTopThread = $this->mThread->topmostThread();
47 - $oldParent = $this->mThread->superthread();
48 -
49 - $this->recursiveSet( $this->mThread, $newSubject, $this->mThread, 'first' );
 46+ $this->mThread->split( $newSubject, $reason );
5047
51 - $oldParent->removeReply( $this->mThread );
 48+ $link = LqtView::linkInContext( $this->mThread );
5249
53 - $oldTopThread->commitRevision( Threads::CHANGE_SPLIT_FROM, $this->mThread, $reason );
54 - $this->mThread->commitRevision( Threads::CHANGE_SPLIT, null, $reason );
55 -
56 - $title = clone $this->mThread->article()->getTitle();
57 - $title->setFragment( '#' . $this->mThread->getAnchorName() );
58 -
59 - $link = $this->user->getSkin()->link( $title, $this->mThread->subject() );
60 -
6150 global $wgOut;
6251 $wgOut->addHTML( wfMsgExt( 'lqt-split-success', array( 'parseinline', 'replaceafter' ),
6352 $link ) );
@@ -64,29 +53,17 @@
6554 return true;
6655 }
6756
68 - function recursiveSet( $thread, $subject, $ancestor, $first = false ) {
69 - $thread->setSubject( $subject );
70 - $thread->setAncestor( $ancestor->id() );
71 -
72 - if ( $first ) {
73 - $thread->setSuperThread( null );
74 - }
75 -
76 - $thread->save( );
77 -
78 - foreach ( $thread->replies() as $subThread ) {
79 - $this->recursiveSet( $subThread, $subject, $ancestor );
80 - }
81 - }
82 -
8357 function validateSubject( $target ) {
8458 if ( !$target ) {
8559 return wfMsgExt( 'lqt_split_nosubject', 'parseinline' );
8660 }
87 -
88 - $title = Title::newFromText( $target );
8961
90 - if ( !$title ) {
 62+ $title = null;
 63+ $article = $this->mThread->article();
 64+
 65+ $ok = Thread::validateSubject( $target, &$title, null, $article );
 66+
 67+ if ( !$ok ) {
9168 return wfMsgExt( 'lqt_split_badsubject', 'parseinline' );
9269 }
9370
Index: trunk/extensions/LiquidThreads/pages/SpecialMergeThread.php
@@ -84,32 +84,13 @@
8585 // Load data
8686 $srcThread = $this->mThread;
8787 $dstThread = $this->mDestThread;
88 - $newSubject = $dstThread->subject();
8988 $reason = $data['reason'];
9089
91 - $oldTopThread = $srcThread->topmostThread();
92 - $oldParent = $srcThread->superthread();
93 -
94 - $this->recursiveSet( $srcThread, $newSubject, $dstThread, $dstThread );
95 -
96 - $dstThread->addReply( $srcThread );
 90+ $srcThread->moveToParent( $dstThread, $reason );
9791
98 - if ( $oldParent ) {
99 - $oldParent->removeReply( $srcThread );
100 - }
 92+ $srcLink = LqtView::inContextLink( $srcThread );
 93+ $dstLink = LqtView::inContextLink( $dstThread );
10194
102 - $oldTopThread->commitRevision( Threads::CHANGE_MERGED_FROM, $srcThread, $reason );
103 - $dstThread->commitRevision( Threads::CHANGE_MERGED_TO, $srcThread, $reason );
104 -
105 - $srcTitle = clone $srcThread->article()->getTitle();
106 - $srcTitle->setFragment( '#' . $srcThread->getAnchorName() );
107 -
108 - $dstTitle = clone $dstThread->article()->getTitle();
109 - $dstTitle->setFragment( '#' . $dstThread->getAnchorName() );
110 -
111 - $srcLink = $this->user->getSkin()->link( $srcTitle, $srcThread->subject() );
112 - $dstLink = $this->user->getSkin()->link( $dstTitle, $dstThread->subject() );
113 -
11495 global $wgOut;
11596 $wgOut->addHTML( wfMsgExt( 'lqt-merge-success', array( 'parseinline', 'replaceafter' ),
11697 $srcLink, $dstLink ) );
@@ -117,21 +98,6 @@
11899 return true;
119100 }
120101
121 - function recursiveSet( $thread, $subject, $ancestor, $superthread = false ) {
122 - $thread->setSubject( $subject );
123 - $thread->setAncestor( $ancestor->id() );
124 -
125 - if ( $superthread ) {
126 - $thread->setSuperThread( $superthread );
127 - }
128 -
129 - $thread->save();
130 -
131 - foreach ( $thread->replies() as $subThread ) {
132 - $this->recursiveSet( $subThread, $subject, $ancestor );
133 - }
134 - }
135 -
136102 function getPageName() {
137103 return 'MergeThread';
138104 }
Index: trunk/extensions/LiquidThreads/api/ApiThreadAction.php
@@ -10,6 +10,8 @@
1111 return array(
1212 'markread' => 'actionMarkRead',
1313 'markunread' => 'actionMarkUnread',
 14+ 'split' => 'actionSplit',
 15+ 'merge' => 'actionMerge',
1416 // 'reply', // Not implemented
1517 // 'newtopic', // Not implemented
1618 );
@@ -21,6 +23,9 @@
2224 'threadaction' => 'The action to take',
2325 'token' => 'An edit token (from ?action=query&prop=info&intoken=edit)',
2426 'talkpage' => 'The talkpage to act on (if applicable)',
 27+ 'subject' => 'The subject to set for the new or split thread',
 28+ 'reason' => 'If applicable, the reason/summary for the action',
 29+ 'newparent' => 'If merging a thread, the ID or title for its new parent',
2530 );
2631 }
2732
@@ -40,6 +45,9 @@
4146 ApiBase::PARAM_TYPE => array_keys( $this->getActions() ),
4247 ),
4348 'token' => null,
 49+ 'subject' => null,
 50+ 'reason' => null,
 51+ 'newparent' => null,
4452 );
4553 }
4654
@@ -89,27 +97,156 @@
9098 public function actionMarkRead( $threads, $params ) {
9199 global $wgUser;
92100
 101+ $result = array();
 102+
93103 foreach( $threads as $t ) {
94104 NewMessages::markThreadAsReadByUser( $t, $wgUser );
 105+ $result[] =
 106+ array(
 107+ 'result' => 'Success',
 108+ 'action' => 'markread',
 109+ 'id' => $t->id(),
 110+ 'title' => $t->title()->getPrefixedText()
 111+ );
95112 }
96113
97 - $result = array( 'result' => 'Success', 'action' => 'markread' );
98 -
99 - $this->getResult()->addValue( null, 'threadaction', $result );
 114+ $this->getResult()->setIndexedTagName( $result, 'thread' );
 115+ $this->getResult()->addValue( null, 'threadactions', $result );
100116 }
101117
102118 public function actionMarkUnread( $threads, $params ) {
103119 global $wgUser;
104120
 121+ $result = array();
 122+
105123 foreach( $threads as $t ) {
106124 NewMessages::markThreadAsUnreadByUser( $t, $wgUser );
 125+
 126+ $result[] =
 127+ array(
 128+ 'result' => 'Success',
 129+ 'action' => 'markunread',
 130+ 'id' => $t->id(),
 131+ 'title' => $t->title()->getPrefixedText()
 132+ );
107133 }
108134
109 - $result = array( 'result' => 'Success', 'action' => 'markunread' );
110135
 136+ $this->getResult()->setIndexedTagName( $result, 'thread' );
111137 $this->getResult()->addValue( null, 'threadaction', $result );
112138 }
113139
 140+ public function actionSplit( $threads, $params ) {
 141+ global $wgUser;
 142+
 143+ if ( count($threads) > 1 ) {
 144+ $this->dieUsage( 'You may only split one thread at a time',
 145+ 'too-many-threads' );
 146+ return;
 147+ } elseif ( count($threads) < 1 ) {
 148+ $this->dieUsage( 'You must specify a thread to split',
 149+ 'no-specified-threads' );
 150+ return;
 151+ }
 152+
 153+ $thread = array_pop( $threads );
 154+
 155+ if ( $thread->isTopmostThread() ) {
 156+ $this->dieUsage( 'This thread is already a top-level thread.',
 157+ 'already-top-level' );
 158+ }
 159+
 160+ $title = null;
 161+ $article = $thread->article();
 162+ if ( empty($params['subject'] ) ||
 163+ ! Thread::validateSubject( $params['subject'], &$title, null, $article ) ) {
 164+
 165+ $this->dieUsage( 'No subject, or an invalid subject, was specified',
 166+ 'no-valid-subject' );
 167+ }
 168+
 169+ $subject = $params['subject'];
 170+
 171+ // Pull a reason, if applicable.
 172+ $reason = '';
 173+ if ( !empty($params['reason']) ) {
 174+ $reason = $params['reason'];
 175+ }
 176+
 177+ // Do the split
 178+ $thread->split( $subject, $reason );
 179+
 180+ $result = array();
 181+ $result[] =
 182+ array(
 183+ 'result' => 'Success',
 184+ 'action' => 'split',
 185+ 'id' => $thread->id(),
 186+ 'title' => $thread->title()->getPrefixedText(),
 187+ 'newsubject' => $subject,
 188+ );
 189+
 190+ $this->getResult()->setIndexedTagName( $result, 'thread' );
 191+ $this->getResult()->addValue( null, 'threadaction', $result );
 192+ }
 193+
 194+ public function actionMerge( $threads, $params ) {
 195+ global $wgUser;
 196+
 197+ if ( count( $threads ) < 1 ) {
 198+ $this->dieUsage( 'You must specify a thread to merge',
 199+ 'no-specified-threads' );
 200+ return;
 201+ }
 202+
 203+ if ( empty( $params['newparent'] ) ) {
 204+ $this->dieUsage( 'You must specify a new parent thread to merge beneath',
 205+ 'no-parent-thread' );
 206+ return;
 207+ }
 208+
 209+ $newParent = $params['newparent'];
 210+ if ( is_numeric( $newParent ) ) {
 211+ $newParent = Threads::withId( $newParent );
 212+ } else {
 213+ $title = Title::newFromText( $newParent );
 214+ $article = new Article( $title );
 215+ $newParent = Threads::withRoot( $article );
 216+ }
 217+
 218+ if ( !$newParent ) {
 219+ $this->dieUsage( 'The parent thread you specified was neither the title '.
 220+ 'of a thread, nor a thread ID.', 'invalid-parent-thread' );
 221+ return;
 222+ }
 223+
 224+ // Pull a reason, if applicable.
 225+ $reason = '';
 226+ if ( !empty($params['reason']) ) {
 227+ $reason = $params['reason'];
 228+ }
 229+
 230+ $result = array();
 231+
 232+ foreach( $threads as $thread ) {
 233+ $thread->moveToParent( $newParent, $reason );
 234+ $result[] =
 235+ array(
 236+ 'result' => 'Success',
 237+ 'action' => 'merge',
 238+ 'id' => $thread->id(),
 239+ 'title' => $thread->title()->getPrefixedText(),
 240+ 'new-parent-id' => $newParent->id(),
 241+ 'new-parent-title' => $newParent->title()->getPrefixedText(),
 242+ 'new-ancestor-id' => $newParent->topmostThread()->id(),
 243+ 'new-ancestor-title' => $newParent->topmostThread()->title()->getPrefixedText(),
 244+ );
 245+ }
 246+
 247+ $this->getResult()->setIndexedTagName( $result, 'thread' );
 248+ $this->getResult()->addValue( null, 'threadaction', $result );
 249+ }
 250+
114251 public function getVersion() {
115252 return __CLASS__ . ': $Id: $';
116253 }

Status & tagging log