Index: trunk/extensions/LiquidThreads/lqt.css |
— | — | @@ -493,13 +493,6 @@ |
494 | 494 | text-align: right; |
495 | 495 | } |
496 | 496 | |
497 | | -.lqt-thread-header-commands { |
498 | | - float: right; |
499 | | - font-size: 85%; |
500 | | - margin: 0; |
501 | | - margin-right: 2em; |
502 | | -} |
503 | | - |
504 | 497 | .lqt-thread-header-commands:hover { |
505 | 498 | background-color: #eeeeee; |
506 | 499 | } |
— | — | @@ -559,3 +552,16 @@ |
560 | 553 | margin: 0.3em; |
561 | 554 | margin-left: 2em; |
562 | 555 | } |
| 556 | + |
| 557 | +.lqt-thread-header-rhs { |
| 558 | + float: right; |
| 559 | + font-size: 85%; |
| 560 | + margin: 0; |
| 561 | + text-wrap: suppress; |
| 562 | +} |
| 563 | + |
| 564 | +.lqt-thread-header-commands { |
| 565 | + padding: 0; |
| 566 | + margin: 0; |
| 567 | + display: inline-block; |
| 568 | +} |
Index: trunk/extensions/LiquidThreads/classes/LqtView.php |
— | — | @@ -297,9 +297,7 @@ |
298 | 298 | function perpetuate( $name, $as ) { |
299 | 299 | $value = $this->request->getVal( $name, '' ); |
300 | 300 | if ( $as == 'hidden' ) { |
301 | | - return <<<HTML |
302 | | - <input type="hidden" name="$name" id="$name" value="$value"> |
303 | | -HTML; |
| 301 | + return Xml::hidden( $name, $value ); |
304 | 302 | } |
305 | 303 | } |
306 | 304 | |
— | — | @@ -572,10 +570,6 @@ |
573 | 571 | 'href' => $history_url, |
574 | 572 | 'enabled' => true ); |
575 | 573 | |
576 | | - $commands['permalink'] = array( 'label' => wfMsgExt( 'lqt_permalink', 'parseinline' ), |
577 | | - 'href' => self::permalinkUrl( $thread ), |
578 | | - 'enabled' => true ); |
579 | | - |
580 | 574 | if ( $this->user->isAllowed( 'delete' ) ) { |
581 | 575 | $threadText = $thread->title()->getPrefixedText(); |
582 | 576 | $deleteTitle = SpecialPage::getTitleFor( 'DeleteThread', $threadText ); |
— | — | @@ -724,15 +718,26 @@ |
725 | 719 | $commandHTML = Xml::tags( 'ul', array( 'class' => 'lqt-thread-header-command-list' ), |
726 | 720 | $this->listItemsForCommands( $commands ) ); |
727 | 721 | |
| 722 | + $headerParts = array(); |
| 723 | + |
| 724 | + $permalink = $this->permalink( $thread, wfMsgExt( 'lqt_permalink', 'parseinline' ) ); |
| 725 | + $permalink = Xml::tags( 'span', array( 'class' => 'lqt-thread-permalink' ), $permalink ); |
| 726 | + $headerParts[] = $permalink; |
| 727 | + |
| 728 | + // Drop-down menu |
728 | 729 | $triggerText = wfMsgExt( 'lqt-header-actions', 'parseinline' ) . |
729 | 730 | Xml::tags( 'span', array('class' => 'lqt-thread-actions-icon'), |
730 | 731 | ' '); |
731 | 732 | $dropDownTrigger = Xml::tags( 'span', |
732 | 733 | array( 'class' => 'lqt-thread-actions-trigger' ), |
733 | 734 | $triggerText ); |
| 735 | + $headerParts[] = Xml::tags( 'div', |
| 736 | + array( 'class' => 'lqt-thread-header-commands' ), |
| 737 | + $dropDownTrigger . $commandHTML ); |
| 738 | + |
734 | 739 | $dropDown = Xml::tags( 'div', |
735 | | - array( 'class' => 'lqt-thread-header-commands' ), |
736 | | - $dropDownTrigger . $commandHTML ); |
| 740 | + array( 'class' => 'lqt-thread-header-rhs' ), |
| 741 | + $wgLang->pipeList( $headerParts ) ); |
737 | 742 | $html .= $dropDown; |
738 | 743 | |
739 | 744 | $html = Xml::tags( 'div', array( 'class' => 'lqt-thread-header' ), $html ); |
Index: trunk/extensions/LiquidThreads/classes/LqtThread.php |
— | — | @@ -337,7 +337,12 @@ |
338 | 338 | |
339 | 339 | function setSuperthread( $thread ) { |
340 | 340 | $this->parentId = $thread->id(); |
341 | | - $this->ancestorId = $thread->ancestorId(); |
| 341 | + |
| 342 | + if ( $thread->isTopmostThread() ) { |
| 343 | + $this->ancestorId = $thread->id(); |
| 344 | + } else { |
| 345 | + $this->ancestorId = $thread->ancestorId(); |
| 346 | + } |
342 | 347 | } |
343 | 348 | |
344 | 349 | function superthread() { |
— | — | @@ -360,12 +365,37 @@ |
361 | 366 | if ( $this->isTopmostThread() ) { |
362 | 367 | return $this; |
363 | 368 | } else { |
364 | | - return Threads::withId( $this->ancestorId ); |
| 369 | + $thread = Threads::withId( $this->ancestorId ); |
| 370 | + |
| 371 | + if (!$thread) { |
| 372 | + $thread = $this->fixMissingAncestor(); |
| 373 | + } |
| 374 | + |
| 375 | + return $thread; |
365 | 376 | } |
366 | 377 | } |
367 | 378 | |
| 379 | + // Due to a bug in earlier versions, the topmost thread sometimes isn't there. |
| 380 | + // Fix the corruption by repeatedly grabbing the parent until we hit the topmost thread. |
| 381 | + function fixMissingAncestor() { |
| 382 | + $thread = $this; |
| 383 | + |
| 384 | + while ( !$thread->isTopmostThread() ) { |
| 385 | + $thread = $thread->superthread(); |
| 386 | + } |
| 387 | + |
| 388 | + $this->ancestorId = $thread->id(); |
| 389 | + |
| 390 | + $dbw = wfGetDB( DB_MASTER ); |
| 391 | + $dbw->update( 'thread', array( 'thread_ancestor' => $thread->id() ), |
| 392 | + array( 'thread_id' => $this->id() ), __METHOD__ ); |
| 393 | + |
| 394 | + return $thread; |
| 395 | + } |
| 396 | + |
368 | 397 | function isTopmostThread() { |
369 | | - return $this->ancestorId == $this->id || intval($this->ancestorId) === 0; |
| 398 | + return $this->ancestorId == $this->id || |
| 399 | + $this->parentId == 0; |
370 | 400 | } |
371 | 401 | |
372 | 402 | function setArticle( $a ) { |
Index: trunk/extensions/LiquidThreads/pages/ThreadPermalinkView.php |
— | — | @@ -82,6 +82,9 @@ |
83 | 83 | function getSubtitle() { |
84 | 84 | wfLoadExtensionMessages( 'LiquidThreads' ); |
85 | 85 | |
| 86 | + $sk = $this->user->getSkin(); |
| 87 | + $fragment = '#'.$this->anchorName( $this->thread ); |
| 88 | + |
86 | 89 | if ( $this->thread->isHistorical() ) { |
87 | 90 | // TODO: Point to the relevant part of the archive. |
88 | 91 | $query = ''; |
— | — | @@ -90,15 +93,21 @@ |
91 | 94 | } |
92 | 95 | |
93 | 96 | $talkpage = $this->thread->article()->getTitle(); |
94 | | - $talkpage_link = $this->user->getSkin()->link( $talkpage ); |
| 97 | + $talkpage->setFragment( $fragment ); |
| 98 | + $talkpage_link = $sk->link( $talkpage ); |
95 | 99 | |
96 | 100 | if ( $this->thread->hasSuperthread() ) { |
97 | | - $permalink = self::permalink( $this->thread->topmostThread(), |
98 | | - wfMsg( 'lqt_discussion_link' ) ); |
| 101 | + $topmostTitle = $this->thread->topmostThread()->title(); |
| 102 | + $topmostTitle->setFragment( $fragment ); |
| 103 | + |
| 104 | + $linkText = wfMsgExt( 'lqt_discussion_link', 'parseinline' ); |
| 105 | + $permalink = $sk->link( $topmostTitle, $linkText ); |
99 | 106 | |
100 | | - return wfMsg( 'lqt_fragment', $permalink, $talkpage_link ); |
| 107 | + return wfMsgExt( 'lqt_fragment', array('parseinline', 'replaceafter'), |
| 108 | + array( $permalink, $talkpage_link ) ); |
101 | 109 | } else { |
102 | | - return wfMsg( 'lqt_from_talk', $talkpage_link ); |
| 110 | + return wfMsgExt( 'lqt_from_talk', array('parseinline', 'replaceafter'), |
| 111 | + array($talkpage_link) ); |
103 | 112 | } |
104 | 113 | } |
105 | 114 | |