comparison forum/Sources/Recent.php @ 76:e3e11437ecea website

Add forum code
author Chris Cannam
date Sun, 07 Jul 2013 11:25:48 +0200
parents
children
comparison
equal deleted inserted replaced
75:72f59aa7e503 76:e3e11437ecea
1 <?php
2
3 /**
4 * Simple Machines Forum (SMF)
5 *
6 * @package SMF
7 * @author Simple Machines http://www.simplemachines.org
8 * @copyright 2011 Simple Machines
9 * @license http://www.simplemachines.org/about/smf/license.php BSD
10 *
11 * @version 2.0
12 */
13
14 if (!defined('SMF'))
15 die('Hacking attempt...');
16
17 /* This file had one very clear purpose. It is here expressly to find and
18 retrieve information about recently posted topics, messages, and the like.
19
20 array getLastPost()
21 // !!!
22
23 array getLastPosts(int number_of_posts)
24 // !!!
25
26 void RecentPosts()
27 // !!!
28
29 void UnreadTopics()
30 // !!!
31 */
32
33 // Get the latest post.
34 function getLastPost()
35 {
36 global $user_info, $scripturl, $modSettings, $smcFunc;
37
38 // Find it by the board - better to order by board than sort the entire messages table.
39 $request = $smcFunc['db_query']('substring', '
40 SELECT ml.poster_time, ml.subject, ml.id_topic, ml.poster_name, SUBSTRING(ml.body, 1, 385) AS body,
41 ml.smileys_enabled
42 FROM {db_prefix}boards AS b
43 INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = b.id_last_msg)
44 WHERE {query_wanna_see_board}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? '
45 AND b.id_board != {int:recycle_board}' : '') . '
46 AND ml.approved = {int:is_approved}
47 ORDER BY b.id_msg_updated DESC
48 LIMIT 1',
49 array(
50 'recycle_board' => $modSettings['recycle_board'],
51 'is_approved' => 1,
52 )
53 );
54 if ($smcFunc['db_num_rows']($request) == 0)
55 return array();
56 $row = $smcFunc['db_fetch_assoc']($request);
57 $smcFunc['db_free_result']($request);
58
59 // Censor the subject and post...
60 censorText($row['subject']);
61 censorText($row['body']);
62
63 $row['body'] = strip_tags(strtr(parse_bbc($row['body'], $row['smileys_enabled']), array('<br />' => '&#10;')));
64 if ($smcFunc['strlen']($row['body']) > 128)
65 $row['body'] = $smcFunc['substr']($row['body'], 0, 128) . '...';
66
67 // Send the data.
68 return array(
69 'topic' => $row['id_topic'],
70 'subject' => $row['subject'],
71 'short_subject' => shorten_subject($row['subject'], 24),
72 'preview' => $row['body'],
73 'time' => timeformat($row['poster_time']),
74 'timestamp' => forum_time(true, $row['poster_time']),
75 'href' => $scripturl . '?topic=' . $row['id_topic'] . '.new;topicseen#new',
76 'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.new;topicseen#new">' . $row['subject'] . '</a>'
77 );
78 }
79
80 // Find the ten most recent posts.
81 function RecentPosts()
82 {
83 global $txt, $scripturl, $user_info, $context, $modSettings, $sourcedir, $board, $smcFunc;
84
85 loadTemplate('Recent');
86 $context['page_title'] = $txt['recent_posts'];
87
88 if (isset($_REQUEST['start']) && $_REQUEST['start'] > 95)
89 $_REQUEST['start'] = 95;
90
91 $query_parameters = array();
92 if (!empty($_REQUEST['c']) && empty($board))
93 {
94 $_REQUEST['c'] = explode(',', $_REQUEST['c']);
95 foreach ($_REQUEST['c'] as $i => $c)
96 $_REQUEST['c'][$i] = (int) $c;
97
98 if (count($_REQUEST['c']) == 1)
99 {
100 $request = $smcFunc['db_query']('', '
101 SELECT name
102 FROM {db_prefix}categories
103 WHERE id_cat = {int:id_cat}
104 LIMIT 1',
105 array(
106 'id_cat' => $_REQUEST['c'][0],
107 )
108 );
109 list ($name) = $smcFunc['db_fetch_row']($request);
110 $smcFunc['db_free_result']($request);
111
112 if (empty($name))
113 fatal_lang_error('no_access', false);
114
115 $context['linktree'][] = array(
116 'url' => $scripturl . '#c' . (int) $_REQUEST['c'],
117 'name' => $name
118 );
119 }
120
121 $request = $smcFunc['db_query']('', '
122 SELECT b.id_board, b.num_posts
123 FROM {db_prefix}boards AS b
124 WHERE b.id_cat IN ({array_int:category_list})
125 AND {query_see_board}',
126 array(
127 'category_list' => $_REQUEST['c'],
128 )
129 );
130 $total_cat_posts = 0;
131 $boards = array();
132 while ($row = $smcFunc['db_fetch_assoc']($request))
133 {
134 $boards[] = $row['id_board'];
135 $total_cat_posts += $row['num_posts'];
136 }
137 $smcFunc['db_free_result']($request);
138
139 if (empty($boards))
140 fatal_lang_error('error_no_boards_selected');
141
142 $query_this_board = 'b.id_board IN ({array_int:boards})';
143 $query_parameters['boards'] = $boards;
144
145 // If this category has a significant number of posts in it...
146 if ($total_cat_posts > 100 && $total_cat_posts > $modSettings['totalMessages'] / 15)
147 {
148 $query_this_board .= '
149 AND m.id_msg >= {int:max_id_msg}';
150 $query_parameters['max_id_msg'] = max(0, $modSettings['maxMsgID'] - 400 - $_REQUEST['start'] * 7);
151 }
152
153 $context['page_index'] = constructPageIndex($scripturl . '?action=recent;c=' . implode(',', $_REQUEST['c']), $_REQUEST['start'], min(100, $total_cat_posts), 10, false);
154 }
155 elseif (!empty($_REQUEST['boards']))
156 {
157 $_REQUEST['boards'] = explode(',', $_REQUEST['boards']);
158 foreach ($_REQUEST['boards'] as $i => $b)
159 $_REQUEST['boards'][$i] = (int) $b;
160
161 $request = $smcFunc['db_query']('', '
162 SELECT b.id_board, b.num_posts
163 FROM {db_prefix}boards AS b
164 WHERE b.id_board IN ({array_int:board_list})
165 AND {query_see_board}
166 LIMIT {int:limit}',
167 array(
168 'board_list' => $_REQUEST['boards'],
169 'limit' => count($_REQUEST['boards']),
170 )
171 );
172 $total_posts = 0;
173 $boards = array();
174 while ($row = $smcFunc['db_fetch_assoc']($request))
175 {
176 $boards[] = $row['id_board'];
177 $total_posts += $row['num_posts'];
178 }
179 $smcFunc['db_free_result']($request);
180
181 if (empty($boards))
182 fatal_lang_error('error_no_boards_selected');
183
184 $query_this_board = 'b.id_board IN ({array_int:boards})';
185 $query_parameters['boards'] = $boards;
186
187 // If these boards have a significant number of posts in them...
188 if ($total_posts > 100 && $total_posts > $modSettings['totalMessages'] / 12)
189 {
190 $query_this_board .= '
191 AND m.id_msg >= {int:max_id_msg}';
192 $query_parameters['max_id_msg'] = max(0, $modSettings['maxMsgID'] - 500 - $_REQUEST['start'] * 9);
193 }
194
195 $context['page_index'] = constructPageIndex($scripturl . '?action=recent;boards=' . implode(',', $_REQUEST['boards']), $_REQUEST['start'], min(100, $total_posts), 10, false);
196 }
197 elseif (!empty($board))
198 {
199 $request = $smcFunc['db_query']('', '
200 SELECT num_posts
201 FROM {db_prefix}boards
202 WHERE id_board = {int:current_board}
203 LIMIT 1',
204 array(
205 'current_board' => $board,
206 )
207 );
208 list ($total_posts) = $smcFunc['db_fetch_row']($request);
209 $smcFunc['db_free_result']($request);
210
211 $query_this_board = 'b.id_board = {int:board}';
212 $query_parameters['board'] = $board;
213
214 // If this board has a significant number of posts in it...
215 if ($total_posts > 80 && $total_posts > $modSettings['totalMessages'] / 10)
216 {
217 $query_this_board .= '
218 AND m.id_msg >= {int:max_id_msg}';
219 $query_parameters['max_id_msg'] = max(0, $modSettings['maxMsgID'] - 600 - $_REQUEST['start'] * 10);
220 }
221
222 $context['page_index'] = constructPageIndex($scripturl . '?action=recent;board=' . $board . '.%1$d', $_REQUEST['start'], min(100, $total_posts), 10, true);
223 }
224 else
225 {
226 $query_this_board = '{query_wanna_see_board}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? '
227 AND b.id_board != {int:recycle_board}' : ''). '
228 AND m.id_msg >= {int:max_id_msg}';
229 $query_parameters['max_id_msg'] = max(0, $modSettings['maxMsgID'] - 100 - $_REQUEST['start'] * 6);
230 $query_parameters['recycle_board'] = $modSettings['recycle_board'];
231
232 // !!! This isn't accurate because we ignore the recycle bin.
233 $context['page_index'] = constructPageIndex($scripturl . '?action=recent', $_REQUEST['start'], min(100, $modSettings['totalMessages']), 10, false);
234 }
235
236 $context['linktree'][] = array(
237 'url' => $scripturl . '?action=recent' . (empty($board) ? (empty($_REQUEST['c']) ? '' : ';c=' . (int) $_REQUEST['c']) : ';board=' . $board . '.0'),
238 'name' => $context['page_title']
239 );
240
241 $key = 'recent-' . $user_info['id'] . '-' . md5(serialize(array_diff_key($query_parameters, array('max_id_msg' => 0)))) . '-' . (int) $_REQUEST['start'];
242 if (empty($modSettings['cache_enable']) || ($messages = cache_get_data($key, 120)) == null)
243 {
244 $done = false;
245 while (!$done)
246 {
247 // Find the 10 most recent messages they can *view*.
248 // !!!SLOW This query is really slow still, probably?
249 $request = $smcFunc['db_query']('', '
250 SELECT m.id_msg
251 FROM {db_prefix}messages AS m
252 INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
253 WHERE ' . $query_this_board . '
254 AND m.approved = {int:is_approved}
255 ORDER BY m.id_msg DESC
256 LIMIT {int:offset}, {int:limit}',
257 array_merge($query_parameters, array(
258 'is_approved' => 1,
259 'offset' => $_REQUEST['start'],
260 'limit' => 10,
261 ))
262 );
263 // If we don't have 10 results, try again with an unoptimized version covering all rows, and cache the result.
264 if (isset($query_parameters['max_id_msg']) && $smcFunc['db_num_rows']($request) < 10)
265 {
266 $smcFunc['db_free_result']($request);
267 $query_this_board = str_replace('AND m.id_msg >= {int:max_id_msg}', '', $query_this_board);
268 $cache_results = true;
269 unset($query_parameters['max_id_msg']);
270 }
271 else
272 $done = true;
273 }
274 $messages = array();
275 while ($row = $smcFunc['db_fetch_assoc']($request))
276 $messages[] = $row['id_msg'];
277 $smcFunc['db_free_result']($request);
278 if (!empty($cache_results))
279 cache_put_data($key, $messages, 120);
280 }
281
282 // Nothing here... Or at least, nothing you can see...
283 if (empty($messages))
284 {
285 $context['posts'] = array();
286 return;
287 }
288
289 // Get all the most recent posts.
290 $request = $smcFunc['db_query']('', '
291 SELECT
292 m.id_msg, m.subject, m.smileys_enabled, m.poster_time, m.body, m.id_topic, t.id_board, b.id_cat,
293 b.name AS bname, c.name AS cname, t.num_replies, m.id_member, m2.id_member AS id_first_member,
294 IFNULL(mem2.real_name, m2.poster_name) AS first_poster_name, t.id_first_msg,
295 IFNULL(mem.real_name, m.poster_name) AS poster_name, t.id_last_msg
296 FROM {db_prefix}messages AS m
297 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
298 INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
299 INNER JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
300 INNER JOIN {db_prefix}messages AS m2 ON (m2.id_msg = t.id_first_msg)
301 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
302 LEFT JOIN {db_prefix}members AS mem2 ON (mem2.id_member = m2.id_member)
303 WHERE m.id_msg IN ({array_int:message_list})
304 ORDER BY m.id_msg DESC
305 LIMIT ' . count($messages),
306 array(
307 'message_list' => $messages,
308 )
309 );
310 $counter = $_REQUEST['start'] + 1;
311 $context['posts'] = array();
312 $board_ids = array('own' => array(), 'any' => array());
313 while ($row = $smcFunc['db_fetch_assoc']($request))
314 {
315 // Censor everything.
316 censorText($row['body']);
317 censorText($row['subject']);
318
319 // BBC-atize the message.
320 $row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']);
321
322 // And build the array.
323 $context['posts'][$row['id_msg']] = array(
324 'id' => $row['id_msg'],
325 'counter' => $counter++,
326 'alternate' => $counter % 2,
327 'category' => array(
328 'id' => $row['id_cat'],
329 'name' => $row['cname'],
330 'href' => $scripturl . '#c' . $row['id_cat'],
331 'link' => '<a href="' . $scripturl . '#c' . $row['id_cat'] . '">' . $row['cname'] . '</a>'
332 ),
333 'board' => array(
334 'id' => $row['id_board'],
335 'name' => $row['bname'],
336 'href' => $scripturl . '?board=' . $row['id_board'] . '.0',
337 'link' => '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['bname'] . '</a>'
338 ),
339 'topic' => $row['id_topic'],
340 'href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'],
341 'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'] . '" rel="nofollow">' . $row['subject'] . '</a>',
342 'start' => $row['num_replies'],
343 'subject' => $row['subject'],
344 'time' => timeformat($row['poster_time']),
345 'timestamp' => forum_time(true, $row['poster_time']),
346 'first_poster' => array(
347 'id' => $row['id_first_member'],
348 'name' => $row['first_poster_name'],
349 'href' => empty($row['id_first_member']) ? '' : $scripturl . '?action=profile;u=' . $row['id_first_member'],
350 'link' => empty($row['id_first_member']) ? $row['first_poster_name'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_first_member'] . '">' . $row['first_poster_name'] . '</a>'
351 ),
352 'poster' => array(
353 'id' => $row['id_member'],
354 'name' => $row['poster_name'],
355 'href' => empty($row['id_member']) ? '' : $scripturl . '?action=profile;u=' . $row['id_member'],
356 'link' => empty($row['id_member']) ? $row['poster_name'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['poster_name'] . '</a>'
357 ),
358 'message' => $row['body'],
359 'can_reply' => false,
360 'can_mark_notify' => false,
361 'can_delete' => false,
362 'delete_possible' => ($row['id_first_msg'] != $row['id_msg'] || $row['id_last_msg'] == $row['id_msg']) && (empty($modSettings['edit_disable_time']) || $row['poster_time'] + $modSettings['edit_disable_time'] * 60 >= time()),
363 );
364
365 if ($user_info['id'] == $row['id_first_member'])
366 $board_ids['own'][$row['id_board']][] = $row['id_msg'];
367 $board_ids['any'][$row['id_board']][] = $row['id_msg'];
368 }
369 $smcFunc['db_free_result']($request);
370
371 // There might be - and are - different permissions between any and own.
372 $permissions = array(
373 'own' => array(
374 'post_reply_own' => 'can_reply',
375 'delete_own' => 'can_delete',
376 ),
377 'any' => array(
378 'post_reply_any' => 'can_reply',
379 'mark_any_notify' => 'can_mark_notify',
380 'delete_any' => 'can_delete',
381 )
382 );
383
384 // Now go through all the permissions, looking for boards they can do it on.
385 foreach ($permissions as $type => $list)
386 {
387 foreach ($list as $permission => $allowed)
388 {
389 // They can do it on these boards...
390 $boards = boardsAllowedTo($permission);
391
392 // If 0 is the only thing in the array, they can do it everywhere!
393 if (!empty($boards) && $boards[0] == 0)
394 $boards = array_keys($board_ids[$type]);
395
396 // Go through the boards, and look for posts they can do this on.
397 foreach ($boards as $board_id)
398 {
399 // Hmm, they have permission, but there are no topics from that board on this page.
400 if (!isset($board_ids[$type][$board_id]))
401 continue;
402
403 // Okay, looks like they can do it for these posts.
404 foreach ($board_ids[$type][$board_id] as $counter)
405 if ($type == 'any' || $context['posts'][$counter]['poster']['id'] == $user_info['id'])
406 $context['posts'][$counter][$allowed] = true;
407 }
408 }
409 }
410
411 $quote_enabled = empty($modSettings['disabledBBC']) || !in_array('quote', explode(',', $modSettings['disabledBBC']));
412 foreach ($context['posts'] as $counter => $dummy)
413 {
414 // Some posts - the first posts - can't just be deleted.
415 $context['posts'][$counter]['can_delete'] &= $context['posts'][$counter]['delete_possible'];
416
417 // And some cannot be quoted...
418 $context['posts'][$counter]['can_quote'] = $context['posts'][$counter]['can_reply'] && $quote_enabled;
419 }
420 }
421
422 // Find unread topics and replies.
423 function UnreadTopics()
424 {
425 global $board, $txt, $scripturl, $sourcedir;
426 global $user_info, $context, $settings, $modSettings, $smcFunc, $options;
427
428 // Guests can't have unread things, we don't know anything about them.
429 is_not_guest();
430
431 // Prefetching + lots of MySQL work = bad mojo.
432 if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch')
433 {
434 ob_end_clean();
435 header('HTTP/1.1 403 Forbidden');
436 die;
437 }
438
439 $context['showing_all_topics'] = isset($_GET['all']);
440 $context['start'] = (int) $_REQUEST['start'];
441 $context['topics_per_page'] = empty($modSettings['disableCustomPerPage']) && !empty($options['topics_per_page']) && !WIRELESS ? $options['topics_per_page'] : $modSettings['defaultMaxTopics'];
442 if ($_REQUEST['action'] == 'unread')
443 $context['page_title'] = $context['showing_all_topics'] ? $txt['unread_topics_all'] : $txt['unread_topics_visit'];
444 else
445 $context['page_title'] = $txt['unread_replies'];
446
447 if ($context['showing_all_topics'] && !empty($context['load_average']) && !empty($modSettings['loadavg_allunread']) && $context['load_average'] >= $modSettings['loadavg_allunread'])
448 fatal_lang_error('loadavg_allunread_disabled', false);
449 elseif ($_REQUEST['action'] != 'unread' && !empty($context['load_average']) && !empty($modSettings['loadavg_unreadreplies']) && $context['load_average'] >= $modSettings['loadavg_unreadreplies'])
450 fatal_lang_error('loadavg_unreadreplies_disabled', false);
451 elseif (!$context['showing_all_topics'] && $_REQUEST['action'] == 'unread' && !empty($context['load_average']) && !empty($modSettings['loadavg_unread']) && $context['load_average'] >= $modSettings['loadavg_unread'])
452 fatal_lang_error('loadavg_unread_disabled', false);
453
454 // Parameters for the main query.
455 $query_parameters = array();
456
457 // Are we specifying any specific board?
458 if (isset($_REQUEST['children']) && (!empty($board) || !empty($_REQUEST['boards'])))
459 {
460 $boards = array();
461
462 if (!empty($_REQUEST['boards']))
463 {
464 $_REQUEST['boards'] = explode(',', $_REQUEST['boards']);
465 foreach ($_REQUEST['boards'] as $b)
466 $boards[] = (int) $b;
467 }
468
469 if (!empty($board))
470 $boards[] = (int) $board;
471
472 // The easiest thing is to just get all the boards they can see, but since we've specified the top of tree we ignore some of them
473 $request = $smcFunc['db_query']('', '
474 SELECT b.id_board, b.id_parent
475 FROM {db_prefix}boards AS b
476 WHERE {query_wanna_see_board}
477 AND b.child_level > {int:no_child}
478 AND b.id_board NOT IN ({array_int:boards})
479 ORDER BY child_level ASC
480 ',
481 array(
482 'no_child' => 0,
483 'boards' => $boards,
484 )
485 );
486
487 while ($row = $smcFunc['db_fetch_assoc']($request))
488 if (in_array($row['id_parent'], $boards))
489 $boards[] = $row['id_board'];
490
491 $smcFunc['db_free_result']($request);
492
493 if (empty($boards))
494 fatal_lang_error('error_no_boards_selected');
495
496 $query_this_board = 'id_board IN ({array_int:boards})';
497 $query_parameters['boards'] = $boards;
498 $context['querystring_board_limits'] = ';boards=' . implode(',', $boards) . ';start=%d';
499 }
500 elseif (!empty($board))
501 {
502 $query_this_board = 'id_board = {int:board}';
503 $query_parameters['board'] = $board;
504 $context['querystring_board_limits'] = ';board=' . $board . '.%1$d';
505 }
506 elseif (!empty($_REQUEST['boards']))
507 {
508 $_REQUEST['boards'] = explode(',', $_REQUEST['boards']);
509 foreach ($_REQUEST['boards'] as $i => $b)
510 $_REQUEST['boards'][$i] = (int) $b;
511
512 $request = $smcFunc['db_query']('', '
513 SELECT b.id_board
514 FROM {db_prefix}boards AS b
515 WHERE {query_see_board}
516 AND b.id_board IN ({array_int:board_list})',
517 array(
518 'board_list' => $_REQUEST['boards'],
519 )
520 );
521 $boards = array();
522 while ($row = $smcFunc['db_fetch_assoc']($request))
523 $boards[] = $row['id_board'];
524 $smcFunc['db_free_result']($request);
525
526 if (empty($boards))
527 fatal_lang_error('error_no_boards_selected');
528
529 $query_this_board = 'id_board IN ({array_int:boards})';
530 $query_parameters['boards'] = $boards;
531 $context['querystring_board_limits'] = ';boards=' . implode(',', $boards) . ';start=%1$d';
532 }
533 elseif (!empty($_REQUEST['c']))
534 {
535 $_REQUEST['c'] = explode(',', $_REQUEST['c']);
536 foreach ($_REQUEST['c'] as $i => $c)
537 $_REQUEST['c'][$i] = (int) $c;
538
539 $see_board = isset($_REQUEST['action']) && $_REQUEST['action'] == 'unreadreplies' ? 'query_see_board' : 'query_wanna_see_board';
540 $request = $smcFunc['db_query']('', '
541 SELECT b.id_board
542 FROM {db_prefix}boards AS b
543 WHERE ' . $user_info[$see_board] . '
544 AND b.id_cat IN ({array_int:id_cat})',
545 array(
546 'id_cat' => $_REQUEST['c'],
547 )
548 );
549 $boards = array();
550 while ($row = $smcFunc['db_fetch_assoc']($request))
551 $boards[] = $row['id_board'];
552 $smcFunc['db_free_result']($request);
553
554 if (empty($boards))
555 fatal_lang_error('error_no_boards_selected');
556
557 $query_this_board = 'id_board IN ({array_int:boards})';
558 $query_parameters['boards'] = $boards;
559 $context['querystring_board_limits'] = ';c=' . implode(',', $_REQUEST['c']) . ';start=%1$d';
560 }
561 else
562 {
563 $see_board = isset($_REQUEST['action']) && $_REQUEST['action'] == 'unreadreplies' ? 'query_see_board' : 'query_wanna_see_board';
564 // Don't bother to show deleted posts!
565 $request = $smcFunc['db_query']('', '
566 SELECT b.id_board
567 FROM {db_prefix}boards AS b
568 WHERE ' . $user_info[$see_board] . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? '
569 AND b.id_board != {int:recycle_board}' : ''),
570 array(
571 'recycle_board' => (int) $modSettings['recycle_board'],
572 )
573 );
574 $boards = array();
575 while ($row = $smcFunc['db_fetch_assoc']($request))
576 $boards[] = $row['id_board'];
577 $smcFunc['db_free_result']($request);
578
579 if (empty($boards))
580 fatal_lang_error('error_no_boards_selected');
581
582 $query_this_board = 'id_board IN ({array_int:boards})';
583 $query_parameters['boards'] = $boards;
584 $context['querystring_board_limits'] = ';start=%1$d';
585 $context['no_board_limits'] = true;
586 }
587
588 $sort_methods = array(
589 'subject' => 'ms.subject',
590 'starter' => 'IFNULL(mems.real_name, ms.poster_name)',
591 'replies' => 't.num_replies',
592 'views' => 't.num_views',
593 'first_post' => 't.id_topic',
594 'last_post' => 't.id_last_msg'
595 );
596
597 // The default is the most logical: newest first.
598 if (!isset($_REQUEST['sort']) || !isset($sort_methods[$_REQUEST['sort']]))
599 {
600 $context['sort_by'] = 'last_post';
601 $_REQUEST['sort'] = 't.id_last_msg';
602 $ascending = isset($_REQUEST['asc']);
603
604 $context['querystring_sort_limits'] = $ascending ? ';asc' : '';
605 }
606 // But, for other methods the default sort is ascending.
607 else
608 {
609 $context['sort_by'] = $_REQUEST['sort'];
610 $_REQUEST['sort'] = $sort_methods[$_REQUEST['sort']];
611 $ascending = !isset($_REQUEST['desc']);
612
613 $context['querystring_sort_limits'] = ';sort=' . $context['sort_by'] . ($ascending ? '' : ';desc');
614 }
615 $context['sort_direction'] = $ascending ? 'up' : 'down';
616
617 if (!empty($_REQUEST['c']) && is_array($_REQUEST['c']) && count($_REQUEST['c']) == 1)
618 {
619 $request = $smcFunc['db_query']('', '
620 SELECT name
621 FROM {db_prefix}categories
622 WHERE id_cat = {int:id_cat}
623 LIMIT 1',
624 array(
625 'id_cat' => (int) $_REQUEST['c'][0],
626 )
627 );
628 list ($name) = $smcFunc['db_fetch_row']($request);
629 $smcFunc['db_free_result']($request);
630
631 $context['linktree'][] = array(
632 'url' => $scripturl . '#c' . (int) $_REQUEST['c'][0],
633 'name' => $name
634 );
635 }
636
637 $context['linktree'][] = array(
638 'url' => $scripturl . '?action=' . $_REQUEST['action'] . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'],
639 'name' => $_REQUEST['action'] == 'unread' ? $txt['unread_topics_visit'] : $txt['unread_replies']
640 );
641
642 if ($context['showing_all_topics'])
643 $context['linktree'][] = array(
644 'url' => $scripturl . '?action=' . $_REQUEST['action'] . ';all' . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'],
645 'name' => $txt['unread_topics_all']
646 );
647 else
648 $txt['unread_topics_visit_none'] = strtr($txt['unread_topics_visit_none'], array('?action=unread;all' => '?action=unread;all' . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits']));
649
650 if (WIRELESS)
651 $context['sub_template'] = WIRELESS_PROTOCOL . '_recent';
652 else
653 {
654 loadTemplate('Recent');
655 $context['sub_template'] = $_REQUEST['action'] == 'unread' ? 'unread' : 'replies';
656 }
657
658 // Setup the default topic icons... for checking they exist and the like ;)
659 $stable_icons = array('xx', 'thumbup', 'thumbdown', 'exclamation', 'question', 'lamp', 'smiley', 'angry', 'cheesy', 'grin', 'sad', 'wink', 'moved', 'recycled', 'wireless', 'clip');
660 $context['icon_sources'] = array();
661 foreach ($stable_icons as $icon)
662 $context['icon_sources'][$icon] = 'images_url';
663
664 $is_topics = $_REQUEST['action'] == 'unread';
665
666 // This part is the same for each query.
667 $select_clause = '
668 ms.subject AS first_subject, ms.poster_time AS first_poster_time, ms.id_topic, t.id_board, b.name AS bname,
669 t.num_replies, t.num_views, ms.id_member AS id_first_member, ml.id_member AS id_last_member,
670 ml.poster_time AS last_poster_time, IFNULL(mems.real_name, ms.poster_name) AS first_poster_name,
671 IFNULL(meml.real_name, ml.poster_name) AS last_poster_name, ml.subject AS last_subject,
672 ml.icon AS last_icon, ms.icon AS first_icon, t.id_poll, t.is_sticky, t.locked, ml.modified_time AS last_modified_time,
673 IFNULL(lt.id_msg, IFNULL(lmr.id_msg, -1)) + 1 AS new_from, SUBSTRING(ml.body, 1, 385) AS last_body,
674 SUBSTRING(ms.body, 1, 385) AS first_body, ml.smileys_enabled AS last_smileys, ms.smileys_enabled AS first_smileys, t.id_first_msg, t.id_last_msg';
675
676 if ($context['showing_all_topics'])
677 {
678 if (!empty($board))
679 {
680 $request = $smcFunc['db_query']('', '
681 SELECT MIN(id_msg)
682 FROM {db_prefix}log_mark_read
683 WHERE id_member = {int:current_member}
684 AND id_board = {int:current_board}',
685 array(
686 'current_board' => $board,
687 'current_member' => $user_info['id'],
688 )
689 );
690 list ($earliest_msg) = $smcFunc['db_fetch_row']($request);
691 $smcFunc['db_free_result']($request);
692 }
693 else
694 {
695 $request = $smcFunc['db_query']('', '
696 SELECT MIN(lmr.id_msg)
697 FROM {db_prefix}boards AS b
698 LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = b.id_board AND lmr.id_member = {int:current_member})
699 WHERE {query_see_board}',
700 array(
701 'current_member' => $user_info['id'],
702 )
703 );
704 list ($earliest_msg) = $smcFunc['db_fetch_row']($request);
705 $smcFunc['db_free_result']($request);
706 }
707
708 // This is needed in case of topics marked unread.
709 if (empty($earliest_msg))
710 $earliest_msg = 0;
711 else
712 {
713 // Using caching, when possible, to ignore the below slow query.
714 if (isset($_SESSION['cached_log_time']) && $_SESSION['cached_log_time'][0] + 45 > time())
715 $earliest_msg2 = $_SESSION['cached_log_time'][1];
716 else
717 {
718 // This query is pretty slow, but it's needed to ensure nothing crucial is ignored.
719 $request = $smcFunc['db_query']('', '
720 SELECT MIN(id_msg)
721 FROM {db_prefix}log_topics
722 WHERE id_member = {int:current_member}',
723 array(
724 'current_member' => $user_info['id'],
725 )
726 );
727 list ($earliest_msg2) = $smcFunc['db_fetch_row']($request);
728 $smcFunc['db_free_result']($request);
729
730 // In theory this could be zero, if the first ever post is unread, so fudge it ;)
731 if ($earliest_msg2 == 0)
732 $earliest_msg2 = -1;
733
734 $_SESSION['cached_log_time'] = array(time(), $earliest_msg2);
735 }
736
737 $earliest_msg = min($earliest_msg2, $earliest_msg);
738 }
739 }
740
741 // !!! Add modified_time in for log_time check?
742
743 if ($modSettings['totalMessages'] > 100000 && $context['showing_all_topics'])
744 {
745 $smcFunc['db_query']('', '
746 DROP TABLE IF EXISTS {db_prefix}log_topics_unread',
747 array(
748 )
749 );
750
751 // Let's copy things out of the log_topics table, to reduce searching.
752 $have_temp_table = $smcFunc['db_query']('', '
753 CREATE TEMPORARY TABLE {db_prefix}log_topics_unread (
754 PRIMARY KEY (id_topic)
755 )
756 SELECT lt.id_topic, lt.id_msg
757 FROM {db_prefix}topics AS t
758 INNER JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic)
759 WHERE lt.id_member = {int:current_member}
760 AND t.' . $query_this_board . (empty($earliest_msg) ? '' : '
761 AND t.id_last_msg > {int:earliest_msg}') . ($modSettings['postmod_active'] ? '
762 AND t.approved = {int:is_approved}' : ''),
763 array_merge($query_parameters, array(
764 'current_member' => $user_info['id'],
765 'earliest_msg' => !empty($earliest_msg) ? $earliest_msg : 0,
766 'is_approved' => 1,
767 'db_error_skip' => true,
768 ))
769 ) !== false;
770 }
771 else
772 $have_temp_table = false;
773
774 if ($context['showing_all_topics'] && $have_temp_table)
775 {
776 $request = $smcFunc['db_query']('', '
777 SELECT COUNT(*), MIN(t.id_last_msg)
778 FROM {db_prefix}topics AS t
779 LEFT JOIN {db_prefix}log_topics_unread AS lt ON (lt.id_topic = t.id_topic)
780 LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
781 WHERE t.' . $query_this_board . (!empty($earliest_msg) ? '
782 AND t.id_last_msg > {int:earliest_msg}' : '') . '
783 AND IFNULL(lt.id_msg, IFNULL(lmr.id_msg, 0)) < t.id_last_msg' . ($modSettings['postmod_active'] ? '
784 AND t.approved = {int:is_approved}' : ''),
785 array_merge($query_parameters, array(
786 'current_member' => $user_info['id'],
787 'earliest_msg' => !empty($earliest_msg) ? $earliest_msg : 0,
788 'is_approved' => 1,
789 ))
790 );
791 list ($num_topics, $min_message) = $smcFunc['db_fetch_row']($request);
792 $smcFunc['db_free_result']($request);
793
794 // Make sure the starting place makes sense and construct the page index.
795 $context['page_index'] = constructPageIndex($scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . $context['querystring_board_limits'] . $context['querystring_sort_limits'], $_REQUEST['start'], $num_topics, $context['topics_per_page'], true);
796 $context['current_page'] = (int) $_REQUEST['start'] / $context['topics_per_page'];
797
798 $context['links'] = array(
799 'first' => $_REQUEST['start'] >= $context['topics_per_page'] ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'] : '',
800 'prev' => $_REQUEST['start'] >= $context['topics_per_page'] ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], $_REQUEST['start'] - $context['topics_per_page']) . $context['querystring_sort_limits'] : '',
801 'next' => $_REQUEST['start'] + $context['topics_per_page'] < $num_topics ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], $_REQUEST['start'] + $context['topics_per_page']) . $context['querystring_sort_limits'] : '',
802 'last' => $_REQUEST['start'] + $context['topics_per_page'] < $num_topics ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], floor(($num_topics - 1) / $context['topics_per_page']) * $context['topics_per_page']) . $context['querystring_sort_limits'] : '',
803 'up' => $scripturl,
804 );
805 $context['page_info'] = array(
806 'current_page' => $_REQUEST['start'] / $context['topics_per_page'] + 1,
807 'num_pages' => floor(($num_topics - 1) / $context['topics_per_page']) + 1
808 );
809
810 if ($num_topics == 0)
811 {
812 // Mark the boards as read if there are no unread topics!
813 require_once($sourcedir . '/Subs-Boards.php');
814 markBoardsRead(empty($boards) ? $board : $boards);
815
816 $context['topics'] = array();
817 if ($context['querystring_board_limits'] == ';start=%1$d')
818 $context['querystring_board_limits'] = '';
819 else
820 $context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $_REQUEST['start']);
821 return;
822 }
823 else
824 $min_message = (int) $min_message;
825
826 $request = $smcFunc['db_query']('substring', '
827 SELECT ' . $select_clause . '
828 FROM {db_prefix}messages AS ms
829 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = ms.id_topic AND t.id_first_msg = ms.id_msg)
830 INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)
831 LEFT JOIN {db_prefix}boards AS b ON (b.id_board = ms.id_board)
832 LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)
833 LEFT JOIN {db_prefix}members AS meml ON (meml.id_member = ml.id_member)
834 LEFT JOIN {db_prefix}log_topics_unread AS lt ON (lt.id_topic = t.id_topic)
835 LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
836 WHERE b.' . $query_this_board . '
837 AND t.id_last_msg >= {int:min_message}
838 AND IFNULL(lt.id_msg, IFNULL(lmr.id_msg, 0)) < t.id_last_msg' . ($modSettings['postmod_active'] ? '
839 AND ms.approved = {int:is_approved}' : '') . '
840 ORDER BY {raw:sort}
841 LIMIT {int:offset}, {int:limit}',
842 array_merge($query_parameters, array(
843 'current_member' => $user_info['id'],
844 'min_message' => $min_message,
845 'is_approved' => 1,
846 'sort' => $_REQUEST['sort'] . ($ascending ? '' : ' DESC'),
847 'offset' => $_REQUEST['start'],
848 'limit' => $context['topics_per_page'],
849 ))
850 );
851 }
852 elseif ($is_topics)
853 {
854 $request = $smcFunc['db_query']('', '
855 SELECT COUNT(*), MIN(t.id_last_msg)
856 FROM {db_prefix}topics AS t' . (!empty($have_temp_table) ? '
857 LEFT JOIN {db_prefix}log_topics_unread AS lt ON (lt.id_topic = t.id_topic)' : '
858 LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})') . '
859 LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
860 WHERE t.' . $query_this_board . ($context['showing_all_topics'] && !empty($earliest_msg) ? '
861 AND t.id_last_msg > {int:earliest_msg}' : (!$context['showing_all_topics'] && empty($_SESSION['first_login']) ? '
862 AND t.id_last_msg > {int:id_msg_last_visit}' : '')) . '
863 AND IFNULL(lt.id_msg, IFNULL(lmr.id_msg, 0)) < t.id_last_msg' . ($modSettings['postmod_active'] ? '
864 AND t.approved = {int:is_approved}' : ''),
865 array_merge($query_parameters, array(
866 'current_member' => $user_info['id'],
867 'earliest_msg' => !empty($earliest_msg) ? $earliest_msg : 0,
868 'id_msg_last_visit' => $_SESSION['id_msg_last_visit'],
869 'is_approved' => 1,
870 ))
871 );
872 list ($num_topics, $min_message) = $smcFunc['db_fetch_row']($request);
873 $smcFunc['db_free_result']($request);
874
875 // Make sure the starting place makes sense and construct the page index.
876 $context['page_index'] = constructPageIndex($scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . $context['querystring_board_limits'] . $context['querystring_sort_limits'], $_REQUEST['start'], $num_topics, $context['topics_per_page'], true);
877 $context['current_page'] = (int) $_REQUEST['start'] / $context['topics_per_page'];
878
879 $context['links'] = array(
880 'first' => $_REQUEST['start'] >= $context['topics_per_page'] ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'] : '',
881 'prev' => $_REQUEST['start'] >= $context['topics_per_page'] ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], $_REQUEST['start'] - $context['topics_per_page']) . $context['querystring_sort_limits'] : '',
882 'next' => $_REQUEST['start'] + $context['topics_per_page'] < $num_topics ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], $_REQUEST['start'] + $context['topics_per_page']) . $context['querystring_sort_limits'] : '',
883 'last' => $_REQUEST['start'] + $context['topics_per_page'] < $num_topics ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], floor(($num_topics - 1) / $context['topics_per_page']) * $context['topics_per_page']) . $context['querystring_sort_limits'] : '',
884 'up' => $scripturl,
885 );
886 $context['page_info'] = array(
887 'current_page' => $_REQUEST['start'] / $context['topics_per_page'] + 1,
888 'num_pages' => floor(($num_topics - 1) / $context['topics_per_page']) + 1
889 );
890
891 if ($num_topics == 0)
892 {
893 // Is this an all topics query?
894 if ($context['showing_all_topics'])
895 {
896 // Since there are no unread topics, mark the boards as read!
897 require_once($sourcedir . '/Subs-Boards.php');
898 markBoardsRead(empty($boards) ? $board : $boards);
899 }
900
901 $context['topics'] = array();
902 if ($context['querystring_board_limits'] == ';start=%d')
903 $context['querystring_board_limits'] = '';
904 else
905 $context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $_REQUEST['start']);
906 return;
907 }
908 else
909 $min_message = (int) $min_message;
910
911 $request = $smcFunc['db_query']('substring', '
912 SELECT ' . $select_clause . '
913 FROM {db_prefix}messages AS ms
914 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = ms.id_topic AND t.id_first_msg = ms.id_msg)
915 INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)
916 LEFT JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
917 LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)
918 LEFT JOIN {db_prefix}members AS meml ON (meml.id_member = ml.id_member)' . (!empty($have_temp_table) ? '
919 LEFT JOIN {db_prefix}log_topics_unread AS lt ON (lt.id_topic = t.id_topic)' : '
920 LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})') . '
921 LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
922 WHERE t.' . $query_this_board . '
923 AND t.id_last_msg >= {int:min_message}
924 AND IFNULL(lt.id_msg, IFNULL(lmr.id_msg, 0)) < ml.id_msg' . ($modSettings['postmod_active'] ? '
925 AND ms.approved = {int:is_approved}' : '') . '
926 ORDER BY {raw:order}
927 LIMIT {int:offset}, {int:limit}',
928 array_merge($query_parameters, array(
929 'current_member' => $user_info['id'],
930 'min_message' => $min_message,
931 'is_approved' => 1,
932 'order' => $_REQUEST['sort'] . ($ascending ? '' : ' DESC'),
933 'offset' => $_REQUEST['start'],
934 'limit' => $context['topics_per_page'],
935 ))
936 );
937 }
938 else
939 {
940 if ($modSettings['totalMessages'] > 100000)
941 {
942 $smcFunc['db_query']('', '
943 DROP TABLE IF EXISTS {db_prefix}topics_posted_in',
944 array(
945 )
946 );
947
948 $smcFunc['db_query']('', '
949 DROP TABLE IF EXISTS {db_prefix}log_topics_posted_in',
950 array(
951 )
952 );
953
954 $sortKey_joins = array(
955 'ms.subject' => '
956 INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)',
957 'IFNULL(mems.real_name, ms.poster_name)' => '
958 INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)
959 LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)',
960 );
961
962 // The main benefit of this temporary table is not that it's faster; it's that it avoids locks later.
963 $have_temp_table = $smcFunc['db_query']('', '
964 CREATE TEMPORARY TABLE {db_prefix}topics_posted_in (
965 id_topic mediumint(8) unsigned NOT NULL default {string:string_zero},
966 id_board smallint(5) unsigned NOT NULL default {string:string_zero},
967 id_last_msg int(10) unsigned NOT NULL default {string:string_zero},
968 id_msg int(10) unsigned NOT NULL default {string:string_zero},
969 PRIMARY KEY (id_topic)
970 )
971 SELECT t.id_topic, t.id_board, t.id_last_msg, IFNULL(lmr.id_msg, 0) AS id_msg' . (!in_array($_REQUEST['sort'], array('t.id_last_msg', 't.id_topic')) ? ', ' . $_REQUEST['sort'] . ' AS sort_key' : '') . '
972 FROM {db_prefix}messages AS m
973 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
974 LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})' . (isset($sortKey_joins[$_REQUEST['sort']]) ? $sortKey_joins[$_REQUEST['sort']] : '') . '
975 WHERE m.id_member = {int:current_member}' . (!empty($board) ? '
976 AND t.id_board = {int:current_board}' : '') . ($modSettings['postmod_active'] ? '
977 AND t.approved = {int:is_approved}' : '') . '
978 GROUP BY m.id_topic',
979 array(
980 'current_board' => $board,
981 'current_member' => $user_info['id'],
982 'is_approved' => 1,
983 'string_zero' => '0',
984 'db_error_skip' => true,
985 )
986 ) !== false;
987
988 // If that worked, create a sample of the log_topics table too.
989 if ($have_temp_table)
990 $have_temp_table = $smcFunc['db_query']('', '
991 CREATE TEMPORARY TABLE {db_prefix}log_topics_posted_in (
992 PRIMARY KEY (id_topic)
993 )
994 SELECT lt.id_topic, lt.id_msg
995 FROM {db_prefix}log_topics AS lt
996 INNER JOIN {db_prefix}topics_posted_in AS pi ON (pi.id_topic = lt.id_topic)
997 WHERE lt.id_member = {int:current_member}',
998 array(
999 'current_member' => $user_info['id'],
1000 'db_error_skip' => true,
1001 )
1002 ) !== false;
1003 }
1004
1005 if (!empty($have_temp_table))
1006 {
1007 $request = $smcFunc['db_query']('', '
1008 SELECT COUNT(*)
1009 FROM {db_prefix}topics_posted_in AS pi
1010 LEFT JOIN {db_prefix}log_topics_posted_in AS lt ON (lt.id_topic = pi.id_topic)
1011 WHERE pi.' . $query_this_board . '
1012 AND IFNULL(lt.id_msg, pi.id_msg) < pi.id_last_msg',
1013 array_merge($query_parameters, array(
1014 ))
1015 );
1016 list ($num_topics) = $smcFunc['db_fetch_row']($request);
1017 $smcFunc['db_free_result']($request);
1018 }
1019 else
1020 {
1021 $request = $smcFunc['db_query']('unread_fetch_topic_count', '
1022 SELECT COUNT(DISTINCT t.id_topic), MIN(t.id_last_msg)
1023 FROM {db_prefix}topics AS t
1024 INNER JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic)
1025 LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})
1026 LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
1027 WHERE t.' . $query_this_board . '
1028 AND m.id_member = {int:current_member}
1029 AND IFNULL(lt.id_msg, IFNULL(lmr.id_msg, 0)) < t.id_last_msg' . ($modSettings['postmod_active'] ? '
1030 AND t.approved = {int:is_approved}' : ''),
1031 array_merge($query_parameters, array(
1032 'current_member' => $user_info['id'],
1033 'is_approved' => 1,
1034 ))
1035 );
1036 list ($num_topics, $min_message) = $smcFunc['db_fetch_row']($request);
1037 $smcFunc['db_free_result']($request);
1038 }
1039
1040 // Make sure the starting place makes sense and construct the page index.
1041 $context['page_index'] = constructPageIndex($scripturl . '?action=' . $_REQUEST['action'] . $context['querystring_board_limits'] . $context['querystring_sort_limits'], $_REQUEST['start'], $num_topics, $context['topics_per_page'], true);
1042 $context['current_page'] = (int) $_REQUEST['start'] / $context['topics_per_page'];
1043
1044 $context['links'] = array(
1045 'first' => $_REQUEST['start'] >= $context['topics_per_page'] ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'] : '',
1046 'prev' => $_REQUEST['start'] >= $context['topics_per_page'] ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], $_REQUEST['start'] - $context['topics_per_page']) . $context['querystring_sort_limits'] : '',
1047 'next' => $_REQUEST['start'] + $context['topics_per_page'] < $num_topics ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], $_REQUEST['start'] + $context['topics_per_page']) . $context['querystring_sort_limits'] : '',
1048 'last' => $_REQUEST['start'] + $context['topics_per_page'] < $num_topics ? $scripturl . '?action=' . $_REQUEST['action'] . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], floor(($num_topics - 1) / $context['topics_per_page']) * $context['topics_per_page']) . $context['querystring_sort_limits'] : '',
1049 'up' => $scripturl,
1050 );
1051 $context['page_info'] = array(
1052 'current_page' => $_REQUEST['start'] / $context['topics_per_page'] + 1,
1053 'num_pages' => floor(($num_topics - 1) / $context['topics_per_page']) + 1
1054 );
1055
1056 if ($num_topics == 0)
1057 {
1058 $context['topics'] = array();
1059 if ($context['querystring_board_limits'] == ';start=%d')
1060 $context['querystring_board_limits'] = '';
1061 else
1062 $context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $_REQUEST['start']);
1063 return;
1064 }
1065
1066 if (!empty($have_temp_table))
1067 $request = $smcFunc['db_query']('', '
1068 SELECT t.id_topic
1069 FROM {db_prefix}topics_posted_in AS t
1070 LEFT JOIN {db_prefix}log_topics_posted_in AS lt ON (lt.id_topic = t.id_topic)
1071 WHERE t.' . $query_this_board . '
1072 AND IFNULL(lt.id_msg, t.id_msg) < t.id_last_msg
1073 ORDER BY {raw:order}
1074 LIMIT {int:offset}, {int:limit}',
1075 array_merge($query_parameters, array(
1076 'order' => (in_array($_REQUEST['sort'], array('t.id_last_msg', 't.id_topic')) ? $_REQUEST['sort'] : 't.sort_key') . ($ascending ? '' : ' DESC'),
1077 'offset' => $_REQUEST['start'],
1078 'limit' => $context['topics_per_page'],
1079 ))
1080 );
1081 else
1082 $request = $smcFunc['db_query']('unread_replies', '
1083 SELECT DISTINCT t.id_topic
1084 FROM {db_prefix}topics AS t
1085 INNER JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic AND m.id_member = {int:current_member})' . (strpos($_REQUEST['sort'], 'ms.') === false ? '' : '
1086 INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)') . (strpos($_REQUEST['sort'], 'mems.') === false ? '' : '
1087 LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)') . '
1088 LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})
1089 LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
1090 WHERE t.' . $query_this_board . '
1091 AND t.id_last_msg >= {int:min_message}
1092 AND (IFNULL(lt.id_msg, IFNULL(lmr.id_msg, 0))) < t.id_last_msg
1093 AND t.approved = {int:is_approved}
1094 ORDER BY {raw:order}
1095 LIMIT {int:offset}, {int:limit}',
1096 array_merge($query_parameters, array(
1097 'current_member' => $user_info['id'],
1098 'min_message' => (int) $min_message,
1099 'is_approved' => 1,
1100 'order' => $_REQUEST['sort'] . ($ascending ? '' : ' DESC'),
1101 'offset' => $_REQUEST['start'],
1102 'limit' => $context['topics_per_page'],
1103 'sort' => $_REQUEST['sort'],
1104 ))
1105 );
1106
1107 $topics = array();
1108 while ($row = $smcFunc['db_fetch_assoc']($request))
1109 $topics[] = $row['id_topic'];
1110 $smcFunc['db_free_result']($request);
1111
1112 // Sanity... where have you gone?
1113 if (empty($topics))
1114 {
1115 $context['topics'] = array();
1116 if ($context['querystring_board_limits'] == ';start=%d')
1117 $context['querystring_board_limits'] = '';
1118 else
1119 $context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $_REQUEST['start']);
1120 return;
1121 }
1122
1123 $request = $smcFunc['db_query']('substring', '
1124 SELECT ' . $select_clause . '
1125 FROM {db_prefix}topics AS t
1126 INNER JOIN {db_prefix}messages AS ms ON (ms.id_topic = t.id_topic AND ms.id_msg = t.id_first_msg)
1127 INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)
1128 INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
1129 LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)
1130 LEFT JOIN {db_prefix}members AS meml ON (meml.id_member = ml.id_member)
1131 LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})
1132 LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
1133 WHERE t.id_topic IN ({array_int:topic_list})
1134 ORDER BY ' . $_REQUEST['sort'] . ($ascending ? '' : ' DESC') . '
1135 LIMIT ' . count($topics),
1136 array(
1137 'current_member' => $user_info['id'],
1138 'topic_list' => $topics,
1139 )
1140 );
1141 }
1142
1143 $context['topics'] = array();
1144 $topic_ids = array();
1145
1146 while ($row = $smcFunc['db_fetch_assoc']($request))
1147 {
1148 if ($row['id_poll'] > 0 && $modSettings['pollMode'] == '0')
1149 continue;
1150
1151 $topic_ids[] = $row['id_topic'];
1152
1153 if (!empty($settings['message_index_preview']))
1154 {
1155 // Limit them to 128 characters - do this FIRST because it's a lot of wasted censoring otherwise.
1156 $row['first_body'] = strip_tags(strtr(parse_bbc($row['first_body'], $row['first_smileys'], $row['id_first_msg']), array('<br />' => '&#10;')));
1157 if ($smcFunc['strlen']($row['first_body']) > 128)
1158 $row['first_body'] = $smcFunc['substr']($row['first_body'], 0, 128) . '...';
1159 $row['last_body'] = strip_tags(strtr(parse_bbc($row['last_body'], $row['last_smileys'], $row['id_last_msg']), array('<br />' => '&#10;')));
1160 if ($smcFunc['strlen']($row['last_body']) > 128)
1161 $row['last_body'] = $smcFunc['substr']($row['last_body'], 0, 128) . '...';
1162
1163 // Censor the subject and message preview.
1164 censorText($row['first_subject']);
1165 censorText($row['first_body']);
1166
1167 // Don't censor them twice!
1168 if ($row['id_first_msg'] == $row['id_last_msg'])
1169 {
1170 $row['last_subject'] = $row['first_subject'];
1171 $row['last_body'] = $row['first_body'];
1172 }
1173 else
1174 {
1175 censorText($row['last_subject']);
1176 censorText($row['last_body']);
1177 }
1178 }
1179 else
1180 {
1181 $row['first_body'] = '';
1182 $row['last_body'] = '';
1183 censorText($row['first_subject']);
1184
1185 if ($row['id_first_msg'] == $row['id_last_msg'])
1186 $row['last_subject'] = $row['first_subject'];
1187 else
1188 censorText($row['last_subject']);
1189 }
1190
1191 // Decide how many pages the topic should have.
1192 $topic_length = $row['num_replies'] + 1;
1193 $messages_per_page = empty($modSettings['disableCustomPerPage']) && !empty($options['messages_per_page']) && !WIRELESS ? $options['messages_per_page'] : $modSettings['defaultMaxMessages'];
1194 if ($topic_length > $messages_per_page)
1195 {
1196 $tmppages = array();
1197 $tmpa = 1;
1198 for ($tmpb = 0; $tmpb < $topic_length; $tmpb += $messages_per_page)
1199 {
1200 $tmppages[] = '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.' . $tmpb . ';topicseen">' . $tmpa . '</a>';
1201 $tmpa++;
1202 }
1203 // Show links to all the pages?
1204 if (count($tmppages) <= 5)
1205 $pages = '&#171; ' . implode(' ', $tmppages);
1206 // Or skip a few?
1207 else
1208 $pages = '&#171; ' . $tmppages[0] . ' ' . $tmppages[1] . ' ... ' . $tmppages[count($tmppages) - 2] . ' ' . $tmppages[count($tmppages) - 1];
1209
1210 if (!empty($modSettings['enableAllMessages']) && $topic_length < $modSettings['enableAllMessages'])
1211 $pages .= ' &nbsp;<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0;all">' . $txt['all'] . '</a>';
1212 $pages .= ' &#187;';
1213 }
1214 else
1215 $pages = '';
1216
1217 // We need to check the topic icons exist... you can never be too sure!
1218 if (empty($modSettings['messageIconChecks_disable']))
1219 {
1220 // First icon first... as you'd expect.
1221 if (!isset($context['icon_sources'][$row['first_icon']]))
1222 $context['icon_sources'][$row['first_icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['first_icon'] . '.gif') ? 'images_url' : 'default_images_url';
1223 // Last icon... last... duh.
1224 if (!isset($context['icon_sources'][$row['last_icon']]))
1225 $context['icon_sources'][$row['last_icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['last_icon'] . '.gif') ? 'images_url' : 'default_images_url';
1226 }
1227
1228 // And build the array.
1229 $context['topics'][$row['id_topic']] = array(
1230 'id' => $row['id_topic'],
1231 'first_post' => array(
1232 'id' => $row['id_first_msg'],
1233 'member' => array(
1234 'name' => $row['first_poster_name'],
1235 'id' => $row['id_first_member'],
1236 'href' => $scripturl . '?action=profile;u=' . $row['id_first_member'],
1237 'link' => !empty($row['id_first_member']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_first_member'] . '" title="' . $txt['profile_of'] . ' ' . $row['first_poster_name'] . '">' . $row['first_poster_name'] . '</a>' : $row['first_poster_name']
1238 ),
1239 'time' => timeformat($row['first_poster_time']),
1240 'timestamp' => forum_time(true, $row['first_poster_time']),
1241 'subject' => $row['first_subject'],
1242 'preview' => $row['first_body'],
1243 'icon' => $row['first_icon'],
1244 'icon_url' => $settings[$context['icon_sources'][$row['first_icon']]] . '/post/' . $row['first_icon'] . '.gif',
1245 'href' => $scripturl . '?topic=' . $row['id_topic'] . '.0;topicseen',
1246 'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0;topicseen">' . $row['first_subject'] . '</a>'
1247 ),
1248 'last_post' => array(
1249 'id' => $row['id_last_msg'],
1250 'member' => array(
1251 'name' => $row['last_poster_name'],
1252 'id' => $row['id_last_member'],
1253 'href' => $scripturl . '?action=profile;u=' . $row['id_last_member'],
1254 'link' => !empty($row['id_last_member']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_last_member'] . '">' . $row['last_poster_name'] . '</a>' : $row['last_poster_name']
1255 ),
1256 'time' => timeformat($row['last_poster_time']),
1257 'timestamp' => forum_time(true, $row['last_poster_time']),
1258 'subject' => $row['last_subject'],
1259 'preview' => $row['last_body'],
1260 'icon' => $row['last_icon'],
1261 'icon_url' => $settings[$context['icon_sources'][$row['last_icon']]] . '/post/' . $row['last_icon'] . '.gif',
1262 'href' => $scripturl . '?topic=' . $row['id_topic'] . ($row['num_replies'] == 0 ? '.0' : '.msg' . $row['id_last_msg']) . ';topicseen#msg' . $row['id_last_msg'],
1263 'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . ($row['num_replies'] == 0 ? '.0' : '.msg' . $row['id_last_msg']) . ';topicseen#msg' . $row['id_last_msg'] . '" rel="nofollow">' . $row['last_subject'] . '</a>'
1264 ),
1265 'new_from' => $row['new_from'],
1266 'new_href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . ';topicseen#new',
1267 'href' => $scripturl . '?topic=' . $row['id_topic'] . ($row['num_replies'] == 0 ? '.0' : '.msg' . $row['new_from']) . ';topicseen' . ($row['num_replies'] == 0 ? '' : 'new'),
1268 'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . ($row['num_replies'] == 0 ? '.0' : '.msg' . $row['new_from']) . ';topicseen#msg' . $row['new_from'] . '" rel="nofollow">' . $row['first_subject'] . '</a>',
1269 'is_sticky' => !empty($modSettings['enableStickyTopics']) && !empty($row['is_sticky']),
1270 'is_locked' => !empty($row['locked']),
1271 'is_poll' => $modSettings['pollMode'] == '1' && $row['id_poll'] > 0,
1272 'is_hot' => $row['num_replies'] >= $modSettings['hotTopicPosts'],
1273 'is_very_hot' => $row['num_replies'] >= $modSettings['hotTopicVeryPosts'],
1274 'is_posted_in' => false,
1275 'icon' => $row['first_icon'],
1276 'icon_url' => $settings[$context['icon_sources'][$row['first_icon']]] . '/post/' . $row['first_icon'] . '.gif',
1277 'subject' => $row['first_subject'],
1278 'pages' => $pages,
1279 'replies' => comma_format($row['num_replies']),
1280 'views' => comma_format($row['num_views']),
1281 'board' => array(
1282 'id' => $row['id_board'],
1283 'name' => $row['bname'],
1284 'href' => $scripturl . '?board=' . $row['id_board'] . '.0',
1285 'link' => '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['bname'] . '</a>'
1286 )
1287 );
1288
1289 determineTopicClass($context['topics'][$row['id_topic']]);
1290 }
1291 $smcFunc['db_free_result']($request);
1292
1293 if ($is_topics && !empty($modSettings['enableParticipation']) && !empty($topic_ids))
1294 {
1295 $result = $smcFunc['db_query']('', '
1296 SELECT id_topic
1297 FROM {db_prefix}messages
1298 WHERE id_topic IN ({array_int:topic_list})
1299 AND id_member = {int:current_member}
1300 GROUP BY id_topic
1301 LIMIT {int:limit}',
1302 array(
1303 'current_member' => $user_info['id'],
1304 'topic_list' => $topic_ids,
1305 'limit' => count($topic_ids),
1306 )
1307 );
1308 while ($row = $smcFunc['db_fetch_assoc']($result))
1309 {
1310 if (empty($context['topics'][$row['id_topic']]['is_posted_in']))
1311 {
1312 $context['topics'][$row['id_topic']]['is_posted_in'] = true;
1313 $context['topics'][$row['id_topic']]['class'] = 'my_' . $context['topics'][$row['id_topic']]['class'];
1314 }
1315 }
1316 $smcFunc['db_free_result']($result);
1317 }
1318
1319 $context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $_REQUEST['start']);
1320 $context['topics_to_mark'] = implode('-', $topic_ids);
1321 }
1322
1323 ?>