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')."↑</a>]", |
66 | | - "[<a href=\"$historylink\">".wfMsg('history_short')."↑</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> </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> </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 | | -} |