Index: trunk/extensions/LiquidThreads/lqt-schema-change-3.sql |
— | — | @@ -1,13 +0,0 @@ |
2 | | -alter table thread add column thread_ancestor int(8) unsigned not null; |
3 | | -alter table thread add column thread_parent int(8) unsigned null; |
4 | | -alter table thread add index thread_ancestor (thread_ancestor); |
5 | | - |
6 | | -update thread set thread_ancestor = substring_index(thread_path, ".", 1), |
7 | | - thread_parent = substring_index(substring_index(thread_path, ".", -2), ".", 1 ) |
8 | | -where locate(".", thread_path) != 0; |
9 | | - |
10 | | -update thread set thread_ancestor = substring_index(thread_path, ".", 1), |
11 | | - thread_parent = null |
12 | | -where locate(".", thread_path) = 0; |
13 | | - |
14 | | -alter table thread drop column thread_path; |
Index: trunk/extensions/LiquidThreads/lqt-schema-change-4.sql |
— | — | @@ -1,4 +0,0 @@ |
2 | | -alter table thread change thread_timestamp thread_modified char(14) binary NOT NULL default ''; |
3 | | -alter table thread add column thread_created char(14) binary NOT NULL default ''; |
4 | | -update thread set thread_created = thread_modified; |
5 | | -alter table thread add index thread_created (thread_created); |
Index: trunk/extensions/LiquidThreads/lqt-schema-change-5.sql |
— | — | @@ -1,13 +0,0 @@ |
2 | | -alter table thread add column thread_editedness int(1) NOT NULL default 0; |
3 | | - |
4 | | -update thread join thread as child on child.thread_parent = thread.thread_id set thread.thread_editedness = 1; |
5 | | - |
6 | | -create temporary table counts ( thread_id int(8) unsigned, revision_count int(8) unsigned, author_count int(8) unsigned, rev_user int(8) unsigned ); |
7 | | - |
8 | | -insert into counts (thread_id, revision_count, author_count, rev_user) select thread_id, count(thread_id), count(distinct rev_user), rev_user from thread join revision on rev_page = thread_root group by thread_id; |
9 | | - |
10 | | -update thread join counts on thread.thread_id = counts.thread_id set thread_editedness = 2 where revision_count > 1; |
11 | | - |
12 | | -update thread join counts on thread.thread_id = counts.thread_id set thread_editedness = 3 where author_count > 1 or (rev_user = 0 and revision_count > 1); |
13 | | - |
14 | | -drop table counts; |
Index: trunk/extensions/LiquidThreads/lqt-schema-change-6.sql |
— | — | @@ -1 +0,0 @@ |
2 | | -alter table thread add index thread_summary_page (thread_summary_page); |
Index: trunk/extensions/LiquidThreads/lqt-schema-change-1.sql |
— | — | @@ -1,5 +0,0 @@ |
2 | | -update thread, page set thread_article_title=page_title, thread_article_namespace=page_namespace where page_id=thread_article and thread_article is not null and thread_article != 0; |
3 | | - |
4 | | -alter table thread drop column thread_article; |
5 | | -alter table thread modify thread_article_namespace not null; |
6 | | -alter table thread modify thread_article_title varchar(255) binary not null; |
Index: trunk/extensions/LiquidThreads/lqt-schema-change-2.sql |
— | — | @@ -1,4 +0,0 @@ |
2 | | -update page set page_namespace=90 where page_namespace=16; |
3 | | -update page set page_namespace=91 where page_namespace=17; |
4 | | -update page set page_namespace=92 where page_namespace=18; |
5 | | -update page set page_namespace=93 where page_namespace=19; |
Index: trunk/extensions/LiquidThreads/pages/TalkpageView.php |
— | — | @@ -4,7 +4,7 @@ |
5 | 5 | |
6 | 6 | class TalkpageView extends LqtView { |
7 | 7 | /* Added to SkinTemplateTabs hook in TalkpageView::show(). */ |
8 | | - function customizeTabs( $skintemplate, $content_actions ) { |
| 8 | + function customizeTabs( $skintemplate, &$content_actions ) { |
9 | 9 | // The arguments are passed in by reference. |
10 | 10 | unset( $content_actions['edit'] ); |
11 | 11 | unset( $content_actions['viewsource'] ); |
— | — | @@ -23,15 +23,6 @@ |
24 | 24 | return true; |
25 | 25 | } |
26 | 26 | |
27 | | - function permalinksForThreads( $threads, $method = null, $operand = null ) { |
28 | | - $permalinks = array(); |
29 | | - foreach ( $threads as $t ) { |
30 | | - $l = $t->subjectWithoutIncrement(); |
31 | | - $permalinks[] = self::permalink( $t, $l, $method, $operand ); |
32 | | - } |
33 | | - return $permalinks; |
34 | | - } |
35 | | - |
36 | 27 | function showHeader() { |
37 | 28 | /* Show the contents of the actual talkpage article if it exists. */ |
38 | 29 | |
— | — | @@ -111,7 +102,7 @@ |
112 | 103 | $subject = Xml::tags( 'a', array( 'href' => $anchor ), $subject ); |
113 | 104 | $row .= Xml::tags( 'td', null, $subject ); |
114 | 105 | |
115 | | - $author = $thread->root()->originalAuthor(); |
| 106 | + $author = $thread->author(); |
116 | 107 | $authorLink = $sk->userLink( $author->getID(), $author->getName() ); |
117 | 108 | $row .= Xml::tags( 'td', null, $authorLink ); |
118 | 109 | |
— | — | @@ -140,23 +131,13 @@ |
141 | 132 | return $html; |
142 | 133 | } |
143 | 134 | |
144 | | - function getArchiveWidget( $threads ) { |
| 135 | + function getArchiveWidget( ) { |
145 | 136 | wfLoadExtensionMessages( 'LiquidThreads' ); |
146 | | - |
147 | | - $threadlinks = self::permalinksForThreads( $threads ); |
148 | | - |
149 | | - if ( count( $threadlinks ) > 0 ) { |
150 | | - $url = $this->talkpageUrl( $this->title, 'talkpage_archive' ); |
151 | | - |
152 | | - $html = ''; |
153 | | - $html = Xml::tags( 'h2', array( 'class' => 'lqt_recently_archived' ), |
154 | | - wfMsgExt( 'lqt_recently_archived', 'parseinline' ) ); |
155 | | - $html .= $this->getList( 'ul', '', '', $threadlinks ); |
156 | | - $html = Xml::tags( 'div', array( 'class' => 'lqt_archive_teaser' ), $html ); |
157 | | - return $html; |
158 | | - } |
159 | | - |
160 | | - return ''; |
| 137 | + $url = $this->talkpageUrl( $this->title, 'talkpage_archive' ); |
| 138 | + |
| 139 | + $html = ''; |
| 140 | + $html = Xml::tags( 'div', array( 'class' => 'lqt_archive_teaser' ), $html ); |
| 141 | + return $html; |
161 | 142 | } |
162 | 143 | |
163 | 144 | function showTalkpageViewOptions( $article ) { |
— | — | @@ -186,7 +167,7 @@ |
187 | 168 | $html .= Xml::label( wfMsg( 'lqt_sorting_order' ), 'lqt_sort_select' ) . ' '; |
188 | 169 | |
189 | 170 | $sortOrderSelect = |
190 | | - new XmlSelect( 'lqt_order', 'lqt_sort_select', $this->sort_order ); |
| 171 | + new XmlSelect( 'lqt_order', 'lqt_sort_select', $this->getSortType() ); |
191 | 172 | |
192 | 173 | $sortOrderSelect->setAttribute( 'class', 'lqt_sort_select' ); |
193 | 174 | $sortOrderSelect->addOption( wfMsg( 'lqt_sort_newest_changes' ), |
— | — | @@ -223,7 +204,22 @@ |
224 | 205 | |
225 | 206 | $this->output->addHTML( $html ); |
226 | 207 | } |
| 208 | + } |
| 209 | + |
| 210 | + function getArchiveTeaser() { |
| 211 | + $archiveBrowseLink = $this->talkpageLink( $this->title, |
| 212 | + wfMsgExt( 'lqt_browse_archive_without_recent', 'parseinline' ), |
| 213 | + 'talkpage_archive' ); |
| 214 | + $archiveBrowseLink = Xml::tags( 'div', array( 'class' => 'lqt_browse_archive' ), |
| 215 | + $archiveBrowseLink ); |
| 216 | + $archiveBrowseLink = Xml::tags( 'div', array( 'class' => 'lqt_archive_teaser_empty' ), |
| 217 | + $archiveBrowseLink ); |
| 218 | + |
| 219 | + $archiveWidget = $this->getArchiveWidget( $recently_archived_threads ); |
227 | 220 | |
| 221 | + $html = Xml::tags( 'div', array( 'class' => 'lqt_toc_archive_wrapper' ), |
| 222 | + $archiveBrowseLink . $toc . |
| 223 | + $archiveWidget ); |
228 | 224 | } |
229 | 225 | |
230 | 226 | function show() { |
— | — | @@ -253,40 +249,204 @@ |
254 | 250 | $this->output->addHTML( Xml::tags( 'strong', null, $newThreadLink ) ); |
255 | 251 | } |
256 | 252 | |
257 | | - $queryType = |
258 | | - $wgRequest->getBool( 'lqt_show_deleted_threads' ) |
259 | | - ? 'fresh' : 'fresh-undeleted'; |
260 | | - $threads = $this->queries->query( $queryType ); |
261 | | - |
262 | | - $archiveBrowseLink = $this->talkpageLink( $this->title, |
263 | | - wfMsgExt( 'lqt_browse_archive_without_recent', 'parseinline' ), |
264 | | - 'talkpage_archive' ); |
265 | | - $archiveBrowseLink = Xml::tags( 'div', array( 'class' => 'lqt_browse_archive' ), |
266 | | - $archiveBrowseLink ); |
267 | | - $archiveBrowseLink = Xml::tags( 'div', array( 'class' => 'lqt_archive_teaser_empty' ), |
268 | | - $archiveBrowseLink ); |
| 253 | + $pager = $this->getPager(); |
269 | 254 | |
270 | | - $recently_archived_threads = $this->queries->query( 'recently-archived' ); |
| 255 | + $threads = $this->getPageThreads( $pager ); |
271 | 256 | |
| 257 | +// $html .= $this->getArchiveWidget(); |
| 258 | + |
272 | 259 | $toc = ''; |
273 | | - if ( count( $threads ) > 1 || count( $recently_archived_threads ) > 0 ) { |
| 260 | + if ( count( $threads ) > 1 ) { |
274 | 261 | $toc = $this->getTOC( $threads ); |
275 | 262 | } |
276 | 263 | |
277 | | - $archiveWidget = $this->getArchiveWidget( $recently_archived_threads ); |
278 | | - |
279 | | - $html = Xml::tags( 'div', array( 'class' => 'lqt_toc_archive_wrapper' ), |
280 | | - $archiveBrowseLink . $toc . |
281 | | - $archiveWidget ); |
282 | | - |
283 | 264 | $html .= Xml::element( 'br', array( 'style' => 'clear: both;' ) ); |
284 | 265 | |
| 266 | + $html .= $pager->getNavigationBar(); |
| 267 | + |
285 | 268 | $this->output->addHTML( $html ); |
286 | 269 | |
287 | 270 | foreach ( $threads as $t ) { |
288 | 271 | $this->showThread( $t ); |
289 | 272 | } |
290 | 273 | |
| 274 | + $this->output->addHTML( $pager->getNavigationBar() ); |
| 275 | + |
291 | 276 | return false; |
292 | 277 | } |
| 278 | + |
| 279 | + function getPager() { |
| 280 | + $showDeleted = $this->request->getBool( 'lqt_show_deleted_threads' ); |
| 281 | + $showDeleted = $showDeleted && $this->user->isAllowed( 'deletedhistory' ); |
| 282 | + |
| 283 | + $sortType = $this->getSortType(); |
| 284 | + return new LqtDiscussionPager( $this->article, $sortType, $showDeleted ); |
| 285 | + } |
| 286 | + |
| 287 | + function getPageThreads( $pager ) { |
| 288 | + $rows = $pager->getRows(); |
| 289 | + |
| 290 | + return Thread::bulkLoad( $rows ); |
| 291 | + } |
| 292 | + |
| 293 | + function getSortType() { |
| 294 | + // Determine sort order |
| 295 | + if ( $this->methodApplies( 'talkpage_sort_order' ) ) { |
| 296 | + // Sort order is explicitly specified through UI |
| 297 | + $lqt_order = $this->request->getVal( 'lqt_order' ); |
| 298 | + switch( $lqt_order ) { |
| 299 | + case 'nc': |
| 300 | + return LQT_NEWEST_CHANGES; |
| 301 | + case 'nt': |
| 302 | + return LQT_NEWEST_THREADS; |
| 303 | + case 'ot': |
| 304 | + return LQT_OLDEST_THREADS; |
| 305 | + } |
| 306 | + } else { |
| 307 | + // Sort order set in user preferences overrides default |
| 308 | + $user_order = $this->user->getOption( 'lqt_sort_order' ) ; |
| 309 | + if ( $user_order ) { |
| 310 | + return $user_order; |
| 311 | + } |
| 312 | + } |
| 313 | + |
| 314 | + // Default |
| 315 | + return LQT_NEWEST_CHANGES; |
| 316 | + } |
293 | 317 | } |
| 318 | + |
| 319 | +class LqtDiscussionPager extends IndexPager { |
| 320 | + |
| 321 | + function __construct( $article, $orderType, $showDeleted ) { |
| 322 | + $this->article = $article; |
| 323 | + $this->orderType = $orderType; |
| 324 | + $this->showDeleted = $showDeleted; |
| 325 | + |
| 326 | + parent::__construct(); |
| 327 | + } |
| 328 | + |
| 329 | + function getQueryInfo() { |
| 330 | + $queryInfo = |
| 331 | + array( |
| 332 | + 'tables' => array( 'thread' ), |
| 333 | + 'fields' => '*', |
| 334 | + 'conds' => |
| 335 | + array( |
| 336 | + Threads::articleClause( $this->article ), |
| 337 | + Threads::topLevelClause(), |
| 338 | + ), |
| 339 | + ); |
| 340 | + |
| 341 | + if ( !$this->showDeleted ) { |
| 342 | + $queryInfo['where']['thread_deleted'] = 0; |
| 343 | + } |
| 344 | + |
| 345 | + return $queryInfo; |
| 346 | + } |
| 347 | + |
| 348 | + // Adapted from getBody(). |
| 349 | + function getRows() { |
| 350 | + if ( !$this->mQueryDone ) { |
| 351 | + $this->doQuery(); |
| 352 | + } |
| 353 | + |
| 354 | + # Don't use any extra rows returned by the query |
| 355 | + $numRows = min( $this->mResult->numRows(), $this->mLimit ); |
| 356 | + |
| 357 | + $rows = array(); |
| 358 | + |
| 359 | + if ( $numRows ) { |
| 360 | + if ( $this->mIsBackwards ) { |
| 361 | + for ( $i = $numRows - 1; $i >= 0; $i-- ) { |
| 362 | + $this->mResult->seek( $i ); |
| 363 | + $row = $this->mResult->fetchObject(); |
| 364 | + $rows[] = $row; |
| 365 | + } |
| 366 | + } else { |
| 367 | + $this->mResult->seek( 0 ); |
| 368 | + for ( $i = 0; $i < $numRows; $i++ ) { |
| 369 | + $row = $this->mResult->fetchObject(); |
| 370 | + $rows[] = $row; |
| 371 | + } |
| 372 | + } |
| 373 | + } |
| 374 | + |
| 375 | + return $rows; |
| 376 | + } |
| 377 | + |
| 378 | + function formatRow( $row ) { |
| 379 | + // No-op, we get the list of rows from getRows() |
| 380 | + } |
| 381 | + |
| 382 | + function getIndexField() { |
| 383 | + switch( $this->orderType ) { |
| 384 | + case LQT_NEWEST_CHANGES: |
| 385 | + return 'thread_modified'; |
| 386 | + case LQT_OLDEST_THREADS: |
| 387 | + case LQT_NEWEST_THREADS: |
| 388 | + return 'thread_created'; |
| 389 | + default: |
| 390 | + throw new MWException( "Unknown sort order ".$this->orderType ); |
| 391 | + } |
| 392 | + } |
| 393 | + |
| 394 | + function getDefaultDirections() { |
| 395 | + switch( $this->orderType ) { |
| 396 | + case LQT_NEWEST_CHANGES: |
| 397 | + case LQT_NEWEST_THREADS: |
| 398 | + return true; // Descending |
| 399 | + case LQT_OLDEST_THREADS: |
| 400 | + return false; // Ascending |
| 401 | + default: |
| 402 | + throw new MWException( "Unknown sort order ".$this->orderType ); |
| 403 | + } |
| 404 | + } |
| 405 | + |
| 406 | + /** |
| 407 | + * A navigation bar with images |
| 408 | + * Stolen from TablePager because it's pretty. |
| 409 | + */ |
| 410 | + function getNavigationBar() { |
| 411 | + global $wgStylePath, $wgContLang; |
| 412 | + |
| 413 | + if ( !$this->isNavigationBarShown() ) return ''; |
| 414 | + |
| 415 | + $path = "$wgStylePath/common/images"; |
| 416 | + $labels = array( |
| 417 | + 'first' => 'table_pager_first', |
| 418 | + 'prev' => 'table_pager_prev', |
| 419 | + 'next' => 'table_pager_next', |
| 420 | + 'last' => 'table_pager_last', |
| 421 | + ); |
| 422 | + $images = array( |
| 423 | + 'first' => $wgContLang->isRTL() ? 'arrow_last_25.png' : 'arrow_first_25.png', |
| 424 | + 'prev' => $wgContLang->isRTL() ? 'arrow_right_25.png' : 'arrow_left_25.png', |
| 425 | + 'next' => $wgContLang->isRTL() ? 'arrow_left_25.png' : 'arrow_right_25.png', |
| 426 | + 'last' => $wgContLang->isRTL() ? 'arrow_first_25.png' : 'arrow_last_25.png', |
| 427 | + ); |
| 428 | + $disabledImages = array( |
| 429 | + 'first' => $wgContLang->isRTL() ? 'arrow_disabled_last_25.png' : 'arrow_disabled_first_25.png', |
| 430 | + 'prev' => $wgContLang->isRTL() ? 'arrow_disabled_right_25.png' : 'arrow_disabled_left_25.png', |
| 431 | + 'next' => $wgContLang->isRTL() ? 'arrow_disabled_left_25.png' : 'arrow_disabled_right_25.png', |
| 432 | + 'last' => $wgContLang->isRTL() ? 'arrow_disabled_first_25.png' : 'arrow_disabled_last_25.png', |
| 433 | + ); |
| 434 | + |
| 435 | + $linkTexts = array(); |
| 436 | + $disabledTexts = array(); |
| 437 | + foreach ( $labels as $type => $label ) { |
| 438 | + $msgLabel = wfMsgHtml( $label ); |
| 439 | + $linkTexts[$type] = "<img src=\"$path/{$images[$type]}\" alt=\"$msgLabel\"/><br/>$msgLabel"; |
| 440 | + $disabledTexts[$type] = "<img src=\"$path/{$disabledImages[$type]}\" alt=\"$msgLabel\"/><br/>$msgLabel"; |
| 441 | + } |
| 442 | + $links = $this->getPagingLinks( $linkTexts, $disabledTexts ); |
| 443 | + |
| 444 | + $navClass = htmlspecialchars( $this->getNavClass() ); |
| 445 | + $s = "<table class=\"$navClass\" align=\"center\" cellpadding=\"3\"><tr>\n"; |
| 446 | + $cellAttrs = 'valign="top" align="center" width="' . 100 / count( $links ) . '%"'; |
| 447 | + foreach ( $labels as $type => $label ) { |
| 448 | + $s .= "<td $cellAttrs>{$links[$type]}</td>\n"; |
| 449 | + } |
| 450 | + $s .= "</tr></table>\n"; |
| 451 | + return $s; |
| 452 | + } |
| 453 | +} |
Index: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-3.sql |
— | — | @@ -0,0 +1,13 @@ |
| 2 | +alter table thread add column thread_ancestor int(8) unsigned not null; |
| 3 | +alter table thread add column thread_parent int(8) unsigned null; |
| 4 | +alter table thread add index thread_ancestor (thread_ancestor); |
| 5 | + |
| 6 | +update thread set thread_ancestor = substring_index(thread_path, ".", 1), |
| 7 | + thread_parent = substring_index(substring_index(thread_path, ".", -2), ".", 1 ) |
| 8 | +where locate(".", thread_path) != 0; |
| 9 | + |
| 10 | +update thread set thread_ancestor = substring_index(thread_path, ".", 1), |
| 11 | + thread_parent = null |
| 12 | +where locate(".", thread_path) = 0; |
| 13 | + |
| 14 | +alter table thread drop column thread_path; |
Property changes on: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-3.sql |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 15 | + native |
Index: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-4.sql |
— | — | @@ -0,0 +1,4 @@ |
| 2 | +alter table thread change thread_timestamp thread_modified char(14) binary NOT NULL default ''; |
| 3 | +alter table thread add column thread_created char(14) binary NOT NULL default ''; |
| 4 | +update thread set thread_created = thread_modified; |
| 5 | +alter table thread add index thread_created (thread_created); |
Property changes on: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-4.sql |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 6 | + native |
Index: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-5.sql |
— | — | @@ -0,0 +1,13 @@ |
| 2 | +alter table thread add column thread_editedness int(1) NOT NULL default 0; |
| 3 | + |
| 4 | +update thread join thread as child on child.thread_parent = thread.thread_id set thread.thread_editedness = 1; |
| 5 | + |
| 6 | +create temporary table counts ( thread_id int(8) unsigned, revision_count int(8) unsigned, author_count int(8) unsigned, rev_user int(8) unsigned ); |
| 7 | + |
| 8 | +insert into counts (thread_id, revision_count, author_count, rev_user) select thread_id, count(thread_id), count(distinct rev_user), rev_user from thread join revision on rev_page = thread_root group by thread_id; |
| 9 | + |
| 10 | +update thread join counts on thread.thread_id = counts.thread_id set thread_editedness = 2 where revision_count > 1; |
| 11 | + |
| 12 | +update thread join counts on thread.thread_id = counts.thread_id set thread_editedness = 3 where author_count > 1 or (rev_user = 0 and revision_count > 1); |
| 13 | + |
| 14 | +drop table counts; |
Property changes on: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-5.sql |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 15 | + native |
Index: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-thread_summary.sql |
— | — | @@ -0,0 +1,5 @@ |
| 2 | +-- Schema change to add thread subject to the thread table. |
| 3 | + |
| 4 | +ALTER TABLE /*_*/thread add column thread_subject varchar(255) NULL; |
| 5 | +ALTER TABLE /*_*/thread add column thread_author_id int unsigned NULL; |
| 6 | +ALTER TABLE /*_*/thread add column thread_author_name varchar(255) NULL; |
Index: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-6.sql |
— | — | @@ -0,0 +1 @@ |
| 2 | +alter table thread add index thread_summary_page (thread_summary_page); |
Property changes on: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-6.sql |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 3 | + native |
Index: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-1.sql |
— | — | @@ -0,0 +1,5 @@ |
| 2 | +update thread, page set thread_article_title=page_title, thread_article_namespace=page_namespace where page_id=thread_article and thread_article is not null and thread_article != 0; |
| 3 | + |
| 4 | +alter table thread drop column thread_article; |
| 5 | +alter table thread modify thread_article_namespace not null; |
| 6 | +alter table thread modify thread_article_title varchar(255) binary not null; |
Property changes on: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-1.sql |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 7 | + native |
Index: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-2.sql |
— | — | @@ -0,0 +1,4 @@ |
| 2 | +update page set page_namespace=90 where page_namespace=16; |
| 3 | +update page set page_namespace=91 where page_namespace=17; |
| 4 | +update page set page_namespace=92 where page_namespace=18; |
| 5 | +update page set page_namespace=93 where page_namespace=19; |
Property changes on: trunk/extensions/LiquidThreads/schema-changes/lqt-schema-change-2.sql |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 6 | + native |
Index: trunk/extensions/LiquidThreads/classes/LqtThreads.php |
— | — | @@ -32,7 +32,8 @@ |
33 | 33 | /** static cache of per-page archivestartdays setting */ |
34 | 34 | static $archiveStartDays; |
35 | 35 | |
36 | | - static function newThread( $root, $article, $superthread = null, $type = self::TYPE_NORMAL ) { |
| 36 | + static function newThread( $root, $article, $superthread = null, |
| 37 | + $type = self::TYPE_NORMAL, $subject = '' ) { |
37 | 38 | // SCHEMA changes must be reflected here. |
38 | 39 | // TODO: It's dumb that the commitRevision code isn't used here. |
39 | 40 | |
— | — | @@ -48,25 +49,28 @@ |
49 | 50 | $change_type = self::CHANGE_NEW_THREAD; |
50 | 51 | } |
51 | 52 | |
52 | | - global $wgUser; // TODO global. |
| 53 | + global $wgUser; |
53 | 54 | |
54 | 55 | $timestamp = wfTimestampNow(); |
55 | 56 | |
56 | 57 | // TODO PG support |
57 | 58 | $newid = $dbw->nextSequenceValue( 'thread_thread_id' ); |
58 | 59 | |
59 | | - $row = array( 'thread_root' => $root->getID(), |
60 | | - 'thread_parent' => $superthread ? $superthread->id() : null, |
61 | | - 'thread_article_namespace' => $article->getTitle()->getNamespace(), |
62 | | - 'thread_article_title' => $article->getTitle()->getDBkey(), |
63 | | - 'thread_modified' => $timestamp, |
64 | | - 'thread_created' => $timestamp, |
65 | | - 'thread_change_type' => $change_type, |
66 | | - 'thread_change_comment' => "", // TODO |
67 | | - 'thread_change_user' => $wgUser->getID(), |
68 | | - 'thread_change_user_text' => $wgUser->getName(), |
69 | | - 'thread_type' => $type, |
70 | | - 'thread_editedness' => self::EDITED_NEVER ); |
| 60 | + $row = array( |
| 61 | + 'thread_root' => $root->getID(), |
| 62 | + 'thread_parent' => $superthread ? $superthread->id() : null, |
| 63 | + 'thread_article_namespace' => $article->getTitle()->getNamespace(), |
| 64 | + 'thread_article_title' => $article->getTitle()->getDBkey(), |
| 65 | + 'thread_modified' => $timestamp, |
| 66 | + 'thread_created' => $timestamp, |
| 67 | + 'thread_change_type' => $change_type, |
| 68 | + 'thread_change_comment' => "", // TODO |
| 69 | + 'thread_change_user' => $wgUser->getID(), |
| 70 | + 'thread_change_user_text' => $wgUser->getName(), |
| 71 | + 'thread_type' => $type, |
| 72 | + 'thread_editedness' => self::EDITED_NEVER, |
| 73 | + 'thread_subject' => $subject, |
| 74 | + ); |
71 | 75 | |
72 | 76 | if ( $superthread ) { |
73 | 77 | $row['thread_ancestor'] = $superthread->ancestorId(); |
— | — | @@ -99,9 +103,6 @@ |
100 | 104 | // We just created the thread, it won't have any children. |
101 | 105 | $newthread = new Thread( $rowObj, array() ); |
102 | 106 | |
103 | | - if ( !$newthread ) |
104 | | - throw new MWException( "No new thread with ID $newid\n" ); |
105 | | - |
106 | 107 | if ( $superthread ) { |
107 | 108 | $superthread->addReply( $newthread ); |
108 | 109 | } |
— | — | @@ -302,7 +303,7 @@ |
303 | 304 | |
304 | 305 | $arr = array( 'thread_ancestor=thread_id', 'thread_parent' => null ); |
305 | 306 | |
306 | | - return $dbr->makeList( $arr, LIST_AND ); |
| 307 | + return $dbr->makeList( $arr, LIST_OR ); |
307 | 308 | } |
308 | 309 | |
309 | 310 | static function getArticleArchiveStartDays( $article ) { |
Index: trunk/extensions/LiquidThreads/classes/LqtView.php |
— | — | @@ -47,31 +47,6 @@ |
48 | 48 | } |
49 | 49 | |
50 | 50 | function initializeQueries() { |
51 | | - |
52 | | - // Determine sort order |
53 | | - if ( $this->methodApplies( 'talkpage_sort_order' ) ) { |
54 | | - // Sort order is explicitly specified through UI |
55 | | - global $wgRequest; |
56 | | - $lqt_order = $wgRequest->getVal( 'lqt_order' ); |
57 | | - switch( $lqt_order ) { |
58 | | - case 'nc': |
59 | | - $this->sort_order = LQT_NEWEST_CHANGES; |
60 | | - break; |
61 | | - case 'nt': |
62 | | - $this->sort_order = LQT_NEWEST_THREADS; |
63 | | - break; |
64 | | - case 'ot': |
65 | | - $this->sort_order = LQT_OLDEST_THREADS; |
66 | | - break; |
67 | | - } |
68 | | - } else { |
69 | | - // Sort order set in user preferences overrides default |
70 | | - global $wgUser; |
71 | | - $user_order = $wgUser->getOption( 'lqt_sort_order' ) ; |
72 | | - if ( $user_order ) { |
73 | | - $this->sort_order = $user_order; |
74 | | - } |
75 | | - } |
76 | 51 | |
77 | 52 | // Create query group |
78 | 53 | global $wgOut, $wgLqtThreadArchiveStartDays, $wgLqtThreadArchiveInactiveDays; |
— | — | @@ -427,7 +402,7 @@ |
428 | 403 | $timestamp = $edit_applies_to->created(); |
429 | 404 | $fTime = $wgContLang->time($timestamp); |
430 | 405 | $fDate = $wgContLang->date($timestamp); |
431 | | - $user = $thread_article->originalAuthor()->getName(); |
| 406 | + $user = $edit_applies_to->author()->getName(); |
432 | 407 | |
433 | 408 | $quoteIntro = wfMsgForContent( 'lqt-quote-intro', $user, $fTime, $fDate ); |
434 | 409 | $quote_text = "$quoteIntro\n<blockquote>\n$quote_text\n</blockquote>\n"; |
— | — | @@ -444,24 +419,33 @@ |
445 | 420 | // For replies and new posts, insert the associated thread object into the DB. |
446 | 421 | if ( $edit_type != 'editExisting' && $edit_type != 'summarize' && $e->didSave ) { |
447 | 422 | if ( $edit_type == 'reply' ) { |
448 | | - $thread = Threads::newThread( $article, $this->article, $edit_applies_to, $e->summary ); |
449 | | - $edit_applies_to->commitRevision( Threads::CHANGE_REPLY_CREATED, $thread, $e->summary ); |
| 423 | + $subject = $edit_applies_to->subject(); |
| 424 | + |
| 425 | + $thread = Threads::newThread( $article, $this->article, $edit_applies_to, |
| 426 | + Threads::TYPE_NORMAL, $subject ); |
| 427 | + |
| 428 | + $edit_applies_to->commitRevision( Threads::CHANGE_REPLY_CREATED, $thread, |
| 429 | + $e->summary ); |
450 | 430 | } else { |
451 | | - $thread = Threads::newThread( $article, $this->article, null, $e->summary ); |
| 431 | + $thread = Threads::newThread( $article, $this->article, null, |
| 432 | + Threads::TYPE_NORMAL, $subject); |
452 | 433 | } |
453 | 434 | } |
454 | 435 | |
455 | 436 | if ( $edit_type == 'summarize' && $e->didSave ) { |
456 | 437 | $edit_applies_to->setSummary( $article ); |
457 | | - $edit_applies_to->commitRevision( Threads::CHANGE_EDITED_SUMMARY, $edit_applies_to, $e->summary ); |
| 438 | + $edit_applies_to->commitRevision( Threads::CHANGE_EDITED_SUMMARY, |
| 439 | + $edit_applies_to, $e->summary ); |
458 | 440 | } |
459 | 441 | |
460 | 442 | // Move the thread and replies if subject changed. |
461 | 443 | if ( $edit_type == 'editExisting' && $e->didSave ) { |
462 | 444 | $subject = $this->request->getVal( 'lqt_subject_field', '' ); |
463 | 445 | if ( $subject && $subject != $thread->subjectWithoutIncrement() ) { |
464 | | - |
465 | | - $this->renameThread( $thread, $subject, $e->summary ); |
| 446 | + $thread->setSubject( $subject ); |
| 447 | + |
| 448 | + // Disabled page-moving for now. |
| 449 | + // $this->renameThread( $thread, $subject, $e->summary ); |
466 | 450 | } |
467 | 451 | // this is unrelated to the subject change and is for all edits: |
468 | 452 | $thread->setRootRevision( Revision::newFromTitle( $thread->root()->getTitle() ) ); |
— | — | @@ -482,6 +466,7 @@ |
483 | 467 | function renameThread( $t, $s, $reason ) { |
484 | 468 | $this->simplePageMove( $t->root()->getTitle(), $s, $reason ); |
485 | 469 | // TODO here create a redirect from old page to new. |
| 470 | + |
486 | 471 | foreach ( $t->subthreads() as $st ) { |
487 | 472 | $this->renameThread( $st, $s, $reason ); |
488 | 473 | } |
— | — | @@ -491,22 +476,38 @@ |
492 | 477 | $token = md5( uniqid( rand(), true ) ); |
493 | 478 | return Title::newFromText( "Thread:$token" ); |
494 | 479 | } |
| 480 | + |
495 | 481 | function newScratchTitle( $subject ) { |
496 | 482 | wfLoadExtensionMessages( 'LiquidThreads' ); |
497 | | - return $this->incrementedTitle( $subject ? $subject:wfMsg( 'lqt_nosubject' ), NS_LQT_THREAD ); |
| 483 | + $subject = $subject ? $subject : wfMsg( 'lqt_nosubject' ); |
| 484 | + |
| 485 | + $base = $this->article->getTitle()->getPrefixedText() . "/$subject"; |
| 486 | + |
| 487 | + return $this->incrementedTitle( $base, NS_LQT_THREAD ); |
498 | 488 | } |
| 489 | + |
499 | 490 | function newSummaryTitle( $t ) { |
500 | | - return $this->incrementedTitle( $t->subject(), NS_LQT_SUMMARY ); |
| 491 | + return $this->incrementedTitle( $t->title()->getText(), NS_LQT_SUMMARY ); |
501 | 492 | } |
| 493 | + |
502 | 494 | function newReplyTitle( $s, $t ) { |
503 | | - return $this->incrementedTitle( $t->subjectWithoutIncrement(), NS_LQT_THREAD ); |
| 495 | + $topThread = $t->topMostThread(); |
| 496 | + |
| 497 | + $base = $t->title()->getText() . '/' . $this->user->getName(); |
| 498 | + |
| 499 | + return $this->incrementedTitle( $base, NS_LQT_THREAD ); |
504 | 500 | } |
| 501 | + |
505 | 502 | /** Keep trying titles starting with $basename until one is unoccupied. */ |
506 | 503 | public static function incrementedTitle( $basename, $namespace ) { |
507 | | - $i = 1; do { |
508 | | - $t = Title::newFromText( $basename . '_(' . $i . ')', $namespace ); |
| 504 | + $i = 2; |
| 505 | + |
| 506 | + $t = Title::makeTitleSafe( $namespace, $basename ); |
| 507 | + while ( $t->exists() || |
| 508 | + in_array( $t->getPrefixedDBkey(), self::$occupied_titles ) ) { |
| 509 | + $t = Title::makeTitleSafe( $namespace, $basename . ' (' . $i . ')' ); |
509 | 510 | $i++; |
510 | | - } while ( $t->exists() || in_array( $t->getPrefixedDBkey(), self::$occupied_titles ) ); |
| 511 | + } |
511 | 512 | return $t; |
512 | 513 | } |
513 | 514 | |
— | — | @@ -524,16 +525,9 @@ |
525 | 526 | |
526 | 527 | self::$occupied_titles[] = $nt->getPrefixedDBkey(); |
527 | 528 | |
528 | | - # don't allow moving to pages with # in |
529 | | - if ( !$nt || $nt->getFragment() != '' ) { |
530 | | - echo "malformed title"; // TODO real error reporting. |
531 | | - return false; |
532 | | - } |
533 | | - |
534 | 529 | $error = $ot->moveTo( $nt, true, "Changed thread subject: $reason" ); |
535 | 530 | if ( $error !== true ) { |
536 | | - var_dump( $error ); |
537 | | - echo "something bad happened trying to rename the thread."; // TODO |
| 531 | + throw new MWException( "Got error $error trying to move pages." ); |
538 | 532 | return false; |
539 | 533 | } |
540 | 534 | |
— | — | @@ -675,14 +669,6 @@ |
676 | 670 | |
677 | 671 | return $parserOutput->getText(); |
678 | 672 | } |
679 | | - |
680 | | - function colorTest() { |
681 | | - $this->output->addHTML( '<div class="lqt_footer"><li class="lqt_footer_sig">' ); |
682 | | - for ( $i = 1; $i <= self::number_of_user_colors; $i++ ) { |
683 | | - $this->output->addHTML( "<span class=\"lqt_post_color_{$i}\"><a href=\"foo\">DavidMcCabe</a></span>" ); |
684 | | - } |
685 | | - $this->output->addHTML( '</li></div>' ); |
686 | | - } |
687 | 673 | |
688 | 674 | function showThreadHeader( $thread ) { |
689 | 675 | global $wgLang; |
— | — | @@ -693,7 +679,7 @@ |
694 | 680 | $infoElements = array(); |
695 | 681 | |
696 | 682 | // Author name. |
697 | | - $author = $thread->root()->originalAuthor(); |
| 683 | + $author = $thread->author(); |
698 | 684 | $signature = $sk->userLink( $author->getId(), $author->getName() ); |
699 | 685 | $signature = Xml::tags( 'span', array( 'class' => 'lqt-thread-header-author' ), |
700 | 686 | $signature ); |
— | — | @@ -904,7 +890,7 @@ |
905 | 891 | $replyLink = Xml::tags( 'a', array( 'href' => '#'.$this->anchorName( $tmp ) ), |
906 | 892 | $tmp->subject() ); |
907 | 893 | $msg = wfMsgExt( 'lqt_in_response_to', array( 'parseinline', 'replaceafter' ), |
908 | | - array( $replyLink, $tmp->root()->originalAuthor()->getName() ) ); |
| 894 | + array( $replyLink, $tmp->author()->getName() ) ); |
909 | 895 | |
910 | 896 | return Xml::tags( 'span', array( 'class' => 'lqt_nonindent_message' ), |
911 | 897 | "← $msg" ); |
— | — | @@ -916,14 +902,16 @@ |
917 | 903 | // Display a moved thread |
918 | 904 | function showMovedThread( $thread ) { |
919 | 905 | global $wgLang; |
| 906 | + |
| 907 | + $sk = $this->user->getSkin(); |
920 | 908 | |
921 | 909 | // Grab target thread |
922 | 910 | $article = new Article( $thread->title() ); |
923 | | - $target = Title::newFromRedirect( $article->getText() ); |
| 911 | + $target = Title::newFromRedirect( $article->getContent() ); |
924 | 912 | $t_thread = Threads::withRoot( new Article( $target ) ); |
925 | 913 | |
926 | 914 | // Grab data about the new post. |
927 | | - $author = $thread->root()->originalAuthor(); |
| 915 | + $author = $thread->author(); |
928 | 916 | $sig = $sk->userLink( $author->getID(), $author->getName() ) . |
929 | 917 | $sk->userToolLinks( $author->getID(), $author->getName() ); |
930 | 918 | |
— | — | @@ -940,6 +928,7 @@ |
941 | 929 | |
942 | 930 | /** Shows a deleted thread. Returns true to show the thread body */ |
943 | 931 | function showDeletedThread( $thread ) { |
| 932 | + $sk = $this->user->getSkin(); |
944 | 933 | if ( $this->user->isAllowed( 'deletedhistory' ) ) { |
945 | 934 | $this->output->addWikiMsg( 'lqt_thread_deleted_for_sysops' ); |
946 | 935 | return true; |
Index: trunk/extensions/LiquidThreads/classes/LqtThread.php |
— | — | @@ -28,6 +28,9 @@ |
29 | 29 | protected $id; |
30 | 30 | protected $revisionNumber; |
31 | 31 | protected $type; |
| 32 | + protected $subject; |
| 33 | + protected $authorId; |
| 34 | + protected $authorName; |
32 | 35 | |
33 | 36 | /* Flag about who has edited or replied to this thread. */ |
34 | 37 | protected $editedness; |
— | — | @@ -117,16 +120,20 @@ |
118 | 121 | self::setChangeOnDescendents( $r, $change_type, $change_object ); |
119 | 122 | return $thread; |
120 | 123 | } |
| 124 | + |
| 125 | + function getDouble() { |
| 126 | + if (!$this->double) { |
| 127 | + $this->double = clone $this; |
| 128 | + } |
| 129 | + |
| 130 | + return $this->double; |
| 131 | + } |
121 | 132 | |
122 | 133 | function commitRevision( $change_type, $change_object = null, $reason = "" ) { |
123 | | - global $wgUser; // TODO global. |
124 | | - /* |
125 | | - $this->changeComment = $reason; |
126 | | - $this->changeUser = $wgUser->getID(); |
127 | | - $this->changeUserText = $wgUser->getName(); |
128 | | - */ |
| 134 | + global $wgUser; |
| 135 | + |
129 | 136 | // TODO open a transaction. |
130 | | - HistoricalThread::create( $this->double, $change_type, $change_object ); |
| 137 | + HistoricalThread::create( $this->getDouble(), $change_type, $change_object ); |
131 | 138 | |
132 | 139 | $this->bumpRevisionsOnAncestors( $change_type, $change_object, $reason, wfTimestampNow() ); |
133 | 140 | self::setChangeOnDescendents( $this->topmostThread(), $change_type, $change_object ); |
— | — | @@ -136,7 +143,7 @@ |
137 | 144 | $this->editedness = Threads::EDITED_HAS_REPLY; |
138 | 145 | } |
139 | 146 | else if ( $change_type == Threads::CHANGE_EDITED_ROOT ) { |
140 | | - $originalAuthor = $this->root()->originalAuthor(); |
| 147 | + $originalAuthor = $this->author(); |
141 | 148 | if ( ( $wgUser->getId() == 0 && $originalAuthor->getName() != $wgUser->getName() ) |
142 | 149 | || $wgUser->getId() != $originalAuthor->getId() ) { |
143 | 150 | $this->editedness = Threads::EDITED_BY_OTHERS; |
— | — | @@ -153,6 +160,9 @@ |
154 | 161 | 'thread_ancestor' => $this->ancestorId, |
155 | 162 | 'thread_parent' => $this->parentId, |
156 | 163 | 'thread_type' => $this->type, |
| 164 | + 'thread_subject' => $this->subject, |
| 165 | + 'thread_author_id' => $this->authorId, |
| 166 | + 'thread_author_name' => $this->authorName, |
157 | 167 | 'thread_summary_page' => $this->summaryId, |
158 | 168 | 'thread_article_namespace' => $this->articleNamespace, |
159 | 169 | 'thread_article_title' => $this->articleTitle, |
— | — | @@ -160,11 +170,27 @@ |
161 | 171 | ), |
162 | 172 | /* WHERE */ array( 'thread_id' => $this->id, ), |
163 | 173 | __METHOD__ ); |
| 174 | + |
| 175 | + // Touch the root |
| 176 | + $this->root()->getTitle()->invalidateCache(); |
164 | 177 | |
165 | 178 | if ( $change_type == Threads::CHANGE_EDITED_ROOT ) { |
166 | 179 | NewMessages::writeMessageStateForUpdatedThread( $this, $change_type, $wgUser ); |
167 | 180 | } |
168 | 181 | } |
| 182 | + |
| 183 | + function author() { |
| 184 | + $this->doLazyUpdates(); |
| 185 | + |
| 186 | + if ($this->authorId) { |
| 187 | + return User::newFromId( $this->authorId ); |
| 188 | + } else { |
| 189 | + $u = new User; |
| 190 | + $u->mName = $this->authorName; |
| 191 | + |
| 192 | + return $u; |
| 193 | + } |
| 194 | + } |
169 | 195 | |
170 | 196 | function delete( $reason ) { |
171 | 197 | $this->type = Threads::TYPE_DELETED; |
— | — | @@ -172,6 +198,7 @@ |
173 | 199 | $this->commitRevision( Threads::CHANGE_DELETED, $this, $reason ); |
174 | 200 | /* TODO: mark thread as read by all users, or we get blank thingies in New Messages. */ |
175 | 201 | } |
| 202 | + |
176 | 203 | function undelete( $reason ) { |
177 | 204 | $this->type = Threads::TYPE_NORMAL; |
178 | 205 | $this->revisionNumber += 1; |
— | — | @@ -187,7 +214,7 @@ |
188 | 215 | $new_articleNamespace = $title->getNamespace(); |
189 | 216 | $new_articleTitle = $title->getDBkey(); |
190 | 217 | |
191 | | - foreach ( $this->replies as $r ) { |
| 218 | + foreach ( $this->replies() as $r ) { |
192 | 219 | $res = $dbr->update( 'thread', |
193 | 220 | /* SET */array( |
194 | 221 | 'thread_revision' => $r->revisionNumber() + 1, |
— | — | @@ -268,10 +295,12 @@ |
269 | 296 | 'thread_change_comment' => 'changeComment', |
270 | 297 | 'thread_change_user' => 'changeUser', |
271 | 298 | 'thread_change_user_text' => 'changeUserText', |
272 | | - 'thread_editedness' => 'editedness' |
| 299 | + 'thread_editedness' => 'editedness', |
| 300 | + 'thread_subject' => 'subject', |
| 301 | + 'thread_author_id' => 'authorId', |
| 302 | + 'thread_author_name' => 'authorName', |
273 | 303 | ); |
274 | 304 | |
275 | | - |
276 | 305 | foreach( $dataLoads as $db_field => $member_field ) { |
277 | 306 | if ( isset($line->$db_field) ) { |
278 | 307 | $this->$member_field = $line->$db_field; |
— | — | @@ -288,7 +317,68 @@ |
289 | 318 | } |
290 | 319 | |
291 | 320 | $this->rootRevision = $this->root->mLatest; |
| 321 | + |
| 322 | + $this->doLazyUpdates( $line ); |
292 | 323 | } |
| 324 | + |
| 325 | + // Load a list of threads in bulk. |
| 326 | + static function bulkLoad( $rows ) { |
| 327 | + $threads = array(); |
| 328 | + |
| 329 | + foreach( $rows as $row ) { |
| 330 | + $threads[] = new Thread( $row, null ); |
| 331 | + } |
| 332 | + |
| 333 | + return $threads; |
| 334 | + } |
| 335 | + |
| 336 | + // Lazy updates done whenever a thread is loaded. |
| 337 | + // Much easier than running a long-running maintenance script. |
| 338 | + function doLazyUpdates( ) { |
| 339 | + // This is an invocation guard to avoid infinite recursion when fixing a |
| 340 | + // missing ancestor. |
| 341 | + static $doingUpdates = false; |
| 342 | + if ($doingUpdates) return; |
| 343 | + $doingUpdates = true; |
| 344 | + |
| 345 | + // Fix missing ancestry information. |
| 346 | + if ($this->parentId &&!$this->ancestorId) { |
| 347 | + $this->fixMissingAncestor(); |
| 348 | + } |
| 349 | + |
| 350 | + $set = array(); |
| 351 | + |
| 352 | + // Fix missing subject information |
| 353 | + if (!$this->subject) { |
| 354 | + $detectedSubject = $this->root()->getTitle()->getText(); |
| 355 | + $parts = self::splitIncrementFromSubject( $detectedSubject ); |
| 356 | + |
| 357 | + $this->subject = $detectedSubject = $parts[1]; |
| 358 | + |
| 359 | + // Update in the DB |
| 360 | + $set['thread_subject'] = $detectedSubject; |
| 361 | + } |
| 362 | + |
| 363 | + // Fix missing authorship information |
| 364 | + if ( !$this->authorName ) { |
| 365 | + $author = $this->root()->originalAuthor(); |
| 366 | + |
| 367 | + $this->authorId = $author->getId(); |
| 368 | + $this->authorName = $author->getName(); |
| 369 | + |
| 370 | + $set['thread_author_name'] = $this->authorName; |
| 371 | + $set['thread_author_id'] = $this->authorId; |
| 372 | + } |
| 373 | + |
| 374 | + if ( count($set) ) { |
| 375 | + $dbw = wfGetDB( DB_MASTER ); |
| 376 | + |
| 377 | + $dbw->update( 'thread', $set, array( 'thread_id' => $this->id() ), __METHOD__ ); |
| 378 | + } |
| 379 | + |
| 380 | + // Done |
| 381 | + $doingUpdates = false; |
| 382 | + } |
293 | 383 | |
294 | 384 | function initWithReplies( $children ) { |
295 | 385 | |
— | — | @@ -319,7 +409,11 @@ |
320 | 410 | // historical thread, duh. Why were we doing this? |
321 | 411 | // $this->replies[] = $thread; |
322 | 412 | } |
| 413 | + |
323 | 414 | function removeReplyWithId( $id ) { |
| 415 | + // Force load |
| 416 | + $this->replies(); |
| 417 | + |
324 | 418 | $target = null; |
325 | 419 | foreach ( $this->replies as $k => $r ) { |
326 | 420 | if ( $r->id() == $id ) { |
— | — | @@ -334,6 +428,24 @@ |
335 | 429 | } |
336 | 430 | } |
337 | 431 | function replies() { |
| 432 | + if ( !is_null($this->replies) ) { |
| 433 | + return $this->replies; |
| 434 | + } |
| 435 | + |
| 436 | + $this->replies = array(); |
| 437 | + |
| 438 | + $dbr = wfGetDB( DB_SLAVE ); |
| 439 | + |
| 440 | + $res = $dbr->select( 'thread', '*', |
| 441 | + array( 'thread_parent' => $this->id() ), __METHOD__ ); |
| 442 | + |
| 443 | + $rows = array(); |
| 444 | + while ( $row = $dbr->fetchObject($res) ) { |
| 445 | + $rows[] = $row; |
| 446 | + } |
| 447 | + |
| 448 | + $this->replies = Thread::bulkLoad( $rows ); |
| 449 | + |
338 | 450 | return $this->replies; |
339 | 451 | } |
340 | 452 | |
— | — | @@ -500,27 +612,21 @@ |
501 | 613 | } |
502 | 614 | |
503 | 615 | function subject() { |
504 | | - return $this->root()->getTitle()->getText(); |
| 616 | + return $this->subject; |
505 | 617 | } |
| 618 | + |
| 619 | + function setSubject( $subject ) { |
| 620 | + $this->subject = $subject; |
| 621 | + } |
506 | 622 | |
507 | 623 | function wikilinkWithoutIncrement() { |
508 | | - $tmp = self::splitIncrementFromSubject( $this->wikilink() ); |
509 | | - |
510 | | - return $tmp[1]; |
| 624 | + return $this->wikilink(); |
511 | 625 | } |
512 | 626 | |
513 | 627 | function subjectWithoutIncrement() { |
514 | | - $tmp = self::splitIncrementFromSubject( $this->subject() ); |
515 | | - |
516 | | - return $tmp[1]; |
| 628 | + return $this->subject(); |
517 | 629 | } |
518 | 630 | |
519 | | - function increment() { |
520 | | - $tmp = self::splitIncrementFromSubject( $this->subject() ); |
521 | | - |
522 | | - return $tmp[2]; |
523 | | - } |
524 | | - |
525 | 631 | function hasDistinctSubject() { |
526 | 632 | if ( $this->hasSuperthread() ) { |
527 | 633 | return $this->superthread()->subjectWithoutIncrement() |
— | — | @@ -531,11 +637,11 @@ |
532 | 638 | } |
533 | 639 | |
534 | 640 | function hasSubthreads() { |
535 | | - return count( $this->replies ) != 0; |
| 641 | + return count( $this->replies() ) != 0; |
536 | 642 | } |
537 | 643 | |
538 | 644 | function subthreads() { |
539 | | - return $this->replies; |
| 645 | + return $this->replies(); |
540 | 646 | } |
541 | 647 | |
542 | 648 | function modified() { |
— | — | @@ -556,7 +662,7 @@ |
557 | 663 | |
558 | 664 | private function replyWithId( $id ) { |
559 | 665 | if ( $this->id == $id ) return $this; |
560 | | - foreach ( $this->replies as $r ) { |
| 666 | + foreach ( $this->replies() as $r ) { |
561 | 667 | if ( $r->id() == $id ) return $r; |
562 | 668 | else { |
563 | 669 | $s = $r->replyWithId( $id ); |
Index: trunk/extensions/LiquidThreads/lqt.sql |
— | — | @@ -4,6 +4,9 @@ |
5 | 5 | thread_ancestor int(8) unsigned NOT NULL, |
6 | 6 | thread_parent int(8) unsigned NULL, |
7 | 7 | thread_summary_page int(8) unsigned NULL, |
| 8 | + thread_subject varchar(255) NULL, |
| 9 | + thread_author_id int unsigned NULL, |
| 10 | + thread_author_name varchar(255) NULL, |
8 | 11 | |
9 | 12 | thread_modified char(14) binary NOT NULL default '', |
10 | 13 | thread_created char(14) binary NOT NULL default '', |
— | — | @@ -25,11 +28,12 @@ |
26 | 29 | |
27 | 30 | PRIMARY KEY thread_id (thread_id), |
28 | 31 | UNIQUE INDEX thread_id (thread_id), |
29 | | - INDEX thread_ancestor (thread_ancestor), |
| 32 | + INDEX thread_ancestor (thread_ancestor, thread_parent), |
30 | 33 | INDEX thread_article_title (thread_article_namespace, thread_article_title), |
31 | 34 | INDEX thread_modified (thread_modified), |
32 | 35 | INDEX thread_created (thread_created), |
33 | | - INDEX thread_summary_page (thread_summary_page) |
| 36 | + INDEX thread_summary_page (thread_summary_page), |
| 37 | + INDEX thread_root (thread_root) |
34 | 38 | ) /*$wgDBTableOptions*/; |
35 | 39 | |
36 | 40 | CREATE TABLE /*$wgDBprefix*/historical_thread ( |