Failed Conditions
Branch release-2.1 (4e22cf)
by Rick
06:39
created

Sources/Recent.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Find and retrieve information about recently posted topics, messages, and the like.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2017 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 4
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
/**
20
 * Get the latest post made on the system
21
 *
22
 * - respects approved, recycled, and board permissions
23
 * - @todo is this even used anywhere?
24
 *
25
 * @return array An array of information about the last post that you can see
26
 */
27
function getLastPost()
28
{
29
	global $scripturl, $modSettings, $smcFunc;
30
31
	// Find it by the board - better to order by board than sort the entire messages table.
32
	$request = $smcFunc['db_query']('substring', '
33
		SELECT ml.poster_time, ml.subject, ml.id_topic, ml.poster_name, SUBSTRING(ml.body, 1, 385) AS body,
34
			ml.smileys_enabled
35
		FROM {db_prefix}boards AS b
36
			INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = b.id_last_msg)
37
		WHERE {query_wanna_see_board}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? '
38
			AND b.id_board != {int:recycle_board}' : '') . '
39
			AND ml.approved = {int:is_approved}
40
		ORDER BY b.id_msg_updated DESC
41
		LIMIT 1',
42
		array(
43
			'recycle_board' => $modSettings['recycle_board'],
44
			'is_approved' => 1,
45
		)
46
	);
47
	if ($smcFunc['db_num_rows']($request) == 0)
48
		return array();
49
	$row = $smcFunc['db_fetch_assoc']($request);
50
	$smcFunc['db_free_result']($request);
51
52
	// Censor the subject and post...
53
	censorText($row['subject']);
54
	censorText($row['body']);
55
56
	$row['body'] = strip_tags(strtr(parse_bbc($row['body'], $row['smileys_enabled']), array('<br>' => '&#10;')));
57 View Code Duplication
	if ($smcFunc['strlen']($row['body']) > 128)
58
		$row['body'] = $smcFunc['substr']($row['body'], 0, 128) . '...';
59
60
	// Send the data.
61
	return array(
62
		'topic' => $row['id_topic'],
63
		'subject' => $row['subject'],
64
		'short_subject' => shorten_subject($row['subject'], 24),
65
		'preview' => $row['body'],
66
		'time' => timeformat($row['poster_time']),
67
		'timestamp' => forum_time(true, $row['poster_time']),
68
		'href' => $scripturl . '?topic=' . $row['id_topic'] . '.new;topicseen#new',
69
		'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.new;topicseen#new">' . $row['subject'] . '</a>'
70
	);
71
}
72
73
/**
74
 * Find the ten most recent posts.
75
 */
76
function RecentPosts()
77
{
78
	global $txt, $scripturl, $user_info, $context, $modSettings, $board, $smcFunc;
79
80
	loadTemplate('Recent');
81
	$context['page_title'] = $txt['recent_posts'];
82
	$context['sub_template'] = 'recent';
83
84
	$context['is_redirect'] = false;
85
86 View Code Duplication
	if (isset($_REQUEST['start']) && $_REQUEST['start'] > 95)
87
		$_REQUEST['start'] = 95;
88
89
	$query_parameters = array();
90
	if (!empty($_REQUEST['c']) && empty($board))
91
	{
92
		$_REQUEST['c'] = explode(',', $_REQUEST['c']);
93
		foreach ($_REQUEST['c'] as $i => $c)
94
			$_REQUEST['c'][$i] = (int) $c;
95
96
		if (count($_REQUEST['c']) == 1)
97
		{
98
			$request = $smcFunc['db_query']('', '
99
				SELECT name
100
				FROM {db_prefix}categories
101
				WHERE id_cat = {int:id_cat}
102
				LIMIT 1',
103
				array(
104
					'id_cat' => $_REQUEST['c'][0],
105
				)
106
			);
107
			list ($name) = $smcFunc['db_fetch_row']($request);
108
			$smcFunc['db_free_result']($request);
109
110
			if (empty($name))
111
				fatal_lang_error('no_access', false);
112
113
			$context['linktree'][] = array(
114
				'url' => $scripturl . '#c' . (int) $_REQUEST['c'],
115
				'name' => $name
116
			);
117
		}
118
119
		$recycling = !empty($modSettings['recycle_enable']) && !empty($modSettings['recycle_board']);
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 b.redirect = {string:empty}' . ($recycling ? '
126
				AND b.id_board != {int:recycle_board}' : '') . '
127
				AND {query_wanna_see_board}',
128
			array(
129
				'category_list' => $_REQUEST['c'],
130
				'empty' => '',
131
				'recycle_board' => !empty($modSettings['recycle_board']) ? $modSettings['recycle_board'] : 0,
132
			)
133
		);
134
		$total_cat_posts = 0;
135
		$boards = array();
136
		while ($row = $smcFunc['db_fetch_assoc']($request))
137
		{
138
			$boards[] = $row['id_board'];
139
			$total_cat_posts += $row['num_posts'];
140
		}
141
		$smcFunc['db_free_result']($request);
142
143
		if (empty($boards))
144
			fatal_lang_error('error_no_boards_selected');
145
146
		$query_this_board = 'b.id_board IN ({array_int:boards})';
147
		$query_parameters['boards'] = $boards;
148
149
		// If this category has a significant number of posts in it...
150 View Code Duplication
		if ($total_cat_posts > 100 && $total_cat_posts > $modSettings['totalMessages'] / 15)
151
		{
152
			$query_this_board .= '
153
					AND m.id_msg >= {int:max_id_msg}';
154
			$query_parameters['max_id_msg'] = max(0, $modSettings['maxMsgID'] - 400 - $_REQUEST['start'] * 7);
155
		}
156
157
		$context['page_index'] = constructPageIndex($scripturl . '?action=recent;c=' . implode(',', $_REQUEST['c']), $_REQUEST['start'], min(100, $total_cat_posts), 10, false);
158
	}
159
	elseif (!empty($_REQUEST['boards']))
160
	{
161
		$_REQUEST['boards'] = explode(',', $_REQUEST['boards']);
162
		foreach ($_REQUEST['boards'] as $i => $b)
163
			$_REQUEST['boards'][$i] = (int) $b;
164
165
		$request = $smcFunc['db_query']('', '
166
			SELECT b.id_board, b.num_posts
167
			FROM {db_prefix}boards AS b
168
			WHERE b.id_board IN ({array_int:board_list})
169
				AND b.redirect = {string:empty}
170
				AND {query_see_board}
171
			LIMIT {int:limit}',
172
			array(
173
				'board_list' => $_REQUEST['boards'],
174
				'limit' => count($_REQUEST['boards']),
175
				'empty' => '',
176
			)
177
		);
178
		$total_posts = 0;
179
		$boards = array();
180
		while ($row = $smcFunc['db_fetch_assoc']($request))
181
		{
182
			$boards[] = $row['id_board'];
183
			$total_posts += $row['num_posts'];
184
		}
185
		$smcFunc['db_free_result']($request);
186
187
		if (empty($boards))
188
			fatal_lang_error('error_no_boards_selected');
189
190
		$query_this_board = 'b.id_board IN ({array_int:boards})';
191
		$query_parameters['boards'] = $boards;
192
193
		// If these boards have a significant number of posts in them...
194 View Code Duplication
		if ($total_posts > 100 && $total_posts > $modSettings['totalMessages'] / 12)
195
		{
196
			$query_this_board .= '
197
					AND m.id_msg >= {int:max_id_msg}';
198
			$query_parameters['max_id_msg'] = max(0, $modSettings['maxMsgID'] - 500 - $_REQUEST['start'] * 9);
199
		}
200
201
		$context['page_index'] = constructPageIndex($scripturl . '?action=recent;boards=' . implode(',', $_REQUEST['boards']), $_REQUEST['start'], min(100, $total_posts), 10, false);
202
	}
203
	elseif (!empty($board))
204
	{
205
		$request = $smcFunc['db_query']('', '
206
			SELECT num_posts, redirect
207
			FROM {db_prefix}boards
208
			WHERE id_board = {int:current_board}
209
			LIMIT 1',
210
			array(
211
				'current_board' => $board,
212
			)
213
		);
214
		list ($total_posts, $redirect) = $smcFunc['db_fetch_row']($request);
215
		$smcFunc['db_free_result']($request);
216
217
		// If this is a redirection board, don't bother counting topics here...
218
		if ($redirect != '')
219
		{
220
			$total_posts = 0;
221
			$context['is_redirect'] = true;
222
		}
223
224
		$query_this_board = 'b.id_board = {int:board}';
225
		$query_parameters['board'] = $board;
226
227
		// If this board has a significant number of posts in it...
228 View Code Duplication
		if ($total_posts > 80 && $total_posts > $modSettings['totalMessages'] / 10)
229
		{
230
			$query_this_board .= '
231
					AND m.id_msg >= {int:max_id_msg}';
232
			$query_parameters['max_id_msg'] = max(0, $modSettings['maxMsgID'] - 600 - $_REQUEST['start'] * 10);
233
		}
234
235
		$context['page_index'] = constructPageIndex($scripturl . '?action=recent;board=' . $board . '.%1$d', $_REQUEST['start'], min(100, $total_posts), 10, true);
236
	}
237
	else
238
	{
239
		$query_this_board = '{query_wanna_see_board}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? '
240
					AND b.id_board != {int:recycle_board}' : ''). '
241
					AND m.id_msg >= {int:max_id_msg}';
242
		$query_parameters['max_id_msg'] = max(0, $modSettings['maxMsgID'] - 100 - $_REQUEST['start'] * 6);
243
		$query_parameters['recycle_board'] = $modSettings['recycle_board'];
244
245
		// "Borrow" some data from above...
246
		$query_these_boards = str_replace('AND m.id_msg >= {int:max_id_msg}', '', $query_this_board);
247
		$query_these_boards_params = $query_parameters;
248
		unset($query_these_boards_params['max_id_msg']);
249
250
		$get_num_posts = $smcFunc['db_query']('', '
251
			SELECT COALESCE(SUM(b.num_posts), 0)
252
			FROM {db_prefix}boards AS b
253
			WHERE ' . $query_these_boards . '
254
				AND b.redirect = {string:empty}',
255
			array_merge($query_these_boards_params, array('empty' => ''))
256
		);
257
258
		list($db_num_posts) = $smcFunc['db_fetch_row']($get_num_posts);
259
		$num_posts = min(100, $db_num_posts);
260
261
		$smcFunc['db_free_result']($get_num_posts);
262
263
		$context['page_index'] = constructPageIndex($scripturl . '?action=recent', $_REQUEST['start'], $num_posts, 10, false);
264
	}
265
266
	$context['linktree'][] = array(
267
		'url' => $scripturl . '?action=recent' . (empty($board) ? (empty($_REQUEST['c']) ? '' : ';c=' . (int) $_REQUEST['c']) : ';board=' . $board . '.0'),
268
		'name' => $context['page_title']
269
	);
270
271
	// If you selected a redirection board, don't try getting posts for it...
272
	if ($context['is_redirect'])
273
		$messages = 0;
274
275
	$key = 'recent-' . $user_info['id'] . '-' . md5($smcFunc['json_encode'](array_diff_key($query_parameters, array('max_id_msg' => 0)))) . '-' . (int) $_REQUEST['start'];
276
	if (!$context['is_redirect'] && (empty($modSettings['cache_enable']) || ($messages = cache_get_data($key, 120)) == null))
277
	{
278
		$done = false;
279
		while (!$done)
280
		{
281
			// Find the 10 most recent messages they can *view*.
282
			// @todo SLOW This query is really slow still, probably?
283
			$request = $smcFunc['db_query']('', '
284
				SELECT m.id_msg
285
				FROM {db_prefix}messages AS m
286
					INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
287
				WHERE ' . $query_this_board . '
288
					AND m.approved = {int:is_approved}
289
				ORDER BY m.id_msg DESC
290
				LIMIT {int:offset}, {int:limit}',
291
				array_merge($query_parameters, array(
292
					'is_approved' => 1,
293
					'offset' => $_REQUEST['start'],
294
					'limit' => 10,
295
				))
296
			);
297
			// If we don't have 10 results, try again with an unoptimized version covering all rows, and cache the result.
298
			if (isset($query_parameters['max_id_msg']) && $smcFunc['db_num_rows']($request) < 10)
299
			{
300
				$smcFunc['db_free_result']($request);
301
				$query_this_board = str_replace('AND m.id_msg >= {int:max_id_msg}', '', $query_this_board);
302
				$cache_results = true;
303
				unset($query_parameters['max_id_msg']);
304
			}
305
			else
306
				$done = true;
307
		}
308
		$messages = array();
309
		while ($row = $smcFunc['db_fetch_assoc']($request))
0 ignored issues
show
The variable $request does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
310
			$messages[] = $row['id_msg'];
311
		$smcFunc['db_free_result']($request);
312
		if (!empty($cache_results))
313
			cache_put_data($key, $messages, 120);
314
	}
315
316
	// Nothing here... Or at least, nothing you can see...
317
	if (empty($messages))
318
	{
319
		$context['posts'] = array();
320
		return;
321
	}
322
323
	// Get all the most recent posts.
324
	$request = $smcFunc['db_query']('', '
325
		SELECT
326
			m.id_msg, m.subject, m.smileys_enabled, m.poster_time, m.body, m.id_topic, t.id_board, b.id_cat,
327
			b.name AS bname, c.name AS cname, t.num_replies, m.id_member, m2.id_member AS id_first_member,
328
			COALESCE(mem2.real_name, m2.poster_name) AS first_poster_name, t.id_first_msg,
329
			COALESCE(mem.real_name, m.poster_name) AS poster_name, t.id_last_msg
330
		FROM {db_prefix}messages AS m
331
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
332
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
333
			INNER JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
334
			INNER JOIN {db_prefix}messages AS m2 ON (m2.id_msg = t.id_first_msg)
335
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
336
			LEFT JOIN {db_prefix}members AS mem2 ON (mem2.id_member = m2.id_member)
337
		WHERE m.id_msg IN ({array_int:message_list})
338
		ORDER BY m.id_msg DESC
339
		LIMIT {int:limit}',
340
		array(
341
			'message_list' => $messages,
342
			'limit' => count($messages),
343
		)
344
	);
345
	$counter = $_REQUEST['start'] + 1;
346
	$context['posts'] = array();
347
	$board_ids = array('own' => array(), 'any' => array());
348
	while ($row = $smcFunc['db_fetch_assoc']($request))
349
	{
350
		// Censor everything.
351
		censorText($row['body']);
352
		censorText($row['subject']);
353
354
		// BBC-atize the message.
355
		$row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']);
356
357
		// And build the array.
358
		$context['posts'][$row['id_msg']] = array(
359
			'id' => $row['id_msg'],
360
			'counter' => $counter++,
361
			'category' => array(
362
				'id' => $row['id_cat'],
363
				'name' => $row['cname'],
364
				'href' => $scripturl . '#c' . $row['id_cat'],
365
				'link' => '<a href="' . $scripturl . '#c' . $row['id_cat'] . '">' . $row['cname'] . '</a>'
366
			),
367
			'board' => array(
368
				'id' => $row['id_board'],
369
				'name' => $row['bname'],
370
				'href' => $scripturl . '?board=' . $row['id_board'] . '.0',
371
				'link' => '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['bname'] . '</a>'
372
			),
373
			'topic' => $row['id_topic'],
374
			'href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'],
375
			'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'] . '" rel="nofollow" title="' . $row['subject'] . '">' . shorten_subject($row['subject'], 30) . '</a>',
376
			'start' => $row['num_replies'],
377
			'subject' => $row['subject'],
378
			'shorten_subject' => shorten_subject($row['subject'], 30),
379
			'time' => timeformat($row['poster_time']),
380
			'timestamp' => forum_time(true, $row['poster_time']),
381
			'first_poster' => array(
382
				'id' => $row['id_first_member'],
383
				'name' => $row['first_poster_name'],
384
				'href' => empty($row['id_first_member']) ? '' : $scripturl . '?action=profile;u=' . $row['id_first_member'],
385
				'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>'
386
			),
387
			'poster' => array(
388
				'id' => $row['id_member'],
389
				'name' => $row['poster_name'],
390
				'href' => empty($row['id_member']) ? '' : $scripturl . '?action=profile;u=' . $row['id_member'],
391
				'link' => empty($row['id_member']) ? $row['poster_name'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['poster_name'] . '</a>'
392
			),
393
			'message' => $row['body'],
394
			'can_reply' => false,
395
			'can_delete' => false,
396
			'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()),
397
			'css_class' => 'windowbg',
398
		);
399
400
		if ($user_info['id'] == $row['id_first_member'])
401
			$board_ids['own'][$row['id_board']][] = $row['id_msg'];
402
		$board_ids['any'][$row['id_board']][] = $row['id_msg'];
403
	}
404
	$smcFunc['db_free_result']($request);
405
406
	// There might be - and are - different permissions between any and own.
407
	$permissions = array(
408
		'own' => array(
409
			'post_reply_own' => 'can_reply',
410
			'delete_own' => 'can_delete',
411
		),
412
		'any' => array(
413
			'post_reply_any' => 'can_reply',
414
			'delete_any' => 'can_delete',
415
		)
416
	);
417
418
	// Now go through all the permissions, looking for boards they can do it on.
419
	foreach ($permissions as $type => $list)
420
	{
421
		foreach ($list as $permission => $allowed)
422
		{
423
			// They can do it on these boards...
424
			$boards = boardsAllowedTo($permission);
425
426
			// If 0 is the only thing in the array, they can do it everywhere!
427 View Code Duplication
			if (!empty($boards) && $boards[0] == 0)
428
				$boards = array_keys($board_ids[$type]);
429
430
			// Go through the boards, and look for posts they can do this on.
431
			foreach ($boards as $board_id)
432
			{
433
				// Hmm, they have permission, but there are no topics from that board on this page.
434
				if (!isset($board_ids[$type][$board_id]))
435
					continue;
436
437
				// Okay, looks like they can do it for these posts.
438
				foreach ($board_ids[$type][$board_id] as $counter)
439
					if ($type == 'any' || $context['posts'][$counter]['poster']['id'] == $user_info['id'])
440
						$context['posts'][$counter][$allowed] = true;
441
			}
442
		}
443
	}
444
445
	$quote_enabled = empty($modSettings['disabledBBC']) || !in_array('quote', explode(',', $modSettings['disabledBBC']));
446 View Code Duplication
	foreach ($context['posts'] as $counter => $dummy)
447
	{
448
		// Some posts - the first posts - can't just be deleted.
449
		$context['posts'][$counter]['can_delete'] &= $context['posts'][$counter]['delete_possible'];
450
451
		// And some cannot be quoted...
452
		$context['posts'][$counter]['can_quote'] = $context['posts'][$counter]['can_reply'] && $quote_enabled;
453
	}
454
455
	// Allow last minute changes.
456
	call_integration_hook('integrate_recent_RecentPosts');
457
}
458
459
/**
460
 * Find unread topics and replies.
461
 */
462
function UnreadTopics()
463
{
464
	global $board, $txt, $scripturl, $sourcedir;
465
	global $user_info, $context, $settings, $modSettings, $smcFunc, $options;
466
467
	// Guests can't have unread things, we don't know anything about them.
468
	is_not_guest();
469
470
	// Prefetching + lots of MySQL work = bad mojo.
471 View Code Duplication
	if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch')
472
	{
473
		ob_end_clean();
474
		header('HTTP/1.1 403 Forbidden');
475
		die;
476
	}
477
478
	$context['showCheckboxes'] = !empty($options['display_quick_mod']) && $options['display_quick_mod'] == 1;
479
480
	$context['showing_all_topics'] = isset($_GET['all']);
481
	$context['start'] = (int) $_REQUEST['start'];
482
	$context['topics_per_page'] = empty($modSettings['disableCustomPerPage']) && !empty($options['topics_per_page']) ? $options['topics_per_page'] : $modSettings['defaultMaxTopics'];
483
	if ($_REQUEST['action'] == 'unread')
484
		$context['page_title'] = $context['showing_all_topics'] ? $txt['unread_topics_all'] : $txt['unread_topics_visit'];
485
	else
486
		$context['page_title'] = $txt['unread_replies'];
487
488
	if ($context['showing_all_topics'] && !empty($context['load_average']) && !empty($modSettings['loadavg_allunread']) && $context['load_average'] >= $modSettings['loadavg_allunread'])
489
		fatal_lang_error('loadavg_allunread_disabled', false);
490 View Code Duplication
	elseif ($_REQUEST['action'] != 'unread' && !empty($context['load_average']) && !empty($modSettings['loadavg_unreadreplies']) && $context['load_average'] >= $modSettings['loadavg_unreadreplies'])
491
		fatal_lang_error('loadavg_unreadreplies_disabled', false);
492 View Code Duplication
	elseif (!$context['showing_all_topics'] && $_REQUEST['action'] == 'unread' && !empty($context['load_average']) && !empty($modSettings['loadavg_unread']) && $context['load_average'] >= $modSettings['loadavg_unread'])
493
		fatal_lang_error('loadavg_unread_disabled', false);
494
495
	// Parameters for the main query.
496
	$query_parameters = array();
497
498
	// Are we specifying any specific board?
499
	if (isset($_REQUEST['children']) && (!empty($board) || !empty($_REQUEST['boards'])))
500
	{
501
		$boards = array();
502
503
		if (!empty($_REQUEST['boards']))
504
		{
505
			$_REQUEST['boards'] = explode(',', $_REQUEST['boards']);
506
			foreach ($_REQUEST['boards'] as $b)
507
				$boards[] = (int) $b;
508
		}
509
510
		if (!empty($board))
511
			$boards[] = (int) $board;
512
513
		// 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
514
		$request = $smcFunc['db_query']('', '
515
			SELECT b.id_board, b.id_parent
516
			FROM {db_prefix}boards AS b
517
			WHERE {query_wanna_see_board}
518
				AND b.child_level > {int:no_child}
519
				AND b.id_board NOT IN ({array_int:boards})
520
			ORDER BY child_level ASC
521
			',
522
			array(
523
				'no_child' => 0,
524
				'boards' => $boards,
525
			)
526
		);
527
528
		while ($row = $smcFunc['db_fetch_assoc']($request))
529
			if (in_array($row['id_parent'], $boards))
530
				$boards[] = $row['id_board'];
531
532
		$smcFunc['db_free_result']($request);
533
534
		if (empty($boards))
535
			fatal_lang_error('error_no_boards_selected');
536
537
		$query_this_board = 'id_board IN ({array_int:boards})';
538
		$query_parameters['boards'] = $boards;
539
		$context['querystring_board_limits'] = ';boards=' . implode(',', $boards) . ';start=%d';
540
	}
541
	elseif (!empty($board))
542
	{
543
		$query_this_board = 'id_board = {int:board}';
544
		$query_parameters['board'] = $board;
545
		$context['querystring_board_limits'] = ';board=' . $board . '.%1$d';
546
	}
547
	elseif (!empty($_REQUEST['boards']))
548
	{
549
		$_REQUEST['boards'] = explode(',', $_REQUEST['boards']);
550
		foreach ($_REQUEST['boards'] as $i => $b)
551
			$_REQUEST['boards'][$i] = (int) $b;
552
553
		$request = $smcFunc['db_query']('', '
554
			SELECT b.id_board
555
			FROM {db_prefix}boards AS b
556
			WHERE {query_see_board}
557
				AND b.id_board IN ({array_int:board_list})',
558
			array(
559
				'board_list' => $_REQUEST['boards'],
560
			)
561
		);
562
		$boards = array();
563
		while ($row = $smcFunc['db_fetch_assoc']($request))
564
			$boards[] = $row['id_board'];
565
		$smcFunc['db_free_result']($request);
566
567
		if (empty($boards))
568
			fatal_lang_error('error_no_boards_selected');
569
570
		$query_this_board = 'id_board IN ({array_int:boards})';
571
		$query_parameters['boards'] = $boards;
572
		$context['querystring_board_limits'] = ';boards=' . implode(',', $boards) . ';start=%1$d';
573
	}
574
	elseif (!empty($_REQUEST['c']))
575
	{
576
		$_REQUEST['c'] = explode(',', $_REQUEST['c']);
577
		foreach ($_REQUEST['c'] as $i => $c)
578
			$_REQUEST['c'][$i] = (int) $c;
579
580
		$see_board = isset($_REQUEST['action']) && $_REQUEST['action'] == 'unreadreplies' ? 'query_see_board' : 'query_wanna_see_board';
581
		$request = $smcFunc['db_query']('', '
582
			SELECT b.id_board
583
			FROM {db_prefix}boards AS b
584
			WHERE ' . $user_info[$see_board] . '
585
				AND b.id_cat IN ({array_int:id_cat})',
586
			array(
587
				'id_cat' => $_REQUEST['c'],
588
			)
589
		);
590
		$boards = array();
591
		while ($row = $smcFunc['db_fetch_assoc']($request))
592
			$boards[] = $row['id_board'];
593
		$smcFunc['db_free_result']($request);
594
595
		if (empty($boards))
596
			fatal_lang_error('error_no_boards_selected');
597
598
		$query_this_board = 'id_board IN ({array_int:boards})';
599
		$query_parameters['boards'] = $boards;
600
		$context['querystring_board_limits'] = ';c=' . implode(',', $_REQUEST['c']) . ';start=%1$d';
601
	}
602
	else
603
	{
604
		$see_board = isset($_REQUEST['action']) && $_REQUEST['action'] == 'unreadreplies' ? 'query_see_board' : 'query_wanna_see_board';
605
		// Don't bother to show deleted posts!
606
		$request = $smcFunc['db_query']('', '
607
			SELECT b.id_board
608
			FROM {db_prefix}boards AS b
609
			WHERE ' . $user_info[$see_board] . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? '
610
				AND b.id_board != {int:recycle_board}' : ''),
611
			array(
612
				'recycle_board' => (int) $modSettings['recycle_board'],
613
			)
614
		);
615
		$boards = array();
616
		while ($row = $smcFunc['db_fetch_assoc']($request))
617
			$boards[] = $row['id_board'];
618
		$smcFunc['db_free_result']($request);
619
620
		if (empty($boards))
621
			fatal_lang_error('error_no_boards_available', false);
622
623
		$query_this_board = 'id_board IN ({array_int:boards})';
624
		$query_parameters['boards'] = $boards;
625
		$context['querystring_board_limits'] = ';start=%1$d';
626
		$context['no_board_limits'] = true;
627
	}
628
629
	$sort_methods = array(
630
		'subject' => 'ms.subject',
631
		'starter' => 'COALESCE(mems.real_name, ms.poster_name)',
632
		'replies' => 't.num_replies',
633
		'views' => 't.num_views',
634
		'first_post' => 't.id_topic',
635
		'last_post' => 't.id_last_msg'
636
	);
637
638
	// The default is the most logical: newest first.
639
	if (!isset($_REQUEST['sort']) || !isset($sort_methods[$_REQUEST['sort']]))
640
	{
641
		$context['sort_by'] = 'last_post';
642
		$_REQUEST['sort'] = 't.id_last_msg';
643
		$ascending = isset($_REQUEST['asc']);
644
645
		$context['querystring_sort_limits'] = $ascending ? ';asc' : '';
646
	}
647
	// But, for other methods the default sort is ascending.
648
	else
649
	{
650
		$context['sort_by'] = $_REQUEST['sort'];
651
		$_REQUEST['sort'] = $sort_methods[$_REQUEST['sort']];
652
		$ascending = !isset($_REQUEST['desc']);
653
654
		$context['querystring_sort_limits'] = ';sort=' . $context['sort_by'] . ($ascending ? '' : ';desc');
655
	}
656
	$context['sort_direction'] = $ascending ? 'up' : 'down';
657
658
	if (!empty($_REQUEST['c']) && is_array($_REQUEST['c']) && count($_REQUEST['c']) == 1)
659
	{
660
		$request = $smcFunc['db_query']('', '
661
			SELECT name
662
			FROM {db_prefix}categories
663
			WHERE id_cat = {int:id_cat}
664
			LIMIT 1',
665
			array(
666
				'id_cat' => (int) $_REQUEST['c'][0],
667
			)
668
		);
669
		list ($name) = $smcFunc['db_fetch_row']($request);
670
		$smcFunc['db_free_result']($request);
671
672
		$context['linktree'][] = array(
673
			'url' => $scripturl . '#c' . (int) $_REQUEST['c'][0],
674
			'name' => $name
675
		);
676
	}
677
678
	$context['linktree'][] = array(
679
		'url' => $scripturl . '?action=' . $_REQUEST['action'] . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'],
680
		'name' => $_REQUEST['action'] == 'unread' ? $txt['unread_topics_visit'] : $txt['unread_replies']
681
	);
682
683
	if ($context['showing_all_topics'])
684
		$context['linktree'][] = array(
685
			'url' => $scripturl . '?action=' . $_REQUEST['action'] . ';all' . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'],
686
			'name' => $txt['unread_topics_all']
687
		);
688
	else
689
		$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']));
690
691
	loadTemplate('Recent');
692
	loadTemplate('MessageIndex');
693
	$context['sub_template'] = $_REQUEST['action'] == 'unread' ? 'unread' : 'replies';
694
695
	// Setup the default topic icons... for checking they exist and the like ;)
696
	$context['icon_sources'] = array();
697
	foreach ($context['stable_icons'] as $icon)
698
		$context['icon_sources'][$icon] = 'images_url';
699
700
	$is_topics = $_REQUEST['action'] == 'unread';
701
702
	// This part is the same for each query.
703
	$select_clause = '
704
				ms.subject AS first_subject, ms.poster_time AS first_poster_time, ms.id_topic, t.id_board, b.name AS bname,
705
				t.num_replies, t.num_views, ms.id_member AS id_first_member, ml.id_member AS id_last_member,' . (!empty($settings['avatars_on_indexes']) ? ' meml.avatar, meml.email_address, mems.avatar AS first_poster_avatar, mems.email_address AS first_poster_email, COALESCE(af.id_attach, 0) AS first_poster_id_attach, af.filename AS first_poster_filename, af.attachment_type AS first_poster_attach_type, COALESCE(al.id_attach, 0) AS last_poster_id_attach, al.filename AS last_poster_filename, al.attachment_type AS last_poster_attach_type,' : '') . '
706
				ml.poster_time AS last_poster_time, COALESCE(mems.real_name, ms.poster_name) AS first_poster_name,
707
				COALESCE(meml.real_name, ml.poster_name) AS last_poster_name, ml.subject AS last_subject,
708
				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,
709
				COALESCE(lt.id_msg, lmr.id_msg, -1) + 1 AS new_from, SUBSTRING(ml.body, 1, 385) AS last_body,
710
				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';
711
712
	if ($context['showing_all_topics'])
713
	{
714
		if (!empty($board))
715
		{
716
			$request = $smcFunc['db_query']('', '
717
				SELECT MIN(id_msg)
718
				FROM {db_prefix}log_mark_read
719
				WHERE id_member = {int:current_member}
720
					AND id_board = {int:current_board}',
721
				array(
722
					'current_board' => $board,
723
					'current_member' => $user_info['id'],
724
				)
725
			);
726
			list ($earliest_msg) = $smcFunc['db_fetch_row']($request);
727
			$smcFunc['db_free_result']($request);
728
		}
729
		else
730
		{
731
			$request = $smcFunc['db_query']('', '
732
				SELECT MIN(lmr.id_msg)
733
				FROM {db_prefix}boards AS b
734
					LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = b.id_board AND lmr.id_member = {int:current_member})
735
				WHERE {query_see_board}',
736
				array(
737
					'current_member' => $user_info['id'],
738
				)
739
			);
740
			list ($earliest_msg) = $smcFunc['db_fetch_row']($request);
741
			$smcFunc['db_free_result']($request);
742
		}
743
744
		// This is needed in case of topics marked unread.
745
		if (empty($earliest_msg))
746
			$earliest_msg = 0;
747
		else
748
		{
749
			// Using caching, when possible, to ignore the below slow query.
750
			if (isset($_SESSION['cached_log_time']) && $_SESSION['cached_log_time'][0] + 45 > time())
751
				$earliest_msg2 = $_SESSION['cached_log_time'][1];
752
			else
753
			{
754
				// This query is pretty slow, but it's needed to ensure nothing crucial is ignored.
755
				$request = $smcFunc['db_query']('', '
756
					SELECT MIN(id_msg)
757
					FROM {db_prefix}log_topics
758
					WHERE id_member = {int:current_member}',
759
					array(
760
						'current_member' => $user_info['id'],
761
					)
762
				);
763
				list ($earliest_msg2) = $smcFunc['db_fetch_row']($request);
764
				$smcFunc['db_free_result']($request);
765
766
				// In theory this could be zero, if the first ever post is unread, so fudge it ;)
767
				if ($earliest_msg2 == 0)
768
					$earliest_msg2 = -1;
769
770
				$_SESSION['cached_log_time'] = array(time(), $earliest_msg2);
771
			}
772
773
			$earliest_msg = min($earliest_msg2, $earliest_msg);
774
		}
775
	}
776
777
	// @todo Add modified_time in for log_time check?
778
779
	if ($modSettings['totalMessages'] > 100000 && $context['showing_all_topics'])
780
	{
781
		$smcFunc['db_query']('', '
782
			DROP TABLE IF EXISTS {db_prefix}log_topics_unread',
783
			array(
784
			)
785
		);
786
787
		// Let's copy things out of the log_topics table, to reduce searching.
788
		$have_temp_table = $smcFunc['db_query']('', '
789
			CREATE TEMPORARY TABLE {db_prefix}log_topics_unread (
790
				PRIMARY KEY (id_topic)
791
			)
792
			SELECT lt.id_topic, lt.id_msg
793
			FROM {db_prefix}topics AS t
794
				INNER JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic)
795
			WHERE lt.id_member = {int:current_member}
796
				AND t.' . $query_this_board . (empty($earliest_msg) ? '' : '
797
				AND t.id_last_msg > {int:earliest_msg}') . ($modSettings['postmod_active'] ? '
798
				AND t.approved = {int:is_approved}' : '') . ' AND lt.unwatched != 1',
799
			array_merge($query_parameters, array(
800
				'current_member' => $user_info['id'],
801
				'earliest_msg' => !empty($earliest_msg) ? $earliest_msg : 0,
802
				'is_approved' => 1,
803
				'db_error_skip' => true,
804
			))
805
		) !== false;
806
	}
807
	else
808
		$have_temp_table = false;
809
810
	if ($context['showing_all_topics'] && $have_temp_table)
811
	{
812
		$request = $smcFunc['db_query']('', '
813
			SELECT COUNT(*), MIN(t.id_last_msg)
814
			FROM {db_prefix}topics AS t
815
				LEFT JOIN {db_prefix}log_topics_unread AS lt ON (lt.id_topic = t.id_topic)
816
				LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
817
			WHERE t.' . $query_this_board . (!empty($earliest_msg) ? '
818
				AND t.id_last_msg > {int:earliest_msg}' : '') . '
819
				AND COALESCE(lt.id_msg, lmr.id_msg, 0) < t.id_last_msg' . ($modSettings['postmod_active'] ? '
820
				AND t.approved = {int:is_approved}' : ''),
821
			array_merge($query_parameters, array(
822
				'current_member' => $user_info['id'],
823
				'earliest_msg' => !empty($earliest_msg) ? $earliest_msg : 0,
824
				'is_approved' => 1,
825
			))
826
		);
827
		list ($num_topics, $min_message) = $smcFunc['db_fetch_row']($request);
828
		$smcFunc['db_free_result']($request);
829
830
		// Make sure the starting place makes sense and construct the page index.
831
		$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);
832
		$context['current_page'] = (int) $_REQUEST['start'] / $context['topics_per_page'];
833
834
		$context['links'] = array(
835
			'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'] : '',
836
			'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'] : '',
837
			'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'] : '',
838
			'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'] : '',
839
			'up' => $scripturl,
840
		);
841
		$context['page_info'] = array(
842
			'current_page' => $_REQUEST['start'] / $context['topics_per_page'] + 1,
843
			'num_pages' => floor(($num_topics - 1) / $context['topics_per_page']) + 1
844
		);
845
846 View Code Duplication
		if ($num_topics == 0)
847
		{
848
			// Mark the boards as read if there are no unread topics!
849
			require_once($sourcedir . '/Subs-Boards.php');
850
			markBoardsRead(empty($boards) ? $board : $boards);
851
852
			$context['topics'] = array();
853
			$context['no_topic_listing'] = true;
854
			if ($context['querystring_board_limits'] == ';start=%1$d')
855
				$context['querystring_board_limits'] = '';
856
			else
857
				$context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $_REQUEST['start']);
858
			return;
859
		}
860
		else
861
			$min_message = (int) $min_message;
862
863
		$request = $smcFunc['db_query']('substring', '
864
			SELECT ' . $select_clause . '
865
			FROM {db_prefix}messages AS ms
866
				INNER JOIN {db_prefix}topics AS t ON (t.id_topic = ms.id_topic AND t.id_first_msg = ms.id_msg)
867
				INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)
868
				LEFT JOIN {db_prefix}boards AS b ON (b.id_board = ms.id_board)
869
				LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)
870
				LEFT JOIN {db_prefix}members AS meml ON (meml.id_member = ml.id_member)' . (!empty($settings['avatars_on_indexes']) ? '
871
				LEFT JOIN {db_prefix}attachments AS af ON (af.id_member = mems.id_member)
872
				LEFT JOIN {db_prefix}attachments AS al ON (al.id_member = meml.id_member)' : '') . '
873
				LEFT JOIN {db_prefix}log_topics_unread AS lt ON (lt.id_topic = t.id_topic)
874
				LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
875
			WHERE b.' . $query_this_board . '
876
				AND t.id_last_msg >= {int:min_message}
877
				AND COALESCE(lt.id_msg, lmr.id_msg, 0) < t.id_last_msg' . ($modSettings['postmod_active'] ? '
878
				AND ms.approved = {int:is_approved}' : '') . '
879
			ORDER BY {raw:sort}
880
			LIMIT {int:offset}, {int:limit}',
881
			array_merge($query_parameters, array(
882
				'current_member' => $user_info['id'],
883
				'min_message' => $min_message,
884
				'is_approved' => 1,
885
				'sort' => $_REQUEST['sort'] . ($ascending ? '' : ' DESC'),
886
				'offset' => $_REQUEST['start'],
887
				'limit' => $context['topics_per_page'],
888
			))
889
		);
890
	}
891
	elseif ($is_topics)
892
	{
893
		$request = $smcFunc['db_query']('', '
894
			SELECT COUNT(*), MIN(t.id_last_msg)
895
			FROM {db_prefix}topics AS t' . (!empty($have_temp_table) ? '
896
				LEFT JOIN {db_prefix}log_topics_unread AS lt ON (lt.id_topic = t.id_topic)' : '
897
				LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member} AND lt.unwatched != 1)') . '
898
				LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
899
			WHERE t.' . $query_this_board . ($context['showing_all_topics'] && !empty($earliest_msg) ? '
900
				AND t.id_last_msg > {int:earliest_msg}' : (!$context['showing_all_topics'] && empty($_SESSION['first_login']) ? '
901
				AND t.id_last_msg > {int:id_msg_last_visit}' : '')) . '
902
				AND COALESCE(lt.id_msg, lmr.id_msg, 0) < t.id_last_msg' . ($modSettings['postmod_active'] ? '
903
				AND t.approved = {int:is_approved}' : '') . '',
904
			array_merge($query_parameters, array(
905
				'current_member' => $user_info['id'],
906
				'earliest_msg' => !empty($earliest_msg) ? $earliest_msg : 0,
907
				'id_msg_last_visit' => $_SESSION['id_msg_last_visit'],
908
				'is_approved' => 1,
909
			))
910
		);
911
		list ($num_topics, $min_message) = $smcFunc['db_fetch_row']($request);
912
		$smcFunc['db_free_result']($request);
913
914
		// Make sure the starting place makes sense and construct the page index.
915
		$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);
916
		$context['current_page'] = (int) $_REQUEST['start'] / $context['topics_per_page'];
917
918
		$context['links'] = array(
919
			'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'] : '',
920
			'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'] : '',
921
			'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'] : '',
922
			'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'] : '',
923
			'up' => $scripturl,
924
		);
925
		$context['page_info'] = array(
926
			'current_page' => $_REQUEST['start'] / $context['topics_per_page'] + 1,
927
			'num_pages' => floor(($num_topics - 1) / $context['topics_per_page']) + 1
928
		);
929
930 View Code Duplication
		if ($num_topics == 0)
931
		{
932
			// Is this an all topics query?
933
			if ($context['showing_all_topics'])
934
			{
935
				// Since there are no unread topics, mark the boards as read!
936
				require_once($sourcedir . '/Subs-Boards.php');
937
				markBoardsRead(empty($boards) ? $board : $boards);
938
			}
939
940
			$context['topics'] = array();
941
			$context['no_topic_listing'] = true;
942
			if ($context['querystring_board_limits'] == ';start=%d')
943
				$context['querystring_board_limits'] = '';
944
			else
945
				$context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $_REQUEST['start']);
946
			return;
947
		}
948
		else
949
			$min_message = (int) $min_message;
950
951
		$request = $smcFunc['db_query']('substring', '
952
			SELECT ' . $select_clause . '
953
			FROM {db_prefix}messages AS ms
954
				INNER JOIN {db_prefix}topics AS t ON (t.id_topic = ms.id_topic AND t.id_first_msg = ms.id_msg)
955
				INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)
956
				LEFT JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
957
				LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)
958
				LEFT JOIN {db_prefix}members AS meml ON (meml.id_member = ml.id_member)' . (!empty($settings['avatars_on_indexes']) ? '
959
				LEFT JOIN {db_prefix}attachments AS af ON (af.id_member = mems.id_member)
960
				LEFT JOIN {db_prefix}attachments AS al ON (al.id_member = meml.id_member)' : '') . '' . (!empty($have_temp_table) ? '
961
				LEFT JOIN {db_prefix}log_topics_unread AS lt ON (lt.id_topic = t.id_topic)' : '
962
				LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member} AND lt.unwatched != 1)') . '
963
				LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
964
			WHERE t.' . $query_this_board . '
965
				AND t.id_last_msg >= {int:min_message}
966
				AND COALESCE(lt.id_msg, lmr.id_msg, 0) < ml.id_msg' . ($modSettings['postmod_active'] ? '
967
				AND ms.approved = {int:is_approved}' : '') . '
968
			ORDER BY {raw:order}
969
			LIMIT {int:offset}, {int:limit}',
970
			array_merge($query_parameters, array(
971
				'current_member' => $user_info['id'],
972
				'min_message' => $min_message,
973
				'is_approved' => 1,
974
				'order' => $_REQUEST['sort'] . ($ascending ? '' : ' DESC'),
975
				'offset' => $_REQUEST['start'],
976
				'limit' => $context['topics_per_page'],
977
			))
978
		);
979
	}
980
	else
981
	{
982
		if ($modSettings['totalMessages'] > 100000)
983
		{
984
			$smcFunc['db_query']('', '
985
				DROP TABLE IF EXISTS {db_prefix}topics_posted_in',
986
				array(
987
				)
988
			);
989
990
			$smcFunc['db_query']('', '
991
				DROP TABLE IF EXISTS {db_prefix}log_topics_posted_in',
992
				array(
993
				)
994
			);
995
996
			$sortKey_joins = array(
997
				'ms.subject' => '
998
					INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)',
999
				'COALESCE(mems.real_name, ms.poster_name)' => '
1000
					INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)
1001
					LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)',
1002
			);
1003
1004
			// The main benefit of this temporary table is not that it's faster; it's that it avoids locks later.
1005
			$have_temp_table = $smcFunc['db_query']('', '
1006
				CREATE TEMPORARY TABLE {db_prefix}topics_posted_in (
1007
					id_topic mediumint(8) unsigned NOT NULL default {string:string_zero},
1008
					id_board smallint(5) unsigned NOT NULL default {string:string_zero},
1009
					id_last_msg int(10) unsigned NOT NULL default {string:string_zero},
1010
					id_msg int(10) unsigned NOT NULL default {string:string_zero},
1011
					PRIMARY KEY (id_topic)
1012
				)
1013
				SELECT t.id_topic, t.id_board, t.id_last_msg, COALESCE(lmr.id_msg, 0) AS id_msg' . (!in_array($_REQUEST['sort'], array('t.id_last_msg', 't.id_topic')) ? ', ' . $_REQUEST['sort'] . ' AS sort_key' : '') . '
1014
				FROM {db_prefix}messages AS m
1015
					INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
1016
					LEFT JOIN {db_prefix}log_topics_unread AS lt ON (lt.id_topic = t.id_topic)
1017
					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']] : '') . '
1018
				WHERE m.id_member = {int:current_member}' . (!empty($board) ? '
1019
					AND t.id_board = {int:current_board}' : '') . ($modSettings['postmod_active'] ? '
1020
					AND t.approved = {int:is_approved}' : '') . '
1021
				GROUP BY m.id_topic',
1022
				array(
1023
					'current_board' => $board,
1024
					'current_member' => $user_info['id'],
1025
					'is_approved' => 1,
1026
					'string_zero' => '0',
1027
					'db_error_skip' => true,
1028
				)
1029
			) !== false;
1030
1031
			// If that worked, create a sample of the log_topics table too.
1032
			if ($have_temp_table)
1033
				$have_temp_table = $smcFunc['db_query']('', '
1034
					CREATE TEMPORARY TABLE {db_prefix}log_topics_posted_in (
1035
						PRIMARY KEY (id_topic)
1036
					)
1037
					SELECT lt.id_topic, lt.id_msg
1038
					FROM {db_prefix}log_topics AS lt
1039
						INNER JOIN {db_prefix}topics_posted_in AS pi ON (pi.id_topic = lt.id_topic)
1040
					WHERE lt.id_member = {int:current_member}',
1041
					array(
1042
						'current_member' => $user_info['id'],
1043
						'db_error_skip' => true,
1044
					)
1045
				) !== false;
1046
		}
1047
1048
		if (!empty($have_temp_table))
1049
		{
1050
			$request = $smcFunc['db_query']('', '
1051
				SELECT COUNT(*)
1052
				FROM {db_prefix}topics_posted_in AS pi
1053
					LEFT JOIN {db_prefix}log_topics_posted_in AS lt ON (lt.id_topic = pi.id_topic)
1054
				WHERE pi.' . $query_this_board . '
1055
					AND COALESCE(lt.id_msg, pi.id_msg) < pi.id_last_msg',
1056
				array_merge($query_parameters, array(
1057
				))
1058
			);
1059
			list ($num_topics) = $smcFunc['db_fetch_row']($request);
1060
			$smcFunc['db_free_result']($request);
1061
		}
1062
		else
1063
		{
1064
			$request = $smcFunc['db_query']('unread_fetch_topic_count', '
1065
				SELECT COUNT(DISTINCT t.id_topic), MIN(t.id_last_msg)
1066
				FROM {db_prefix}topics AS t
1067
					INNER JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic)
1068
					LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})
1069
					LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
1070
				WHERE t.' . $query_this_board . '
1071
					AND m.id_member = {int:current_member}
1072
					AND COALESCE(lt.id_msg, lmr.id_msg, 0) < t.id_last_msg' . ($modSettings['postmod_active'] ? '
1073
					AND t.approved = {int:is_approved}' : '') . ' AND lt.unwatched != 1',
1074
				array_merge($query_parameters, array(
1075
					'current_member' => $user_info['id'],
1076
					'is_approved' => 1,
1077
				))
1078
			);
1079
			list ($num_topics, $min_message) = $smcFunc['db_fetch_row']($request);
1080
			$smcFunc['db_free_result']($request);
1081
		}
1082
1083
		// Make sure the starting place makes sense and construct the page index.
1084
		$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);
1085
		$context['current_page'] = (int) $_REQUEST['start'] / $context['topics_per_page'];
1086
1087
		$context['links'] = array(
1088
			'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'] : '',
1089
			'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'] : '',
1090
			'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'] : '',
1091
			'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'] : '',
1092
			'up' => $scripturl,
1093
		);
1094
		$context['page_info'] = array(
1095
			'current_page' => $_REQUEST['start'] / $context['topics_per_page'] + 1,
1096
			'num_pages' => floor(($num_topics - 1) / $context['topics_per_page']) + 1
1097
		);
1098
1099 View Code Duplication
		if ($num_topics == 0)
1100
		{
1101
			$context['topics'] = array();
1102
			$context['no_topic_listing'] = true;
1103
			if ($context['querystring_board_limits'] == ';start=%d')
1104
				$context['querystring_board_limits'] = '';
1105
			else
1106
				$context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $_REQUEST['start']);
1107
			return;
1108
		}
1109
1110
		if (!empty($have_temp_table))
1111
			$request = $smcFunc['db_query']('', '
1112
				SELECT t.id_topic
1113
				FROM {db_prefix}topics_posted_in AS t
1114
					LEFT JOIN {db_prefix}log_topics_posted_in AS lt ON (lt.id_topic = t.id_topic)
1115
				WHERE t.' . $query_this_board . '
1116
					AND COALESCE(lt.id_msg, t.id_msg) < t.id_last_msg
1117
				ORDER BY {raw:order}
1118
				LIMIT {int:offset}, {int:limit}',
1119
				array_merge($query_parameters, array(
1120
					'order' => (in_array($_REQUEST['sort'], array('t.id_last_msg', 't.id_topic')) ? $_REQUEST['sort'] : 't.sort_key') . ($ascending ? '' : ' DESC'),
1121
					'offset' => $_REQUEST['start'],
1122
					'limit' => $context['topics_per_page'],
1123
				))
1124
			);
1125
		else
1126
			$request = $smcFunc['db_query']('', '
1127
				SELECT DISTINCT t.id_topic,'.$_REQUEST['sort'].'
1128
				FROM {db_prefix}topics AS t
1129
					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 ? '' : '
1130
					INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)') . (strpos($_REQUEST['sort'], 'mems.') === false ? '' : '
1131
					LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)') . '
1132
					LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})
1133
					LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
1134
				WHERE t.' . $query_this_board . '
1135
					AND t.id_last_msg >= {int:min_message}
1136
					AND (COALESCE(lt.id_msg, lmr.id_msg, 0)) < t.id_last_msg
1137
					AND t.approved = {int:is_approved} AND lt.unwatched != 1
1138
				ORDER BY {raw:order}
1139
				LIMIT {int:offset}, {int:limit}',
1140
				array_merge($query_parameters, array(
1141
					'current_member' => $user_info['id'],
1142
					'min_message' => (int) $min_message,
0 ignored issues
show
The variable $min_message does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1143
					'is_approved' => 1,
1144
					'order' => $_REQUEST['sort'] . ($ascending ? '' : ' DESC'),
1145
					'offset' => $_REQUEST['start'],
1146
					'limit' => $context['topics_per_page'],
1147
					'sort' => $_REQUEST['sort'],
1148
				))
1149
			);
1150
1151
		$topics = array();
1152
		while ($row = $smcFunc['db_fetch_assoc']($request))
1153
			$topics[] = $row['id_topic'];
1154
		$smcFunc['db_free_result']($request);
1155
1156
		// Sanity... where have you gone?
1157 View Code Duplication
		if (empty($topics))
1158
		{
1159
			$context['topics'] = array();
1160
			$context['no_topic_listing'] = true;
1161
			if ($context['querystring_board_limits'] == ';start=%d')
1162
				$context['querystring_board_limits'] = '';
1163
			else
1164
				$context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $_REQUEST['start']);
1165
			return;
1166
		}
1167
1168
		$request = $smcFunc['db_query']('substring', '
1169
			SELECT ' . $select_clause . '
1170
			FROM {db_prefix}topics AS t
1171
				INNER JOIN {db_prefix}messages AS ms ON (ms.id_topic = t.id_topic AND ms.id_msg = t.id_first_msg)
1172
				INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)
1173
				INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
1174
				LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)
1175
				LEFT JOIN {db_prefix}members AS meml ON (meml.id_member = ml.id_member)' . (!empty($settings['avatars_on_indexes']) ? '
1176
				LEFT JOIN {db_prefix}attachments AS af ON (af.id_member = mems.id_member)
1177
				LEFT JOIN {db_prefix}attachments AS al ON (al.id_member = meml.id_member)' : '') . '
1178
				LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})
1179
				LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})
1180
			WHERE t.id_topic IN ({array_int:topic_list})
1181
			ORDER BY {raw:sort}' . ($ascending ? '' : ' DESC') . '
1182
			LIMIT {int:limit}',
1183
			array(
1184
				'current_member' => $user_info['id'],
1185
				'topic_list' => $topics,
1186
				'sort' => $_REQUEST['sort'],
1187
				'limit' => count($topics),
1188
			)
1189
		);
1190
	}
1191
1192
	$context['topics'] = array();
1193
	$topic_ids = array();
1194
	$recycle_board = !empty($modSettings['recycle_enable']) && !empty($modSettings['recycle_board']) ? $modSettings['recycle_board'] : 0;
1195
1196
	while ($row = $smcFunc['db_fetch_assoc']($request))
1197
	{
1198
		if ($row['id_poll'] > 0 && $modSettings['pollMode'] == '0')
1199
			continue;
1200
1201
		$topic_ids[] = $row['id_topic'];
1202
1203
		if (!empty($modSettings['preview_characters']))
1204
		{
1205
			// Limit them to 128 characters - do this FIRST because it's a lot of wasted censoring otherwise.
1206
			$row['first_body'] = strip_tags(strtr(parse_bbc($row['first_body'], $row['first_smileys'], $row['id_first_msg']), array('<br>' => '&#10;')));
1207 View Code Duplication
			if ($smcFunc['strlen']($row['first_body']) > 128)
1208
				$row['first_body'] = $smcFunc['substr']($row['first_body'], 0, 128) . '...';
1209
			$row['last_body'] = strip_tags(strtr(parse_bbc($row['last_body'], $row['last_smileys'], $row['id_last_msg']), array('<br>' => '&#10;')));
1210 View Code Duplication
			if ($smcFunc['strlen']($row['last_body']) > 128)
1211
				$row['last_body'] = $smcFunc['substr']($row['last_body'], 0, 128) . '...';
1212
1213
			// Censor the subject and message preview.
1214
			censorText($row['first_subject']);
1215
			censorText($row['first_body']);
1216
1217
			// Don't censor them twice!
1218 View Code Duplication
			if ($row['id_first_msg'] == $row['id_last_msg'])
1219
			{
1220
				$row['last_subject'] = $row['first_subject'];
1221
				$row['last_body'] = $row['first_body'];
1222
			}
1223
			else
1224
			{
1225
				censorText($row['last_subject']);
1226
				censorText($row['last_body']);
1227
			}
1228
		}
1229 View Code Duplication
		else
1230
		{
1231
			$row['first_body'] = '';
1232
			$row['last_body'] = '';
1233
			censorText($row['first_subject']);
1234
1235
			if ($row['id_first_msg'] == $row['id_last_msg'])
1236
				$row['last_subject'] = $row['first_subject'];
1237
			else
1238
				censorText($row['last_subject']);
1239
		}
1240
1241
		// Decide how many pages the topic should have.
1242
		$topic_length = $row['num_replies'] + 1;
1243
		$messages_per_page = empty($modSettings['disableCustomPerPage']) && !empty($options['messages_per_page']) ? $options['messages_per_page'] : $modSettings['defaultMaxMessages'];
1244
		if ($topic_length > $messages_per_page)
1245
		{
1246
			$start = -1;
1247
			$pages = constructPageIndex($scripturl . '?topic=' . $row['id_topic'] . '.%1$d', $start, $topic_length, $messages_per_page, true, false);
1248
1249
			// If we can use all, show all.
1250 View Code Duplication
			if (!empty($modSettings['enableAllMessages']) && $topic_length < $modSettings['enableAllMessages'])
1251
				$pages .= ' &nbsp;<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0;all">' . $txt['all'] . '</a>';
1252
		}
1253
1254
		else
1255
			$pages = '';
1256
1257
		// We need to check the topic icons exist... you can never be too sure!
1258
		if (!empty($modSettings['messageIconChecks_enable']))
1259
		{
1260
			// First icon first... as you'd expect.
1261 View Code Duplication
			if (!isset($context['icon_sources'][$row['first_icon']]))
1262
				$context['icon_sources'][$row['first_icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['first_icon'] . '.png') ? 'images_url' : 'default_images_url';
1263
			// Last icon... last... duh.
1264 View Code Duplication
			if (!isset($context['icon_sources'][$row['last_icon']]))
1265
				$context['icon_sources'][$row['last_icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['last_icon'] . '.png') ? 'images_url' : 'default_images_url';
1266
		}
1267
1268
		// Force the recycling icon if appropriate
1269
		if ($recycle_board == $row['id_board'])
1270
		{
1271
			$row['first_icon'] = 'recycled';
1272
			$row['last_icon'] = 'recycled';
1273
		}
1274
1275
		// Reference the main color class.
1276
		$colorClass = 'windowbg';
1277
1278
		// Sticky topics should get a different color, too.
1279
		if ($row['is_sticky'])
1280
			$colorClass .= ' sticky';
1281
1282
		// Locked topics get special treatment as well.
1283
		if ($row['locked'])
1284
			$colorClass .= ' locked';
1285
1286
		// And build the array.
1287
		$context['topics'][$row['id_topic']] = array(
1288
			'id' => $row['id_topic'],
1289
			'first_post' => array(
1290
				'id' => $row['id_first_msg'],
1291
				'member' => array(
1292
					'name' => $row['first_poster_name'],
1293
					'id' => $row['id_first_member'],
1294
					'href' => $scripturl . '?action=profile;u=' . $row['id_first_member'],
1295
					'link' => !empty($row['id_first_member']) ? '<a class="preview" 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']
1296
				),
1297
				'time' => timeformat($row['first_poster_time']),
1298
				'timestamp' => forum_time(true, $row['first_poster_time']),
1299
				'subject' => $row['first_subject'],
1300
				'preview' => $row['first_body'],
1301
				'icon' => $row['first_icon'],
1302
				'icon_url' => $settings[$context['icon_sources'][$row['first_icon']]] . '/post/' . $row['first_icon'] . '.png',
1303
				'href' => $scripturl . '?topic=' . $row['id_topic'] . '.0;topicseen',
1304
				'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0;topicseen">' . $row['first_subject'] . '</a>'
1305
			),
1306
			'last_post' => array(
1307
				'id' => $row['id_last_msg'],
1308
				'member' => array(
1309
					'name' => $row['last_poster_name'],
1310
					'id' => $row['id_last_member'],
1311
					'href' => $scripturl . '?action=profile;u=' . $row['id_last_member'],
1312
					'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']
1313
				),
1314
				'time' => timeformat($row['last_poster_time']),
1315
				'timestamp' => forum_time(true, $row['last_poster_time']),
1316
				'subject' => $row['last_subject'],
1317
				'preview' => $row['last_body'],
1318
				'icon' => $row['last_icon'],
1319
				'icon_url' => $settings[$context['icon_sources'][$row['last_icon']]] . '/post/' . $row['last_icon'] . '.png',
1320
				'href' => $scripturl . '?topic=' . $row['id_topic'] . ($row['num_replies'] == 0 ? '.0' : '.msg' . $row['id_last_msg']) . ';topicseen#msg' . $row['id_last_msg'],
1321
				'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>'
1322
			),
1323
			'new_from' => $row['new_from'],
1324
			'new_href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . ';topicseen#new',
1325
			'href' => $scripturl . '?topic=' . $row['id_topic'] . ($row['num_replies'] == 0 ? '.0' : '.msg' . $row['new_from']) . ';topicseen' . ($row['num_replies'] == 0 ? '' : 'new'),
1326
			'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>',
1327
			'is_sticky' => !empty($row['is_sticky']),
1328
			'is_locked' => !empty($row['locked']),
1329
			'css_class' => $colorClass,
1330
			'is_poll' => $modSettings['pollMode'] == '1' && $row['id_poll'] > 0,
1331
			'is_posted_in' => false,
1332
			'icon' => $row['first_icon'],
1333
			'icon_url' => $settings[$context['icon_sources'][$row['first_icon']]] . '/post/' . $row['first_icon'] . '.png',
1334
			'subject' => $row['first_subject'],
1335
			'pages' => $pages,
1336
			'replies' => comma_format($row['num_replies']),
1337
			'views' => comma_format($row['num_views']),
1338
			'board' => array(
1339
				'id' => $row['id_board'],
1340
				'name' => $row['bname'],
1341
				'href' => $scripturl . '?board=' . $row['id_board'] . '.0',
1342
				'link' => '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['bname'] . '</a>'
1343
			)
1344
		);
1345
		if (!empty($settings['avatars_on_indexes']))
1346
		{
1347
			$context['topics'][$row['id_topic']]['last_post']['member']['avatar'] = set_avatar_data(array(
1348
				'avatar' => $row['avatar'],
1349
				'email' => $row['email_address'],
1350
				'filename' => $row['last_poster_filename'],
1351
			));
1352
1353
			$context['topics'][$row['id_topic']]['first_post']['member']['avatar'] = set_avatar_data(array(
1354
				'avatar' => $row['first_poster_avatar'],
1355
				'email' => $row['first_poster_email'],
1356
				'filename' => $row['first_poster_filename'],
1357
			));
1358
		}
1359
1360
		$context['topics'][$row['id_topic']]['first_post']['started_by'] = sprintf($txt['topic_started_by'], $context['topics'][$row['id_topic']]['first_post']['member']['link'], $context['topics'][$row['id_topic']]['board']['link']);
1361
	}
1362
	$smcFunc['db_free_result']($request);
1363
1364
	if ($is_topics && !empty($modSettings['enableParticipation']) && !empty($topic_ids))
1365
	{
1366
		$result = $smcFunc['db_query']('', '
1367
			SELECT id_topic
1368
			FROM {db_prefix}messages
1369
			WHERE id_topic IN ({array_int:topic_list})
1370
				AND id_member = {int:current_member}
1371
			GROUP BY id_topic
1372
			LIMIT {int:limit}',
1373
			array(
1374
				'current_member' => $user_info['id'],
1375
				'topic_list' => $topic_ids,
1376
				'limit' => count($topic_ids),
1377
			)
1378
		);
1379
		while ($row = $smcFunc['db_fetch_assoc']($result))
1380
		{
1381
			if (empty($context['topics'][$row['id_topic']]['is_posted_in']))
1382
				$context['topics'][$row['id_topic']]['is_posted_in'] = true;
1383
		}
1384
		$smcFunc['db_free_result']($result);
1385
	}
1386
1387
	$context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $_REQUEST['start']);
1388
	$context['topics_to_mark'] = implode('-', $topic_ids);
1389
1390
	// Build the recent button array.
1391
	if ($is_topics)
1392
	{
1393
		$context['recent_buttons'] = array(
1394
			'markread' => array('text' => !empty($context['no_board_limits']) ? 'mark_as_read' : 'mark_read_short', 'image' => 'markread.png', 'custom' => 'data-confirm="'.  $txt['are_sure_mark_read'] .'"', 'class' => 'you_sure', 'url' => $scripturl . '?action=markasread;sa=' . (!empty($context['no_board_limits']) ? 'all' : 'board' . $context['querystring_board_limits']) . ';' . $context['session_var'] . '=' . $context['session_id']),
1395
		);
1396
1397 View Code Duplication
		if ($context['showCheckboxes'])
1398
			$context['recent_buttons']['markselectread'] = array(
1399
				'text' => 'quick_mod_markread',
1400
				'image' => 'markselectedread.png',
1401
				'url' => 'javascript:document.quickModForm.submit();',
1402
			);
1403
1404
		if (!empty($context['topics']) && !$context['showing_all_topics'])
1405
			$context['recent_buttons']['readall'] = array('text' => 'unread_topics_all', 'image' => 'markreadall.png', 'url' => $scripturl . '?action=unread;all' . $context['querystring_board_limits'], 'active' => true);
1406
	}
1407
	elseif (!$is_topics && isset($context['topics_to_mark']))
1408
	{
1409
		$context['recent_buttons'] = array(
1410
			'markread' => array('text' => 'mark_as_read', 'image' => 'markread.png', 'custom' => 'data-confirm="'. $txt['are_sure_mark_read']  .'"', 'class' => 'you_sure', 'url' => $scripturl . '?action=markasread;sa=unreadreplies;topics=' . $context['topics_to_mark'] . ';' . $context['session_var'] . '=' . $context['session_id']),
1411
		);
1412
1413 View Code Duplication
		if ($context['showCheckboxes'])
1414
			$context['recent_buttons']['markselectread'] = array(
1415
				'text' => 'quick_mod_markread',
1416
				'image' => 'markselectedread.png',
1417
				'url' => 'javascript:document.quickModForm.submit();',
1418
			);
1419
	}
1420
1421
	// Allow mods to add additional buttons here
1422
	call_integration_hook('integrate_recent_buttons');
1423
1424
	$context['no_topic_listing'] = empty($context['topics']);
1425
1426
	// Allow helpdesks and bug trackers and what not to add their own unread data (just add a template_layer to show custom stuff in the template!)
1427
 	call_integration_hook('integrate_unread_list');
1428
}
1429
1430
?>