r47245 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r47244‎ | r47245 | r47246 >
Date:23:53, 13 February 2009
Author:werdna
Status:deferred
Tags:
Comment:
Remove obsolete file.
Modified paths:
  • /trunk/extensions/LiquidThreads/LqtPages.php (deleted) (history)

Diff [purge]

Index: trunk/extensions/LiquidThreads/LqtPages.php
@@ -1,1355 +0,0 @@
2 -<?php
3 -
4 -/**
5 -* @package MediaWiki
6 -* @subpackage LiquidThreads
7 -* @author David McCabe <davemccabe@gmail.com>
8 -* @licence GPL2
9 -*/
10 -
11 -if( !defined( 'MEDIAWIKI' ) ) {
12 - echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" );
13 - die( -1 );
14 -}
15 -
16 -class TalkpageView extends LqtView {
17 - /* Added to SkinTemplateTabs hook in TalkpageView::show(). */
18 - function customizeTabs( $skintemplate, $content_actions ) {
19 - // The arguments are passed in by reference.
20 - unset($content_actions['edit']);
21 - unset($content_actions['viewsource']);
22 - unset($content_actions['addsection']);
23 - unset($content_actions['history']);
24 - unset($content_actions['watch']);
25 - unset($content_actions['move']);
26 -
27 - /*
28 - TODO:
29 - We could make these tabs actually follow the tab metaphor if we repointed
30 - the 'history' and 'edit' tabs to the original subject page. That way 'discussion'
31 - would just be one of four ways to view the article. But then those other tabs, for
32 - logged-in users, don't really fit the metaphor. What to do, what to do?
33 - */
34 - return true;
35 - }
36 -
37 - function permalinksForThreads($ts, $method = null, $operand = null) {
38 - $ps = array();
39 - foreach ($ts as $t) {
40 - $u = $this->permalinkUrl($t, $method, $operand);
41 - $l = $t->subjectWithoutIncrement();
42 - $ps[] = "<a href=\"$u\">$l</a>";
43 - }
44 - return $ps;
45 - }
46 -
47 - function showHeader() {
48 - /* Show the contents of the actual talkpage article if it exists. */
49 -
50 - $article = new Article( $this->title );
51 - $revision = Revision::newFromId($article->getLatest());
52 - if( $revision ) $article_text = $revision->getRawText();
53 -
54 - $oldid = $this->request->getVal('oldid', null);
55 - $editlink = $this->title->getFullURL( 'action=edit' );
56 -
57 - wfLoadExtensionMessages( 'LiquidThreads' );
58 - // If $article_text == "", the talkpage was probably just created
59 - // when the first thread was posted to make the links blue.
60 - if ( $article->exists() && $article_text != "" ) {
61 - $historylink = $this->title->getFullURL( 'action=history' );
62 - $this->openDiv('lqt_header_content');
63 - $this->showPostBody($article, $oldid);
64 - $this->outputList('ul', 'lqt_header_commands', null, array(
65 - "[<a href=\"$editlink\">".wfMsg('edit')."&uarr;</a>]",
66 - "[<a href=\"$historylink\">".wfMsg('history_short')."&uarr;</a>]"
67 - ));
68 - $this->closeDiv();
69 - } else {
70 - $this->output->addHTML("<p class=\"lqt_header_notice\">[<a href=\"$editlink\">".wfMsg('lqt_add_header')."</a>]</p>");
71 - }
72 - }
73 -
74 - function outputList( $kind, $class, $id, $contents ) {
75 - $this->output->addHTML(Xml::openElement($kind, array('class'=>$class,'id'=>$id)));
76 - foreach ($contents as $li) {
77 - $this->output->addHTML( Xml::openElement('li') );
78 - $this->output->addHTML( $li );
79 - $this->output->addHTML( Xml::closeElement('li') );
80 - }
81 - $this->output->addHTML(Xml::closeElement($kind));
82 - }
83 -
84 - function showTOC($threads) {
85 - wfLoadExtensionMessages( 'LiquidThreads' );
86 -
87 - $sk = $this->user->getSkin();
88 - $toclines = array();
89 - $i = 1;
90 - $toclines[] = $sk->tocIndent();
91 - foreach($threads as $t) {
92 - $toclines[] = $sk->tocLine($this->anchorName($t), $t->subjectWithoutIncrement(), $i, 1);
93 - $i++;
94 - }
95 - $toclines[] = $sk->tocUnindent(1);
96 -
97 - $this->openDiv('lqt_toc_wrapper');
98 - $this->output->addHTML('<h2 class="lqt_toc_title">'.wfMsg('lqt_contents_title').'</h2> <ul>');
99 -
100 - foreach($threads as $t) {
101 - $this->output->addHTML('<li><a href="#'.$this->anchorName($t).'">'.$t->subjectWithoutIncrement().'</a></li>');
102 - }
103 -
104 - $this->output->addHTML('</ul></div>');
105 - }
106 -
107 - function showArchiveWidget($threads) {
108 - wfLoadExtensionMessages( 'LiquidThreads' );
109 -
110 - $threadlinks = $this->permalinksForThreads($threads);
111 - $url = $this->talkpageUrl($this->title, 'talkpage_archive');
112 -
113 - if ( count($threadlinks) > 0 ) {
114 - $this->openDiv('lqt_archive_teaser');
115 - $this->output->addHTML('<h2 class="lqt_recently_archived">'.wfMsg('lqt_recently_archived').'</h2>');
116 - // $this->output->addHTML("<span class=\"lqt_browse_archive\">[<a href=\"$url\">".wfMsg('lqt_browse_archive_with_recent')."</a>]</span></h2>");
117 - $this->outputList('ul', '', '', $threadlinks);
118 - $this->closeDiv();
119 - } else {
120 - }
121 - }
122 -
123 - function showTalkpageViewOptions($article) {
124 - wfLoadExtensionMessages( 'LiquidThreads' );
125 - // TODO WTF who wrote this?
126 -
127 - if( $this->methodApplies('talkpage_sort_order') ) {
128 - $remember_sort_checked = $this->request->getBool('lqt_remember_sort') ? 'checked ' : '';
129 - $this->user->setOption('lqt_sort_order', $this->sort_order);
130 - $this->user->saveSettings();
131 - } else {
132 - $remember_sort_checked = '';
133 - }
134 -
135 - if($article->exists()) {
136 - $nc_sort = $this->sort_order==LQT_NEWEST_CHANGES ? ' selected' : '';
137 - $nt_sort = $this->sort_order==LQT_NEWEST_THREADS ? ' selected' : '';
138 - $ot_sort = $this->sort_order==LQT_OLDEST_THREADS ? ' selected' : '';
139 - $newest_changes = wfMsg('lqt_sort_newest_changes');
140 - $newest_threads = wfMsg('lqt_sort_newest_threads');
141 - $oldest_threads = wfMsg('lqt_sort_oldest_threads');
142 - $lqt_remember_sort = wfMsg('lqt_remember_sort') ;
143 - $form_action_url = $this->talkpageUrl( $this->title, 'talkpage_sort_order');
144 - $lqt_sorting_order = wfMsg('lqt_sorting_order');
145 - $lqt_sort_newest_changes = wfMsg('lqt_sort_newest_changes');
146 - $lqt_sort_newest_threads = wfMsg('lqt_sort_newest_threads');
147 - $lqt_sort_oldest_threads = wfMsg('lqt_sort_oldest_threads');
148 - $go=wfMsg('go');
149 - if($this->user->isLoggedIn()) {
150 - $remember_sort =
151 - <<<HTML
152 -<br />
153 -<label for="lqt_remember_sort_checkbox">
154 -<input id="lqt_remember_sort_checkbox" name="lqt_remember_sort" type="checkbox" value="1" $remember_sort_checked />
155 -$lqt_remember_sort</label>
156 -HTML;
157 - } else {
158 - $remember_sort = '';
159 - }
160 - if ( in_array('deletedhistory', $this->user->getRights()) ) {
161 - $show_deleted_checked = $this->request->getBool('lqt_show_deleted_threads') ? 'checked ' : '';
162 - $show_deleted = "<br />\n" .
163 - "<label for=\"lqt_show_deleted_threads_checkbox\">\n" .
164 - "<input id=\"lqt_show_deleted_threads_checkbox\" name=\"lqt_show_deleted_threads\" type=\"checkbox\" value=\"1\" $show_deleted_checked />\n" .
165 - wfMsg( 'lqt_delete_show_checkbox' ) . "</label>\n";
166 - } else {
167 - $show_deleted = "";
168 - }
169 - $this->openDiv('lqt_view_options');
170 - $this->output->addHTML(
171 -
172 - <<<HTML
173 -<form name="lqt_sort" action="$form_action_url" method="post">$lqt_sorting_order
174 -<select name="lqt_order" class="lqt_sort_select">
175 -<option value="nc"$nc_sort>$lqt_sort_newest_changes</option>
176 -<option value="nt"$nt_sort>$lqt_sort_newest_threads</option>
177 -<option value="ot"$ot_sort>$lqt_sort_oldest_threads</option>
178 -</select>
179 -$remember_sort
180 -$show_deleted
181 -<input name="submitsort" type="submit" value="$go" class="lqt_go_sort"/>
182 -</form>
183 -HTML
184 - );
185 - $this->closeDiv();
186 - }
187 -
188 - }
189 -
190 - function show() {
191 - global $wgHooks;
192 - wfLoadExtensionMessages( 'LiquidThreads' );
193 - // Why is a hook added here?
194 - $wgHooks['SkinTemplateTabs'][] = array($this, 'customizeTabs');
195 -
196 - $this->output->setPageTitle( $this->title->getTalkpage()->getPrefixedText() );
197 - self::addJSandCSS();
198 - $article = new Article( $this->title ); // Added in r29715 sorting. Why?
199 -
200 - // Removed in r29715 sorting. Again, why?
201 - $this->showHeader();
202 -
203 - global $wgRequest; // TODO
204 - if( $this->methodApplies('talkpage_new_thread') ) {
205 - $this->showNewThreadForm();
206 - } else {
207 - $this->showTalkpageViewOptions($article);
208 - $url = $this->talkpageUrl( $this->title, 'talkpage_new_thread' );
209 - $this->output->addHTML("<strong><a class=\"lqt_start_discussion\" href=\"$url\">".wfMsg('lqt_new_thread')."</a></strong>");
210 - }
211 -
212 - $threads = $this->queries->query('fresh');
213 -
214 - $this->openDiv('lqt_toc_archive_wrapper');
215 -
216 - $this->openDiv('lqt_archive_teaser_empty');
217 - $this->output->addHTML("<div class=\"lqt_browse_archive\"><a href=\"{$this->talkpageUrl($this->title, 'talkpage_archive')}\">".
218 - wfMsg('lqt_browse_archive_without_recent')."</a></div>");
219 - $this->closeDiv();
220 - $recently_archived_threads = $this->queries->query('recently-archived');
221 - if(count($threads) > 3 || count($recently_archived_threads) > 0) {
222 - $this->showTOC($threads);
223 - }
224 - $this->showArchiveWidget($recently_archived_threads);
225 - $this->closeDiv();
226 - // Clear any floats
227 - $this->output->addHTML('<br clear="all" />');
228 -
229 - foreach($threads as $t) {
230 - $this->showThread($t);
231 - }
232 - return false;
233 - }
234 -}
235 -
236 -class TalkpageArchiveView extends TalkpageView {
237 - function __construct(&$output, &$article, &$title, &$user, &$request) {
238 - parent::__construct($output, $article, $title, $user, $request);
239 - $this->loadQueryFromRequest();
240 - }
241 -
242 - function showThread($t) {
243 - $this->output->addHTML(<<<HTML
244 -<tr>
245 -<td><a href="{$this->permalinkUrl($t)}">{$t->subjectWithoutIncrement()}</a></td>
246 -<td>
247 -HTML
248 - ); if( $t->hasSummary() ) {
249 - $this->showPostBody($t->summary());
250 - } else if ( $t->type() == Threads::TYPE_MOVED ) {
251 - $rthread = $t->redirectThread();
252 - if( $rthread && $rthread->summary() ) {
253 - $this->showPostBody($rthread->summary());
254 - }
255 - }
256 - $this->output->addHTML(<<<HTML
257 -</td>
258 -</tr>
259 -HTML
260 - );
261 - }
262 -
263 - function loadQueryFromRequest() {
264 - wfLoadExtensionMessages( 'LiquidThreads' );
265 - // Begin with with the requirements for being *in* the archive.
266 - $startdate = Date::now()->nDaysAgo($this->archive_start_days)->midnight();
267 - $where = array(Threads::articleClause($this->article),
268 - 'thread.thread_parent is null',
269 - '(thread.thread_summary_page is not null' .
270 - ' OR thread.thread_type = '.Threads::TYPE_MOVED.')',
271 - 'thread.thread_modified < ' . $startdate->text());
272 - $options = array('ORDER BY thread.thread_modified DESC');
273 -
274 - $annotations = array( wfMsg ( 'lqt-searching' ));
275 -
276 - $r = $this->request;
277 -
278 - /* START AND END DATES */
279 - // $this->start and $this->end are clipped into the range of available
280 - // months, for use in the actual query and the selects. $this->raw* are
281 - // as actually provided, for use by the 'older' and 'newer' buttons.
282 - $ignore_dates = ! $r->getVal('lqt_archive_filter_by_date', true);
283 - if ( !$ignore_dates ) {
284 - $months = Threads::monthsWhereArticleHasThreads($this->article);
285 - }
286 - $s = $r->getVal('lqt_archive_start');
287 - if ($s && ctype_digit($s) && strlen($s) == 6 && !$ignore_dates) {
288 - $this->selstart = new Date( "{$s}01000000" );
289 - $this->starti = array_search($s, $months);
290 - $where[] = 'thread.thread_modified >= ' . $this->selstart->text();
291 - }
292 - $e = $r->getVal('lqt_archive_end');
293 - if ($e && ctype_digit($e) && strlen($e) == 6 && !$ignore_dates) {
294 - $this->selend = new Date("{$e}01000000");
295 - $this->endi = array_search($e, $months);
296 - $where[] = 'thread.thread_modified < ' . $this->selend->nextMonth()->text();
297 - }
298 - if ( isset($this->selstart) && isset($this->selend) ) {
299 -
300 - $this->datespan = $this->starti - $this->endi;
301 -
302 - $formattedFrom = $this->formattedMonth($this->selstart->text());
303 - $formattedTo = $this->formattedMonth($this->selend->text());
304 -
305 - if( $this->datespan == 0 ) {
306 - $annotations[] = wfMsg('lqt_archive_month_annotation', $formattedFrom);
307 - } else {
308 - $annotations[] = wfMsg('lqt_archive_month_range_annotation', $formattedFrom, $formattedTo);
309 - }
310 - } else if (isset($this->selstart)) {
311 - $annotations[] = "after {$this->selstart->text()}";
312 - } else if (isset($this->selend)) {
313 - $annotations[] = "before {$this->selend->text()}";
314 - }
315 -
316 - $this->where = $where;
317 - $this->options = $options;
318 - $this->annotations = implode("<br />\n", $annotations);
319 - }
320 -
321 - function threads() {
322 - return Threads::where($this->where, $this->options);
323 - }
324 -
325 - function formattedMonth($yyyymm) {
326 - global $wgLang; // TODO global.
327 - return $wgLang->getMonthName( substr($yyyymm, 4, 2) ).' '.substr($yyyymm, 0, 4);
328 - }
329 -
330 - function monthSelect($months, $name) {
331 - $selection = $this->request->getVal($name);
332 -
333 - // Silently adjust to stay in range.
334 - $selection = max( min( $selection, $months[0] ), $months[count($months)-1] );
335 -
336 - $options = array();
337 - foreach($months as $m) {
338 - $options[$this->formattedMonth($m)] = $m;
339 - }
340 - $result = "<select name=\"$name\" id=\"$name\">";
341 - foreach( $options as $label => $value ) {
342 - $selected = $selection == $value ? 'selected="true"' : '';
343 - $result .= "<option value=\"$value\" $selected>$label";
344 - }
345 - $result .= "</select>";
346 - return $result;
347 - }
348 -
349 - function clip( $vals, $min, $max ) {
350 - $res = array();
351 - foreach($vals as $val) $res[] = max( min( $val, $max ), $min );
352 - return $res;
353 - }
354 -
355 - /* @return True if there are no threads to show, false otherwise.
356 - TODO is is somewhat bizarre. */
357 - function showSearchForm() {
358 - $months = Threads::monthsWhereArticleHasThreads($this->article);
359 - if (count($months) == 0) {
360 - return true;
361 - }
362 - wfLoadExtensionMessages( 'LiquidThreads' );
363 -
364 - $use_dates = $this->request->getVal('lqt_archive_filter_by_date', null);
365 - if ( $use_dates === null ) {
366 - $use_dates = $this->request->getBool('lqt_archive_start', false) ||
367 - $this->request->getBool('lqt_archive_end', false);
368 - }
369 - $any_date_check = !$use_dates ? 'checked="1"' : '';
370 - $these_dates_check = $use_dates ? 'checked="1"' : '';
371 - $any_date = wfMsg ( 'lqt-any-date' );
372 - $only_date= wfMsg ( 'lqt-only-date' );
373 - $date_from= wfMsg ( 'lqt-date-from' );
374 - $date_to = wfMsg ( 'lqt-date-to' );
375 - $date_info = wfMsg ( 'lqt-date-info' );
376 - if( isset($this->datespan) ) {
377 - $oatte = $this->starti + 1;
378 - $oatts = $this->starti + 1 + $this->datespan;
379 -
380 - $natts = $this->endi - 1;
381 - $natte = $this->endi - 1 - $this->datespan;
382 -
383 - list($oe, $os, $ns, $ne) =
384 - $this->clip( array($oatte, $oatts, $natts, $natte),
385 - 0, count($months)-1 );
386 -
387 - $older = '<a class="lqt_newer_older" href="' . $this->queryReplace(array(
388 - 'lqt_archive_filter_by_date'=>'1',
389 - 'lqt_archive_start' => $months[$os],
390 - 'lqt_archive_end' => $months[$oe]))
391 - . '">«'.wfMsg ( 'lqt-older' ).'</a>';
392 - $newer = '<a class="lqt_newer_older" href="' . $this->queryReplace(array(
393 - 'lqt_archive_filter_by_date'=>'1',
394 - 'lqt_archive_start' => $months[$ns],
395 - 'lqt_archive_end' => $months[$ne]))
396 - . '">'.wfMsg ( 'lqt-newer' ).'»</a>';
397 - }
398 - else {
399 - $older = '<span class="lqt_newer_older_disabled" title="'.wfMsg ( 'lqt-date-info' ).'">«'.wfMsg ( 'lqt-older' ).'</span>';
400 - $newer = '<span class="lqt_newer_older_disabled" title="'.wfMsg ( 'lqt-date-info' ).'">'.wfMsg ( 'lqt-newer' ).'»</span>';
401 - }
402 -
403 - $this->output->addHTML(<<<HTML
404 -<form id="lqt_archive_search_form" action="{$this->title->getLocalURL()}">
405 -<input type="hidden" name="lqt_method" value="talkpage_archive">
406 -<input type="hidden" name="title" value="{$this->title->getPrefixedURL()}"
407 -
408 -<input type="radio" id="lqt_archive_filter_by_date_no"
409 -name="lqt_archive_filter_by_date" value="0" {$any_date_check}>
410 -<label for="lqt_archive_filter_by_date_no">{$any_date}</label> <br />
411 -<input type="radio" id="lqt_archive_filter_by_date_yes"
412 -name="lqt_archive_filter_by_date" value="1" {$these_dates_check}>
413 -<label for="lqt_archive_filter_by_date_yes">{$only_date}</label> <br />
414 -
415 -<table>
416 -<tr><td><label for="lqt_archive_start">{$date_from}</label>
417 -<td>{$this->monthSelect($months, 'lqt_archive_start')} <br />
418 -<tr><td><label for="lqt_archive_end">{$date_to}</label>
419 -<td>{$this->monthSelect($months, 'lqt_archive_end')}
420 -</table>
421 -<input type="submit">
422 -$older $newer
423 -</form>
424 -HTML
425 - );
426 - return false;
427 - }
428 -
429 - function show() {
430 - global $wgHooks;
431 - $wgHooks['SkinTemplateTabs'][] = array($this, 'customizeTabs');
432 -
433 - $this->output->setPageTitle( $this->title->getTalkpage()->getPrefixedText() );
434 - self::addJSandCSS();
435 - wfLoadExtensionMessages( 'LiquidThreads' );
436 -
437 - $empty = $this->showSearchForm();
438 - if ($empty) {
439 - $this->output->addHTML('<p><br /><b>'. wfMsg('lqt-nothread' ) . '</b></p>' );
440 - return false;
441 - }
442 - $lqt_title = wfMsg ( 'lqt-title');
443 - $lqt_summary = wfMsg ( 'lqt-summary' );
444 - $this->output->addHTML(<<<HTML
445 -<p class="lqt_search_annotations">{$this->annotations}</p>
446 -<table class="lqt_archive_listing">
447 -<col class="lqt_titles" />
448 -<col class="lqt_summaries" />
449 -<tr><th>{$lqt_title}<th>{$lqt_summary}</tr>
450 -HTML
451 - );
452 - foreach ($this->threads() as $t) {
453 - $this->showThread($t);
454 - }
455 - $this->output->addHTML('</table>');
456 -
457 - return false;
458 - }
459 -}
460 -
461 -class ThreadPermalinkView extends LqtView {
462 - protected $thread;
463 -
464 - function customizeTabs( $skintemplate, $content_actions ) {
465 - wfLoadExtensionMessages( 'LiquidThreads' );
466 - // Insert fake 'article' and 'discussion' tabs before the thread tab.
467 - // If you call the key 'talk', the url gets re-set later. TODO:
468 - // the access key for the talk tab doesn't work.
469 - $article_t = $this->thread->article()->getTitle();
470 - $talk_t = $this->thread->article()->getTitle()->getTalkPage();
471 - efInsertIntoAssoc('article', array(
472 - 'text'=>wfMsg($article_t->getNamespaceKey()),
473 - 'href'=>$article_t->getFullURL(),
474 - 'class' => $article_t->exists() ? '' : 'new'),
475 - 'nstab-thread', $content_actions);
476 - efInsertIntoAssoc('not_talk', array(
477 - // talkpage certainly exists since this thread is from it.
478 - 'text'=>wfMsg('talk'),
479 - 'href'=>$talk_t->getFullURL()),
480 - 'nstab-thread', $content_actions);
481 -
482 - unset($content_actions['edit']);
483 - unset($content_actions['viewsource']);
484 - unset($content_actions['talk']);
485 - if( array_key_exists( 'move', $content_actions ) && $this->thread ) {
486 - $content_actions['move']['href'] =
487 - SpecialPage::getTitleFor('MoveThread')->getFullURL() . '/' .
488 - $this->thread->title()->getPrefixedURL();
489 - }
490 - if( array_key_exists( 'delete', $content_actions ) && $this->thread ) {
491 - $content_actions['delete']['href'] =
492 - SpecialPage::getTitleFor('DeleteThread')->getFullURL() . '/' .
493 - $this->thread->title()->getPrefixedURL();
494 - }
495 -
496 - if( array_key_exists('history', $content_actions) ) {
497 - $content_actions['history']['href'] = $this->permalinkUrl( $this->thread, 'thread_history' );
498 - if( $this->methodApplies('thread_history') ) {
499 - $content_actions['history']['class'] = 'selected';
500 - }
501 - }
502 -
503 - return true;
504 - }
505 -
506 - function showThreadHeading( $thread ) {
507 - if ( $this->headerLevel == 2 ) {
508 - $this->output->setPageTitle( $thread->wikilink() );
509 - } else {
510 - parent::showThreadHeading($thread);
511 - }
512 - }
513 -
514 - function noSuchRevision() {
515 - wfLoadExtensionMessages( 'LiquidThreads' );
516 - $this->output->addHTML(wfMsg('lqt_nosuchrevision'));
517 - }
518 -
519 - function showMissingThreadPage() {
520 - wfLoadExtensionMessages( 'LiquidThreads' );
521 - $this->output->addHTML(wfMsg('lqt_nosuchthread'));
522 - }
523 -
524 - function getSubtitle() {
525 - wfLoadExtensionMessages( 'LiquidThreads' );
526 - // TODO the archive month part is obsolete.
527 - if (Date::now()->nDaysAgo(30)->midnight()->isBefore( new Date($this->thread->modified()) ))
528 - $query = '';
529 - else
530 - $query = 'lqt_archive_month=' . substr($this->thread->modified(),0,6);
531 - $talkpage = $this->thread->article()->getTitle()->getTalkpage();
532 - $talkpage_link = $this->user->getSkin()->makeKnownLinkObj($talkpage, '', $query);
533 - if ( $this->thread->hasSuperthread() ) {
534 - return wfMsg('lqt_fragment',"<a href=\"{$this->permalinkUrl($this->thread->topmostThread())}\">".wfMsg('lqt_discussion_link')."</a>",$talkpage_link);
535 - } else {
536 - return wfMsg('lqt_from_talk', $talkpage_link);
537 - }
538 - }
539 -
540 - function __construct(&$output, &$article, &$title, &$user, &$request) {
541 -
542 - parent::__construct($output, $article, $title, $user, $request);
543 -
544 - $t = Threads::withRoot( $this->article );
545 - $r = $this->request->getVal('lqt_oldid', null); if( $r ) {
546 - $t = $t->atRevision($r);
547 - if( !$t ) { $this->noSuchRevision(); return; }
548 -
549 - }
550 - $this->thread = $t;
551 - if( ! $t ) {
552 - return; // error reporting is handled in show(). this kinda sucks.
553 - }
554 -
555 - // $this->article gets saved to thread_article, so we want it to point to the
556 - // subject page associated with the talkpage, always, not the permalink url.
557 - $this->article = $t->article(); # for creating reply threads.
558 -
559 - }
560 -
561 - function show() {
562 - global $wgHooks;
563 - $wgHooks['SkinTemplateTabs'][] = array($this, 'customizeTabs');
564 -
565 - if( ! $this->thread ) {
566 - $this->showMissingThreadPage();
567 - return false;
568 - }
569 -
570 - self::addJSandCSS();
571 - $this->output->setSubtitle($this->getSubtitle());
572 -
573 - if( $this->methodApplies('summarize') )
574 - $this->showSummarizeForm($this->thread);
575 -
576 - $this->showThread($this->thread);
577 - return false;
578 - }
579 -}
580 -
581 -/*
582 -* Cheap views that just pass through to MW functions.
583 -*/
584 -
585 -class TalkpageHeaderView extends LqtView {
586 - function customizeTabs( $skintemplate, $content_actions ) {
587 - unset($content_actions['edit']);
588 - unset($content_actions['addsection']);
589 - unset($content_actions['history']);
590 - unset($content_actions['watch']);
591 - unset($content_actions['move']);
592 -
593 - $content_actions['talk']['class'] = false;
594 - $content_actions['header'] = array( 'class'=>'selected',
595 - 'text'=>'header',
596 - 'href'=>'');
597 -
598 - return true;
599 - }
600 -
601 - function show() {
602 - global $wgHooks, $wgOut, $wgTitle, $wgRequest;
603 - // Why is a hook added here?
604 - $wgHooks['SkinTemplateTabs'][] = array($this, 'customizeTabs');
605 -
606 - if( $wgRequest->getVal('action') === 'edit' ) {
607 - wfLoadExtensionMessages( 'LiquidThreads' );
608 - $warn_bold = '<strong>' . wfMsg('lqt_header_warning_bold') . '</strong>';
609 - $warn_link = '<a href="'.$this->talkpageUrl($wgTitle, 'talkpage_new_thread').'">'.
610 - wfMsg('lqt_header_warning_new_discussion').'</a>';
611 - $wgOut->addHTML('<p class="lqt_header_warning">' .
612 - wfMsg('lqt_header_warning_before_big', $warn_bold, $warn_link) .
613 - '<big>' . wfMsg('lqt_header_warning_big', $warn_bold, $warn_link) . '</big>' .
614 - wfMsg('lqt_header_warning_after_big', $warn_bold, $warn_link) .
615 - '</p>');
616 - }
617 -
618 - return true;
619 - }
620 -}
621 -
622 -/*
623 -This is invoked in two cases:
624 -(1) the single-article history listing
625 -(2) an old revision of a single article.
626 -*/
627 -class IndividualThreadHistoryView extends ThreadPermalinkView {
628 - protected $oldid;
629 -
630 - function customizeTabs( $skintemplate, $content_actions ) {
631 - $content_actions['history']['class'] = 'selected';
632 - parent::customizeTabs($skintemplate, $content_actions);
633 - return true;
634 - }
635 -
636 - /* This customizes the subtitle of a history *listing* from the hook,
637 - and of an old revision from getSubtitle() below. */
638 - function customizeSubtitle() {
639 - wfLoadExtensionMessages( 'LiquidThreads' );
640 - $msg = wfMsg('lqt_hist_view_whole_thread');
641 - $threadhist = "<a href=\"{$this->permalinkUrl($this->thread->topmostThread(), 'thread_history')}\">$msg</a>";
642 - $this->output->setSubtitle( parent::getSubtitle() . '<br />' . $this->output->getSubtitle() . "<br />$threadhist" );
643 - return true;
644 - }
645 -
646 - /* */
647 - function getSubtitle() {
648 - $this->article->setOldSubtitle($this->oldid);
649 - $this->customizeSubtitle();
650 - return $this->output->getSubtitle();
651 - }
652 -
653 - function show() {
654 - global $wgHooks;
655 - /*
656 - $this->oldid = $this->request->getVal('oldid', null);
657 - if( $this->oldid !== null ) {
658 -
659 - parent::show();
660 - return false;
661 - }
662 - */
663 - $wgHooks['SkinTemplateTabs'][] = array($this, 'customizeTabs');
664 -
665 - $wgHooks['PageHistoryBeforeList'][] = array($this, 'customizeSubtitle');
666 -
667 - return true;
668 - }
669 -}
670 -
671 -class ThreadDiffView {
672 - function customizeTabs( $skintemplate, $content_actions ) {
673 - unset($content_actions['edit']);
674 - unset($content_actions['viewsource']);
675 - unset($content_actions['talk']);
676 -
677 - $content_actions['talk']['class'] = false;
678 - $content_actions['history']['class'] = 'selected';
679 -
680 - return true;
681 - }
682 -
683 - function show() {
684 - global $wgHooks;
685 - $wgHooks['SkinTemplateTabs'][] = array($this, 'customizeTabs');
686 - return true;
687 - }
688 -}
689 -
690 -class ThreadWatchView extends ThreadPermalinkView {
691 - function show() {
692 - global $wgHooks;
693 - $wgHooks['SkinTemplateTabs'][] = array($this, 'customizeTabs');
694 - return true;
695 - }
696 -}
697 -
698 -class ThreadProtectionFormView {
699 - function customizeTabs( $skintemplate, $content_actions ) {
700 - unset($content_actions['edit']);
701 - unset($content_actions['addsection']);
702 - unset($content_actions['viewsource']);
703 - unset($content_actions['talk']);
704 -
705 - $content_actions['talk']['class'] = false;
706 - if ( array_key_exists('protect', $content_actions) )
707 - $content_actions['protect']['class'] = 'selected';
708 - else if ( array_key_exists('unprotect', $content_actions) )
709 - $content_actions['unprotect']['class'] = 'selected';
710 -
711 - return true;
712 - }
713 -
714 - function show() {
715 - global $wgHooks;
716 - $wgHooks['SkinTemplateTabs'][] = array($this, 'customizeTabs');
717 - return true;
718 - }
719 -}
720 -
721 -class ThreadHistoryListingView extends ThreadPermalinkView {
722 -
723 - private function rowForThread($t) {
724 - global $wgLang, $wgOut; // TODO global.
725 - wfLoadExtensionMessages( 'LiquidThreads' );
726 - /* TODO: best not to refer to LqtView class directly. */
727 - /* We don't use oldid because that has side-effects. */
728 - $result = array();
729 - $change_names = array( Threads::CHANGE_EDITED_ROOT => wfMsg('lqt_hist_comment_edited'),
730 - Threads::CHANGE_EDITED_SUMMARY => wfMsg('lqt_hist_summary_changed'),
731 - Threads::CHANGE_REPLY_CREATED => wfMsg('lqt_hist_reply_created'),
732 - Threads::CHANGE_NEW_THREAD => wfMsg('lqt_hist_thread_created'),
733 - Threads::CHANGE_DELETED => wfMsg('lqt_hist_deleted'),
734 - Threads::CHANGE_UNDELETED => wfMsg('lqt_hist_undeleted'),
735 - Threads::CHANGE_MOVED_TALKPAGE => wfMsg('lqt_hist_moved_talkpage'));
736 - $change_label = array_key_exists($t->changeType(), $change_names) ? $change_names[$t->changeType()] : "";
737 -
738 - $url = LqtView::permalinkUrlWithQuery( $this->thread, 'lqt_oldid=' . $t->revisionNumber() );
739 -
740 - $user_id = $t->changeUser()->getID(); # ever heard of a User object?
741 - $user_text = $t->changeUser()->getName();
742 - $sig = $this->user->getSkin()->userLink( $user_id, $user_text ) .
743 - $this->user->getSkin()->userToolLinks( $user_id, $user_text );
744 -
745 - $change_comment=$t->changeComment();
746 - if(!empty($change_comment))
747 - $change_comment="<em>($change_comment)</em>";
748 -
749 - $result[] = "<tr>";
750 - $result[] = "<td><a href=\"$url\">" . $wgLang->timeanddate($t->modified()) . "</a></td>";
751 - $result[] = "<td>" . $sig . "</td>";
752 - $result[] = "<td>$change_label</td>";
753 - $result[] = "<td>$change_comment</td>";
754 - $result[] = "</tr>";
755 - return implode('', $result);
756 - }
757 -
758 - function showHistoryListing($t) {
759 - wfLoadExtensionMessages( 'LiquidThreads' );
760 - $revisions = new ThreadHistoryIterator($t, $this->perPage, $this->perPage * ($this->page - 1));
761 -
762 - $this->output->addHTML('<table>');
763 - foreach($revisions as $ht) {
764 - $this->output->addHTML($this->rowForThread($ht));
765 - }
766 - $this->output->addHTML('</table>');
767 -
768 - if ( count($revisions) == 0 && $this->page == 1 ) {
769 - $this->output->addHTML('<p>'.wfMsg('lqt_hist_no_revisions_error'));
770 - }
771 - else if ( count($revisions) == 0 ) {
772 - // we could redirect to the previous page... yow.
773 - $this->output->addHTML('<p>'.wfMsg('lqt_hist_past_last_page_error'));
774 - }
775 -
776 - if( $this->page > 1 ) {
777 - $this->output->addHTML( '<a class="lqt_newer_older" href="' . $this->queryReplace(array('lqt_hist_page'=>$this->page - 1)) .'">'.wfMsg('lqt_newer').'</a>' );
778 - } else {
779 - $this->output->addHTML( '<span class="lqt_newer_older_disabled" title="'.wfMsg('lqt_hist_tooltip_newer_disabled').'">'.wfMsg('lqt_newer').'</span>' );
780 - }
781 -
782 - $is_last_page = false;
783 - foreach($revisions as $r)
784 - if( $r->changeType() == Threads::CHANGE_NEW_THREAD )
785 - $is_last_page = true;
786 - if( $is_last_page ) {
787 - $this->output->addHTML( '<span class="lqt_newer_older_disabled" title="'.wfMsg('lqt_hist_tooltip_older_disabled').'">'.wfMsg('lqt_older').'</span>' );
788 - } else {
789 - $this->output->addHTML( '<a class="lqt_newer_older" href="' . $this->queryReplace(array('lqt_hist_page'=>$this->page + 1)) . '">'.wfMsg('lqt_older').'</a>' );
790 - }
791 - }
792 -
793 - function __construct(&$output, &$article, &$title, &$user, &$request) {
794 - parent::__construct($output, $article, $title, $user, $request);
795 - $this->loadParametersFromRequest();
796 - }
797 -
798 - function loadParametersFromRequest() {
799 - $this->perPage = $this->request->getInt('lqt_hist_per_page', 10);
800 - $this->page = $this->request->getInt('lqt_hist_page', 1);
801 - }
802 -
803 - function show() {
804 - global $wgHooks;
805 - $wgHooks['SkinTemplateTabs'][] = array($this, 'customizeTabs');
806 -
807 - if( ! $this->thread ) {
808 - $this->showMissingThreadPage();
809 - return false;
810 - }
811 - self::addJSandCSS();
812 - wfLoadExtensionMessages( 'LiquidThreads' );
813 -
814 - $this->output->setSubtitle($this->getSubtitle() . '<br />' . wfMsg('lqt_hist_listing_subtitle'));
815 -
816 - $this->showThreadHeading($this->thread);
817 - $this->showHistoryListing($this->thread);
818 -
819 - $this->showThread($this->thread);
820 -
821 - return false;
822 - }
823 -}
824 -
825 -class ThreadHistoricalRevisionView extends ThreadPermalinkView {
826 -
827 - /* TOOD: customize tabs so that History is highlighted. */
828 -
829 - function postDivClass($thread) {
830 - $is_changed_thread = $thread->changeObject() &&
831 - $thread->changeObject()->id() == $thread->id();
832 - if ( $is_changed_thread )
833 - return 'lqt_post_changed_by_history';
834 - else
835 - return 'lqt_post';
836 - }
837 -
838 - function showHistoryInfo() {
839 - global $wgLang; // TODO global.
840 - wfLoadExtensionMessages( 'LiquidThreads' );
841 - $this->openDiv('lqt_history_info');
842 - $this->output->addHTML(wfMsg('lqt_revision_as_of', $wgLang->timeanddate($this->thread->modified())) .'<br />' );
843 -
844 - $ct = $this->thread->changeType();
845 - if( $ct == Threads::CHANGE_NEW_THREAD ) $msg = wfMsg('lqt_change_new_thread');
846 - else if( $ct == Threads::CHANGE_REPLY_CREATED ) $msg = wfMsg('lqt_change_reply_created');
847 - else if( $ct == Threads::CHANGE_EDITED_ROOT ) {
848 - $diff_url = $this->permalinkUrlWithDiff($this->thread);
849 - $msg = wfMsg('lqt_change_edited_root') . " [<a href=\"$diff_url\">" . wfMsg('diff') . '</a>]';
850 - }
851 - $this->output->addHTML($msg);
852 - $this->closeDiv();
853 - }
854 -
855 - function show() {
856 - if( ! $this->thread ) {
857 - $this->showMissingThreadPage();
858 - return false;
859 - }
860 - $this->showHistoryInfo();
861 - parent::show();
862 - return false;
863 - }
864 -}
865 -
866 -
867 -class SummaryPageView extends LqtView {
868 - function show() {
869 - wfLoadExtensionMessages( 'LiquidThreads' );
870 - $thread = Threads::withSummary($this->article);
871 - if( $thread ) {
872 - $url = $thread->root()->getTitle()->getFullURL();
873 - $name = $thread->root()->getTitle()->getPrefixedText();
874 - $this->output->setSubtitle(
875 - wfMsg('lqt_summary_subtitle',
876 - '<a href="'.$url.'">'.$name.'</a>'));
877 - }
878 - return true;
879 - }
880 -}
881 -
882 -
883 -class SpecialMoveThread extends UnlistedSpecialPage {
884 - private $user, $output, $request, $title, $thread;
885 -
886 - function __construct() {
887 - parent::__construct( 'Movethread' );
888 - $this->includable( false );
889 - }
890 -
891 - /**
892 - * @see SpecialPage::getDescription
893 - */
894 - function getDescription() {
895 - wfLoadExtensionMessages( 'LiquidThreads' );
896 - return wfMsg( 'lqt_movethread' );
897 - }
898 -
899 - function handleGet() {
900 - wfLoadExtensionMessages( 'LiquidThreads' );
901 - $form_action = $this->title->getLocalURL() . '/' . $this->thread->title()->getPrefixedURL();
902 - $thread_name = $this->thread->title()->getPrefixedText();
903 - $article_name = $this->thread->article()->getTitle()->getTalkPage()->getPrefixedText();
904 - $edit_url = LqtView::permalinkUrl($this->thread, 'edit', $this->thread);
905 - $wfMsg = 'wfMsg'; // functions can only be called within string expansion by variable name.
906 - $this->output->addHTML(<<<HTML
907 -<p>{$wfMsg('lqt_move_movingthread', "<b>$thread_name</b>", "<b>$article_name</b>")}</p>
908 -<p>{$wfMsg('lqt_move_torename', "<a href=\"$edit_url\">{$wfMsg('lqt_move_torename_edit')}</a>")}</p>
909 -<form id="lqt_move_thread_form" action="$form_action" method="POST">
910 -<table>
911 -<tr>
912 -<td><label for="lqt_move_thread_target_title">{$wfMsg('lqt_move_destinationtitle')}</label></td>
913 -<td><input id="lqt_move_thread_target_title" name="lqt_move_thread_target_title" tabindex="100" size="40" /></td>
914 -</tr><tr>
915 -<td><label for="lqt_move_thread_reason">{$wfMsg('movereason')}</label></td>
916 -<td><input id="lqt_move_thread_reason" name="lqt_move_thread_reason" tabindex="200" size="40" /></td>
917 -</tr><tr>
918 -<td>&nbsp;</td>
919 -<td><input type="submit" value="{$wfMsg('lqt_move_move')}" style="float:right;" tabindex="300" /></td>
920 -</tr>
921 -</table>
922 -</form>
923 -HTML
924 - );
925 -
926 - }
927 -
928 - function checkUserRights() {
929 - if ( !$this->user->isAllowed( 'move' ) ) {
930 - $this->output->showErrorPage( 'movenologin', 'movenologintext' );
931 - return false;
932 - }
933 - if ( $this->user->isBlocked() ) {
934 - $this->output->blockedPage();
935 - return false;
936 - }
937 - if ( wfReadOnly() ) {
938 - $this->output->readOnlyPage();
939 - return false;
940 - }
941 - if ( $this->user->pingLimiter( 'move' ) ) {
942 - $this->output->rateLimited();
943 - return false;
944 - }
945 - /* Am I forgetting anything? */
946 - return true;
947 - }
948 -
949 - function redisplayForm($problem_fields, $message) {
950 - $this->output->addHTML($message);
951 - $this->handleGet();
952 - }
953 -
954 - function handlePost() {
955 - if( !$this->checkUserRights() ) return;
956 - wfLoadExtensionMessages( 'LiquidThreads' );
957 -
958 - $tmp = $this->request->getVal('lqt_move_thread_target_title');
959 - if( $tmp === "" ) {
960 - $this->redisplayForm(array('lqt_move_thread_target_title'), wfMsg('lqt_move_nodestination'));
961 - return;
962 - }
963 - $newtitle = Title::newFromText( $tmp )->getSubjectPage();
964 -
965 - $reason = $this->request->getVal('lqt_move_thread_reason', wfMsg('lqt_noreason'));
966 -
967 - // TODO no status code from this method.
968 - $this->thread->moveToSubjectPage( $newtitle, $reason, true );
969 -
970 - $this->showSuccessMessage( $newtitle->getTalkPage() );
971 - }
972 -
973 - function showSuccessMessage( $target_title ) {
974 - wfLoadExtensionMessages( 'LiquidThreads' );
975 - $this->output->addHTML(wfMsg('lqt_move_success',
976 - '<a href="'.$target_title->getFullURL().'">'.$target_title->getPrefixedText().'</a>'));
977 - }
978 -
979 - function execute( $par ) {
980 - global $wgOut, $wgRequest, $wgTitle, $wgUser;
981 - $this->user = $wgUser;
982 - $this->output = $wgOut;
983 - $this->request = $wgRequest;
984 - $this->title = $wgTitle;
985 -
986 - $this->setHeaders();
987 -
988 - if( $par === null || $par === "") {
989 - wfLoadExtensionMessages( 'LiquidThreads' );
990 - $this->output->addHTML(wfMsg('lqt_threadrequired'));
991 - return;
992 - }
993 - // TODO should implement Threads::withTitle(...).
994 - $thread = Threads::withRoot( new Article(Title::newFromURL($par)) );
995 - if (!$thread) {
996 - wfLoadExtensionMessages( 'LiquidThreads' );
997 - $this->output->addHTML(wfMsg('lqt_nosuchthread'));
998 - return;
999 - }
1000 -
1001 - $this->thread = $thread;
1002 -
1003 - if ( $this->request->wasPosted() ) {
1004 - $this->handlePost();
1005 - } else {
1006 - $this->handleGet();
1007 - }
1008 -
1009 - }
1010 -}
1011 -
1012 -class SpecialDeleteThread extends UnlistedSpecialPage {
1013 - private $user, $output, $request, $title, $thread;
1014 -
1015 - function __construct() {
1016 - parent::__construct( 'Deletethread' );
1017 - $this->includable( false );
1018 - }
1019 -
1020 - /**
1021 - * @see SpecialPage::getDescription
1022 - */
1023 - function getDescription() {
1024 - wfLoadExtensionMessages( 'LiquidThreads' );
1025 - return wfMsg( 'lqt_deletethread' );
1026 - }
1027 -
1028 - function handleGet() {
1029 - if( !$this->checkUserRights() ) return;
1030 - wfLoadExtensionMessages( 'LiquidThreads' );
1031 -
1032 - $form_action = $this->title->getLocalURL() . '/' . $this->thread->title()->getPrefixedURL();
1033 - $thread_name = $this->thread->title()->getPrefixedText();
1034 - $article_name = $this->thread->article()->getTitle()->getTalkPage()->getPrefixedText();
1035 -
1036 - $deleting = $this->thread->type() != Threads::TYPE_DELETED;
1037 -
1038 - $operation_message = $deleting ?
1039 - wfMsg('lqt_delete_deleting', "<b>$thread_name</b>", '<b>'.wfMsg('lqt_delete_deleting_allreplies').'</b>')
1040 - // "Deleting <b>$thread_name</b> and <b>all replies</b> to it."
1041 - : wfMsg('lqt_delete_undeleting', "<b>$thread_name</b>");
1042 - $button_label = $deleting ?
1043 - wfMsg('lqt_delete_deletethread')
1044 - : wfMsg('lqt_delete_undeletethread');
1045 - $part_of = wfMsg('lqt_delete_partof', '<b>'.$article_name.'</b>');
1046 - $reason = wfMsg('movereason'); // XXX arguably wrong to use movereason.
1047 -
1048 - $this->output->addHTML(<<<HTML
1049 -<p>$operation_message
1050 -$part_of</p>
1051 -<form id="lqt_delete_thread_form" action="{$form_action}" method="POST">
1052 -<table>
1053 -<tr>
1054 -<td><label for="lqt_delete_thread_reason">$reason</label></td>
1055 -<td><input id="lqt_delete_thread_reason" name="lqt_delete_thread_reason" tabindex="200" size="40" /></td>
1056 -</tr><tr>
1057 -<td>&nbsp;</td>
1058 -<td><input type="submit" value="$button_label" style="float:right;" tabindex="300" /></td>
1059 -</tr>
1060 -</table>
1061 -</form>
1062 -HTML
1063 - );
1064 -
1065 - }
1066 -
1067 - function checkUserRights() {
1068 - if( in_array('delete', $this->user->getRights()) ) {
1069 - return true;
1070 - } else {
1071 - wfLoadExtensionMessages( 'LiquidThreads' );
1072 - $this->output->addHTML(wfMsg('lqt_delete_unallowed'));
1073 - return false;
1074 - }
1075 - }
1076 -
1077 - function redisplayForm($problem_fields, $message) {
1078 - $this->output->addHTML($message);
1079 - $this->handleGet();
1080 - }
1081 -
1082 - function handlePost() {
1083 - // in theory the model should check rights...
1084 - if( !$this->checkUserRights() ) return;
1085 - wfLoadExtensionMessages( 'LiquidThreads' );
1086 -
1087 - $reason = $this->request->getVal('lqt_delete_thread_reason', wfMsg('lqt_noreason'));
1088 -
1089 - // TODO: in theory, two fast-acting sysops could undo each others' work.
1090 - $is_deleted_already = $this->thread->type() == Threads::TYPE_DELETED;
1091 - if ( $is_deleted_already ) {
1092 - $this->thread->undelete($reason);
1093 - } else {
1094 - $this->thread->delete($reason);
1095 - }
1096 - $this->showSuccessMessage( $is_deleted_already );
1097 - }
1098 -
1099 - function showSuccessMessage( $is_deleted_already ) {
1100 - wfLoadExtensionMessages( 'LiquidThreads' );
1101 - // TODO talkpageUrl should accept threads, and look up their talk pages.
1102 - $talkpage_url = LqtView::talkpageUrl($this->thread->article()->getTitle()->getTalkpage());
1103 - $message = $is_deleted_already ? wfMsg('lqt_delete_undeleted') : wfMsg('lqt_delete_deleted');
1104 - $message .= ' ';
1105 - $message .= wfMsg('lqt_delete_return', '<a href="'.$talkpage_url.'">'.wfMsg('lqt_delete_return_link').'</a>');
1106 - $this->output->addHTML($message);
1107 - }
1108 -
1109 - function execute( $par ) {
1110 - global $wgOut, $wgRequest, $wgTitle, $wgUser;
1111 - $this->user = $wgUser;
1112 - $this->output = $wgOut;
1113 - $this->request = $wgRequest;
1114 - $this->title = $wgTitle;
1115 -
1116 - $this->setHeaders();
1117 -
1118 - if( $par === null || $par === "") {
1119 - wfLoadExtensionMessages( 'LiquidThreads' );
1120 - $this->output->addHTML(wfMsg('lqt_threadrequired'));
1121 - return;
1122 - }
1123 - // TODO should implement Threads::withTitle(...).
1124 - $thread = Threads::withRoot( new Article(Title::newFromURL($par)) );
1125 - if (!$thread) {
1126 - wfLoadExtensionMessages( 'LiquidThreads' );
1127 - $this->output->addHTML(wfMsg('lqt_nosuchthread'));
1128 - return;
1129 - }
1130 -
1131 - $this->thread = $thread;
1132 -
1133 - if ( $this->request->wasPosted() ) {
1134 - $this->handlePost();
1135 - } else {
1136 - $this->handleGet();
1137 - }
1138 -
1139 - }
1140 -}
1141 -
1142 -class NewUserMessagesView extends LqtView {
1143 -
1144 - protected $threads;
1145 - protected $tops;
1146 - protected $targets;
1147 -
1148 - protected function htmlForReadButton($label, $title, $class, $ids) {
1149 - $ids_s = implode(',', $ids);
1150 - return <<<HTML
1151 - <form method="POST" class="{$class}">
1152 - <input type="hidden" name="lqt_method" value="mark_as_read" />
1153 - <input type="hidden" name="lqt_operand" value="{$ids_s}" />
1154 - <input type="submit" value="{$label}" name="lqt_read_button" title="{$title}" />
1155 - </form>
1156 -HTML;
1157 - }
1158 -
1159 - function showReadAllButton($threads) {
1160 - wfLoadExtensionMessages( 'LiquidThreads' );
1161 - $ids = array_map(create_function('$t', 'return $t->id();'), $threads);
1162 - $this->output->addHTML(
1163 - $this->htmlForReadButton(
1164 - wfMsg('lqt-read-all'),
1165 - wfMsg('lqt-read-all-tooltip'),
1166 - "lqt_newmessages_read_all_button",
1167 - $ids )
1168 - );
1169 - }
1170 -
1171 - function preShowThread($t) {
1172 - wfLoadExtensionMessages( 'LiquidThreads' );
1173 - // $t_ids = implode(',', array_map(create_function('$t', 'return $t->id();'), $this->targets[$t->id()]));
1174 - $read_button = $this->htmlForReadButton(
1175 - wfMsg('lqt-read-message'),
1176 - wfMsg('lqt-read-message-tooltip'),
1177 - 'lqt_newmessages_read_button',
1178 - $this->targets[$t->id()]);
1179 - $this->output->addHTML(<<<HTML
1180 -<table ><tr>
1181 -<td style="padding-right: 1em; vertical-align: top; padding-top: 1em;" >
1182 -$read_button
1183 -</td>
1184 -<td>
1185 -HTML
1186 - );
1187 - }
1188 -
1189 - function postShowThread($t) {
1190 - $this->output->addHTML(<<<HTML
1191 -</td>
1192 -</tr></table>
1193 -HTML
1194 - );
1195 - }
1196 -
1197 - function showUndo($ids) {
1198 - wfLoadExtensionMessages( 'LiquidThreads' );
1199 - if( count($ids) == 1 ) {
1200 - $t = Threads::withId($ids[0]);
1201 - if( !$t )
1202 - return; // empty or just bogus operand.
1203 - $msg = wfMsg( 'lqt-marked-read',$t->subject() );
1204 - } else {
1205 - $count = count($ids);
1206 - $msg = wfMsg( 'lqt-count-marked-read',$count );
1207 - }
1208 - $operand = implode(',', $ids);
1209 - $lqt_email_undo = wfMsg ( 'lqt-email-undo' );
1210 - $lqt_info_undo = wfMsg ( 'lqt-email-info-undo' );
1211 - $this->output->addHTML(<<<HTML
1212 -<form method="POST" class="lqt_undo_mark_as_read">
1213 -$msg
1214 -<input type="hidden" name="lqt_method" value="mark_as_unread" />
1215 -<input type="hidden" name="lqt_operand" value="{$operand}" />
1216 -<input type="submit" value="{$lqt_email_undo}" name="lqt_read_button" title="{$lqt_info_undo}" />
1217 -</form>
1218 -HTML
1219 - );
1220 - }
1221 -
1222 - function postDivClass($thread) {
1223 - $topid = $thread->topmostThread()->id();
1224 - if( in_array($thread->id(), $this->targets[$topid]) )
1225 - return 'lqt_post_new_message';
1226 - else
1227 - return 'lqt_post';
1228 - }
1229 -
1230 - function showOnce() {
1231 - self::addJSandCSS();
1232 -
1233 - if( $this->request->wasPosted() ) {
1234 - // If they just viewed this page, maybe they still want that notice.
1235 - // But if they took the time to dismiss even one message, they
1236 - // probably don't anymore.
1237 - $this->user->setNewtalk(false);
1238 - }
1239 -
1240 - if( $this->request->wasPosted() && $this->methodApplies('mark_as_unread') ) {
1241 - $ids = explode(',', $this->request->getVal('lqt_operand', ''));
1242 - if( $ids !== false ) {
1243 - foreach($ids as $id) {
1244 - $tmp_thread = Threads::withId($id); if($tmp_thread)
1245 - NewMessages::markThreadAsReadByUser($tmp_thread, $this->user);
1246 - }
1247 - $this->output->redirect( $this->title->getFullURL() );
1248 - }
1249 - }
1250 -
1251 - else if( $this->request->wasPosted() && $this->methodApplies('mark_as_read') ) {
1252 - $ids = explode(',', $this->request->getVal('lqt_operand'));
1253 - if( $ids !== false ) {
1254 - foreach($ids as $id) {
1255 - $tmp_thread = Threads::withId($id); if($tmp_thread)
1256 - NewMessages::markThreadAsReadByUser($tmp_thread, $this->user);
1257 - }
1258 - $query = 'lqt_method=undo_mark_as_read&lqt_operand=' . implode(',', $ids);
1259 - $this->output->redirect( $this->title->getFullURL($query) );
1260 - }
1261 - }
1262 -
1263 - else if( $this->methodApplies('undo_mark_as_read') ) {
1264 - $ids = explode(',', $this->request->getVal('lqt_operand', ''));
1265 - $this->showUndo($ids);
1266 - }
1267 - }
1268 -
1269 - function show() {
1270 - if ( ! is_array( $this->threads ) ) {
1271 - throw new MWException('You must use NewUserMessagesView::setThreads() before calling NewUserMessagesView::show().');
1272 - }
1273 -
1274 - // Do everything by id, because we can't depend on reference identity; a simple Thread::withId
1275 - // can change the cached value and screw up your references.
1276 -
1277 - $this->targets = array();
1278 - $this->tops = array();
1279 - foreach( $this->threads as $t ) {
1280 - $top = $t->topmostThread();
1281 - if( !in_array($top->id(), $this->tops) )
1282 - $this->tops[] = $top->id();
1283 - if( !array_key_exists($top->id(), $this->targets) )
1284 - $this->targets[$top->id()] = array();
1285 - $this->targets[$top->id()][] = $t->id();
1286 - }
1287 -
1288 - foreach($this->tops as $t_id) {
1289 - $t = Threads::withId($t_id);
1290 - // It turns out that with lqtviews composed of threads from various talkpages,
1291 - // each thread is going to have a different article... this is pretty ugly.
1292 - $this->article = $t->article();
1293 -
1294 - $this->preShowThread($t);
1295 - $this->showThread($t);
1296 - $this->postShowThread($t);
1297 - }
1298 - return false;
1299 - }
1300 -
1301 - function setThreads( $threads ) {
1302 - $this->threads = $threads;
1303 - }
1304 -}
1305 -
1306 -class SpecialNewMessages extends SpecialPage {
1307 - private $user, $output, $request, $title;
1308 -
1309 - function __construct() {
1310 - SpecialPage::SpecialPage( 'Newmessages' );
1311 - $this->includable( true );
1312 - }
1313 -
1314 - /**
1315 - * @see SpecialPage::getDescription
1316 - */
1317 - function getDescription() {
1318 - wfLoadExtensionMessages( 'LiquidThreads' );
1319 - return wfMsg( 'lqt_newmessages' );
1320 - }
1321 -
1322 - function execute( $par ) {
1323 - global $wgOut, $wgRequest, $wgTitle, $wgUser;
1324 - wfLoadExtensionMessages( 'LiquidThreads' );
1325 - $this->user = $wgUser;
1326 - $this->output = $wgOut;
1327 - $this->request = $wgRequest;
1328 - $this->title = $wgTitle;
1329 -
1330 - $this->setHeaders();
1331 -
1332 - $view = new NewUserMessagesView( $this->output, new Article($this->title),
1333 - $this->title, $this->user, $this->request );
1334 -
1335 - $view->showOnce(); // handles POST etc.
1336 -
1337 - $first_set = NewMessages::newUserMessages($this->user);
1338 - $second_set = NewMessages::watchedThreadsForUser($this->user);
1339 - $both_sets = array_merge($first_set, $second_set);
1340 - if( count($both_sets) == 0 ) {
1341 - $wgOut->addWikitext( wfMsg('lqt-no-new-messages') );
1342 - return;
1343 - }
1344 - $view->showReadAllButton($both_sets); // ugly hack.
1345 -
1346 - $view->setHeaderLevel(3);
1347 -
1348 - $this->output->addHTML('<h2 class="lqt_newmessages_section">'.wfMsg ( 'lqt-messages-sent' ).'</h2>');
1349 - $view->setThreads( $first_set );
1350 - $view->show();
1351 -
1352 - $this->output->addHTML('<h2 class="lqt_newmessages_section">'.wfMsg ( 'lqt-other-messages' ).'</h2>');
1353 - $view->setThreads( $second_set );
1354 - $view->show();
1355 - }
1356 -}

Status & tagging log