BoardsList::_buildLastPost()   F
last analyzed

Complexity

Conditions 12
Paths 512

Size

Total Lines 43
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 19.5936

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 29
c 1
b 0
f 0
nc 512
nop 1
dl 0
loc 43
ccs 10
cts 16
cp 0.625
crap 19.5936
rs 3.4777

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file contains a class to collect the data needed to
5
 * show a list of boards for the board index and the message index.
6
 *
7
 * @package   ElkArte Forum
8
 * @copyright ElkArte Forum contributors
9
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
10
 *
11
 * This file contains code covered by:
12
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
13
 *
14
 * @version 2.0 Beta 1
15
 *
16
 */
17
18
namespace ElkArte;
19
20
use BBC\ParserWrapper;
21
use ElkArte\Cache\Cache;
22
use ElkArte\Database\QueryInterface;
23
use ElkArte\Helper\Util;
24
25
/**
26
 * This class fetches all the stuff needed to build a list of boards
27
 */
28
class BoardsList
29
{
30
	/** @var array All the options */
31
	private $_options;
32
33
	/** @var array Some data regarding the current user */
34
	private $_user;
35
36
	/** @var array Holds the info about the latest post of the series */
37
	private $_latest_post = [];
38
39
	/** @var int[] Remembers boards to easily scan the array to add moderators later */
40
	private $_boards = [];
41
42
	/** @var array An array containing all the data of the categories and boards requested */
43
	private $_categories = [];
44
45
	/** @var array The category/board that is being processed "now" */
46
	private $_current_boards = [];
47
48
	/** @var string The url where to find images */
49
	private $_images_url;
50
51
	/** @var int Cut the subject at this number of chars, set from modSettings */
52
	private $_subject_length = 48;
53
54
	/** @var int The id of the recycle board (0 for none or not enabled) */
55
	private $_recycle_board = 0;
56
57
	/** @var QueryInterface The database! */
58
	private $_db;
59
60
	/**
61
	 * Initialize the class
62
	 *
63
	 * @param array $options - Available options and corresponding defaults are:
64
	 *   - 'include_categories' => false
65
	 *   - 'countChildPosts' => false
66
	 *   - 'base_level' => false
67
	 *   - 'parent_id' => 0
68
	 *   - 'set_latest_post' => false
69
	 *   - 'get_moderators' => true
70
	 */
71
	public function __construct($options)
72
	{
73
		global $settings, $context, $modSettings;
74
75
		$this->_options = array_merge([
76
			'include_categories' => false,
77
			'countChildPosts' => false,
78
			'base_level' => 0,
79
			'parent_id' => 0,
80
			'set_latest_post' => false,
81
			'get_moderators' => true,
82
		], $options);
83
84
		$this->_options['avatars_on_indexes'] = !empty($settings['avatars_on_indexes']) && $settings['avatars_on_indexes'] !== 2;
85
		$this->_images_url = $settings['images_url'] . '/' . $context['theme_variant_url'];
86
87
		if (!empty($modSettings['subject_length']))
88
		{
89
			$this->_subject_length = $modSettings['subject_length'];
90
		}
91
92
		$this->_user = User::$info;
0 ignored issues
show
Documentation Bug introduced by
It seems like ElkArte\User::info of type ElkArte\Helper\ValuesContainer is incompatible with the declared type array of property $_user.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
93
		$this->_user['mod_cache_ap'] = empty($this->_user->mod_cache['ap']) ? [] : $this->_user->mod_cache['ap'];
0 ignored issues
show
Bug Best Practice introduced by
The property mod_cache does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
94
95
		$this->_db = database();
96
97
		// Start with an empty array.
98
		if ($this->_options['include_categories'])
99
		{
100
			$this->_categories = [];
101
		}
102
		else
103
		{
104
			$this->_current_boards = [];
105
		}
106
107
		// For performance, track the latest post while going through the boards.
108
		if (!empty($this->_options['set_latest_post']))
109
		{
110
			$this->_latest_post = ['timestamp' => 0];
111
		}
112
113
		if (!empty($modSettings['recycle_enable']))
114
		{
115 4
			$this->_recycle_board = (int) $modSettings['recycle_board'];
116
		}
117 4
	}
118
119 4
	/**
120 4
	 * Fetches a list of boards and (optional) categories including statistical
121
	 * information, sub-boards, and moderators.
122
	 *  - Used by both the board index (main data) and the message index (child boards).
123
	 *  - Depending on the include_categories setting returns an associative array with
124
	 * categories->boards->child_boards or an associative array with boards->child_boards.
125
	 *
126 2
	 * @return array
127
	 */
128 4
	public function getBoards(): array
129
	{
130 4
		global $txt, $modSettings;
131 4
132
		// Fetch and sort the boards' data.
133 4
		$result_boards = $this->_fetchBoardsData();
134
		$bbc_parser = ParserWrapper::instance();
135 4
136 4
		// Parent map used when accumulating grandchild post/topic counts
137
		$parent_map = [];
138 4
139
		// Run through the categories and boards (or only boards)...
140
		foreach ($result_boards as $row_board)
141 4
		{
142
			// Perhaps we are ignoring this board?
143 2
			$ignoreThisBoard = in_array($row_board['id_board'], $this->_user['ignoreboards']);
144
			$row_board['is_read'] = !empty($row_board['is_read']) || $ignoreThisBoard ? '1' : '0';
145
			// Not a child.
146
			$isChild = false;
147 2
148
			// Initialize category scaffolding when needed and early-continue if collapsed.
149
			$this->_initCategoryIfNeeded($row_board);
150
			if ($this->_options['include_categories'] && $this->_categories[$row_board['id_cat']]['is_collapsed'])
151 4
			{
152
				continue;
153 2
			}
154
155
			// This is a parent board.
156 4
			if ((int) $row_board['id_parent'] === (int) $this->_options['parent_id'])
157
			{
158
				$this->_ensureParentBoardEntry($row_board, $bbc_parser);
159
			}
160 4
			// Found a sub-board... make sure we've found its parent and the child hasn't been set yet.
161
			elseif (isset($this->_current_boards[$row_board['id_parent']]['children']) && !isset($this->_current_boards[$row_board['id_parent']]['children'][$row_board['id_board']]))
162
			{
163
				// A valid child!
164
				$isChild = true;
165
				$this->_addChildBoard($row_board, $bbc_parser);
166
			}
167
			// Child of a child... just add it on...
168
			elseif (!empty($this->_options['countChildPosts']))
169
			{
170
				$this->_accumulateGrandchildCounts($row_board, $parent_map);
171
				continue;
172
			}
173 4
			// Found a child of a child - skip.
174
			else
175 4
			{
176
				continue;
177
			}
178 4
179 4
			// Prepare the subject and make sure it's not too long.
180 4
			$this_last_post = $this->_buildLastPost($row_board);
181
182
			// Set the last post in the parent board.
183
			$this->_assignLastPost($row_board, $isChild, $this_last_post);
184
			// Determine a global most recent topic.
185
			if (!$this->_options['set_latest_post'])
186 4
			{
187 4
				continue;
188 4
			}
189 4
			if (empty($row_board['poster_time']))
190 4
			{
191 4
				continue;
192 4
			}
193
			if ($row_board['poster_time'] <= $this->_latest_post['timestamp'])
194 4
			{
195 4
				continue;
196 4
			}
197 4
			if ($ignoreThisBoard)
198 4
			{
199 4
				continue;
200
			}
201
			$this->_latest_post = &$this->_current_boards[$isChild ? $row_board['id_parent'] : $row_board['id_board']]['last_post'];
202 4
		}
203 4
204 4
		if ($this->_options['get_moderators'] && !empty($this->_boards))
205 4
		{
206
			$this->_getBoardModerators();
207
		}
208
209 4
		usort($this->_categories, static fn($a, $b) => $a['order'] <=> $b['order']);
210
211
		return $this->_options['include_categories'] ? $this->_categories : $this->_current_boards;
212
	}
213 4
214
	/**
215 4
	 * Fetch all boards (and optional categories) data from DB and sort by board_order
216
	 */
217
	private function _fetchBoardsData(): array
218 4
	{
219
		$request = $this->_db->fetchQuery('
220
			SELECT ' . ($this->_options['include_categories'] ? '
221 2
				c.id_cat, c.name AS cat_name, c.cat_order,' : '') . '
222 2
				b.id_board, b.name AS board_name, b.description, b.board_order,
223
				CASE WHEN b.redirect != {string:blank_string} THEN 1 ELSE 0 END AS is_redirect,
224 2
				b.num_posts, b.num_topics, b.unapproved_posts, b.unapproved_topics, b.id_parent,
225
				COALESCE(m.poster_time, 0) AS poster_time, COALESCE(mem.member_name, m.poster_name) AS poster_name,
226 2
				m.subject, m.id_topic, COALESCE(mem.real_name, m.poster_name) AS real_name,
227
				' . ($this->_user['is_guest'] ? ' 1 AS is_read, 0 AS new_from,' : '
228
				(CASE WHEN COALESCE(lb.id_msg, 0) >= b.id_msg_updated THEN 1 ELSE 0 END) AS is_read, COALESCE(lb.id_msg, -1) + 1 AS new_from,' . ($this->_options['include_categories'] ? '
229 2
				c.can_collapse, COALESCE(cc.id_member, 0) AS is_collapsed,' : '')) . '
230
				COALESCE(mem.id_member, 0) AS id_member, mem.avatar, m.id_msg' . ($this->_options['avatars_on_indexes'] ? ',
231 2
				COALESCE(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type, mem.email_address' : '') . '
232 2
			FROM {db_prefix}boards AS b' . ($this->_options['include_categories'] ? '
233 2
				LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)' : '') . '
234 2
				LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = b.id_last_msg)
235 2
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)' . ($this->_user['is_guest'] ? '' : '
236 2
				LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = b.id_board AND lb.id_member = {int:current_member})' . ($this->_options['include_categories'] ? '
237 2
				LEFT JOIN {db_prefix}collapsed_categories AS cc ON (cc.id_cat = c.id_cat AND cc.id_member = {int:current_member})' : '')) . ($this->_options['avatars_on_indexes'] ? '
238 2
				LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = m.id_member AND a.id_member != 0)' : '') . '
239 2
			WHERE {query_see_board}' . (empty($this->_options['countChildPosts']) ? (empty($this->_options['base_level']) ? '' : '
240 2
				AND b.child_level >= {int:child_level}') : '
241
				AND b.child_level BETWEEN {int:child_level} AND {int:upper_level}'),
242
			[
243
				'current_member' => $this->_user['id'],
244 2
				'child_level' => $this->_options['base_level'],
245 2
				'upper_level' => $this->_options['base_level'] + 1,
246 2
				'blank_string' => '',
247
			]
248
		);
249
250 2
		$result_boards = $request->fetch_all();
251
		usort($result_boards, static fn($a, $b) => $a['board_order'] <=> $b['board_order']);
252 2
		return $result_boards;
253
	}
254
255
	/**
256 2
	 * Initialize category for a row (when include_categories is enabled)
257
	 */
258
	private function _initCategoryIfNeeded(array $row_board): void
259 2
	{
260
		global $txt, $modSettings;
261
262
		if (!$this->_options['include_categories'])
263
		{
264
			return;
265 2
		}
266
267
		if (empty($this->_categories[$row_board['id_cat']]))
268
		{
269 2
			$cat_name = $row_board['cat_name'];
270
			$can_collapse = !empty($row_board['can_collapse']) && (int) $row_board['can_collapse'] === 1;
271
			$is_collapsed = $can_collapse && (int) $row_board['is_collapsed'] > 0;
272 2
273
			$this->_categories[$row_board['id_cat']] = [
274 2
				'id' => $row_board['id_cat'],
275 2
				'name' => $row_board['cat_name'],
276 2
				'order' => $row_board['cat_order'],
277 2
				'is_collapsed' => $is_collapsed,
278 2
				'can_collapse' => $can_collapse,
279 2
				'collapse_href' => $can_collapse ? getUrl('action', ['action' => 'collapse', 'c' => $row_board['id_cat'], 'sa' => $is_collapsed ? 'expand' : 'collapse', '{session_data}',]) . '#c' . $row_board['id_cat'] : '',
280 2
				'collapse_image' => $can_collapse ? '<img src="' . $this->_images_url . ($is_collapsed ? 'expand.png" alt="+"' : 'collapse.png" alt="-"') . ' />' : '',
281
				'href' => getUrl('action', $modSettings['default_forum_action']) . '#c' . $row_board['id_cat'],
282
				'boards' => [],
283
				'new' => false
284
			];
285
			$this->_categories[$row_board['id_cat']]['link'] = '<a id="c' . $row_board['id_cat'] . '"></a>' . ($this->_user['is_guest']
286 2
				? $cat_name
287 2
				: '<a href="' . getUrl('action', ['action' => 'unread', 'c' => $row_board['id_cat']]) . '" title="' . sprintf($txt['new_posts_in_category'], strip_tags($row_board['cat_name'])) . '">' . $cat_name . '</a>');
288 2
		}
289 2
290 2
		// Category new indicator (skip recycle bin)
291 2
		if ($this->_recycle_board !== (int) $row_board['id_board'])
292 2
		{
293 2
			$this->_categories[$row_board['id_cat']]['new'] |= empty($row_board['is_read']) && $row_board['poster_name'] !== '';
294
		}
295
296 2
		// Avoid showing a category unread link where it only has redirection boards.
297
		$this->_categories[$row_board['id_cat']]['show_unread'] = empty($this->_categories[$row_board['id_cat']]['show_unread']) ? !$row_board['is_redirect'] : 1;
298
299
		// Set current boards reference for this category (even if collapsed)
300
		$this->_current_boards = &$this->_categories[$row_board['id_cat']]['boards'];
301
	}
302
303
	/**
304
	 * Ensure the parent board entry exists and record for moderators mapping
305
	 */
306
	private function _ensureParentBoardEntry(array $row_board, ParserWrapper $bbc_parser): void
307
	{
308
		if (!isset($this->_current_boards[$row_board['id_board']]))
309
		{
310
			$href = getUrl('board', ['board' => $row_board['id_board'], 'start' => '0', 'name' => $row_board['board_name']]);
311
			$this->_current_boards[$row_board['id_board']] = [
312
				'new' => empty($row_board['is_read']),
313
				'id' => (int) $row_board['id_board'],
314
				'name' => $row_board['board_name'],
315
				'description' => $bbc_parser->parseBoard($row_board['description']),
316
				'raw_description' => $row_board['description'],
317
				'moderators' => [],
318
				'link_moderators' => [],
319
				'children' => [],
320
				'link_children' => [],
321
				'children_new' => false,
322
				'topics' => (int) $row_board['num_topics'],
323
				'posts' => (int) $row_board['num_posts'],
324
				'is_redirect' => $row_board['is_redirect'],
325
				'unapproved_topics' => $row_board['unapproved_topics'],
326
				'unapproved_posts' => $row_board['unapproved_posts'] - $row_board['unapproved_topics'],
327
				'can_approve_posts' => $this->_user['mod_cache_ap'] == [0] || in_array($row_board['id_board'], $this->_user['mod_cache_ap']),
328
				'href' => $href,
329
				'link' => '<a href="' . $href . '">' . $row_board['board_name'] . '</a>'
330
			];
331
		}
332
333
		$this->_boards[$row_board['id_board']] = $this->_options['include_categories'] ? $row_board['id_cat'] : 0;
334
	}
335
336
	/**
337
	 * Add a child board to its parent and update counters and links
338
	 */
339
	private function _addChildBoard(array $row_board, ParserWrapper $bbc_parser): void
340
	{
341
		$href = getUrl('board', ['board' => $row_board['id_board'], 'start' => '0', 'name' => $row_board['board_name']]);
342
		$this->_current_boards[$row_board['id_parent']]['children'][$row_board['id_board']] = [
343
			'id' => (int) $row_board['id_board'],
344
			'name' => $row_board['board_name'],
345
			'description' => $bbc_parser->parseBoard($row_board['description']),
346
			'raw_description' => $row_board['description'],
347
			'new' => empty($row_board['is_read']) && $row_board['poster_name'] !== '',
348
			'topics' => (int) $row_board['num_topics'],
349
			'posts' => (int) $row_board['num_posts'],
350
			'is_redirect' => $row_board['is_redirect'],
351
			'unapproved_topics' => $row_board['unapproved_topics'],
352
			'unapproved_posts' => $row_board['unapproved_posts'] - $row_board['unapproved_topics'],
353
			'can_approve_posts' => $this->_user['mod_cache_ap'] == [0] || in_array($row_board['id_board'], $this->_user['mod_cache_ap']),
354
			'href' => $href,
355
			'link' => '<a href="' . $href . '">' . $row_board['board_name'] . '</a>'
356
		];
357
358
		// Counting sub-board posts is... slow :/.
359
		if (!empty($this->_options['countChildPosts']) && !$row_board['is_redirect'])
360
		{
361
			$this->_current_boards[$row_board['id_parent']]['posts'] += $row_board['num_posts'];
362
			$this->_current_boards[$row_board['id_parent']]['topics'] += $row_board['num_topics'];
363
		}
364
365
		// Does this board contain new boards?
366
		$is_read = empty($row_board['is_read']);
367
		$this->_current_boards[$row_board['id_parent']]['children_new'] |= $is_read;
368
369
		// This is easier to use in many cases for the theme...
370
		$this->_current_boards[$row_board['id_parent']]['link_children'][] = &$this->_current_boards[$row_board['id_parent']]['children'][$row_board['id_board']]['link'];
371
	}
372
373
	/**
374
	 * Accumulate posts/topics for grandchildren when countChildPosts is enabled
375
	 */
376
	private function _accumulateGrandchildCounts(array $row_board, array &$parent_map): void
377
	{
378 2
		if (!isset($parent_map[$row_board['id_parent']]))
379 2
		{
380 2
			foreach ($this->_current_boards as $id => $board)
381
			{
382 2
				if (!isset($board['children'][$row_board['id_parent']]))
383 2
				{
384 2
					continue;
385 2
				}
386 2
387
				$parent_map[$row_board['id_parent']] = [&$this->_current_boards[$id], &$this->_current_boards[$id]['children'][$row_board['id_parent']]];
388 2
				$parent_map[$row_board['id_board']] = [&$this->_current_boards[$id], &$this->_current_boards[$id]['children'][$row_board['id_parent']]];
389 2
				break;
390 2
			}
391 2
		}
392 2
393
		if (isset($parent_map[$row_board['id_parent']]) && !$row_board['is_redirect'])
394 2
		{
395 2
			$parent_map[$row_board['id_parent']][0]['posts'] += $row_board['num_posts'];
396
			$parent_map[$row_board['id_parent']][0]['topics'] += $row_board['num_topics'];
397
			$parent_map[$row_board['id_parent']][1]['posts'] += $row_board['num_posts'];
398 2
			$parent_map[$row_board['id_parent']][1]['topics'] += $row_board['num_topics'];
399
		}
400 2
	}
401
402
	/**
403
	 * Build the last post-array for a board row
404 2
	 */
405
	private function _buildLastPost(array $row_board): array
406 2
	{
407 2
		global $txt;
408
409
		$row_board['subject'] = censor($row_board['subject']);
410
		$row_board['short_subject'] = Util::shorten_text($row_board['subject'], $this->_subject_length);
411
		$poster_href = getUrl('profile', ['action' => 'profile', 'u' => $row_board['id_member'], 'name' => $row_board['real_name']]);
412 2
		$this_last_post = [
413
			'id' => (int) $row_board['id_msg'],
414
			'time' => $row_board['poster_time'] > 0 ? standardTime($row_board['poster_time']) : $txt['not_applicable'],
415
			'html_time' => $row_board['poster_time'] > 0 ? htmlTime($row_board['poster_time']) : $txt['not_applicable'],
416
			'timestamp' => forum_time(true, $row_board['poster_time']),
417
			'subject' => $row_board['short_subject'],
418
			'member' => [
419
				'id' => (int) $row_board['id_member'],
420
				'username' => $row_board['poster_name'] !== '' ? $row_board['poster_name'] : $txt['not_applicable'],
421
				'name' => $row_board['real_name'],
422 2
				'href' => $row_board['poster_name'] !== '' && !empty($row_board['id_member']) ? $poster_href : '',
423
				'link' => $row_board['poster_name'] !== '' ? (empty($row_board['id_member']) ? $row_board['real_name'] : '<a href="' . $poster_href . '">' . $row_board['real_name'] . '</a>') : $txt['not_applicable'],
424 2
			],
425
			'start' => 'msg' . $row_board['new_from'],
426
			'topic' => (int) $row_board['id_topic']
427 2
		];
428
429
		if ($this->_options['avatars_on_indexes'])
430
		{
431
			$this_last_post['member']['avatar'] = determineAvatar($row_board);
432
		}
433
434
		if ($row_board['subject'] !== '')
435 2
		{
436
			$this_last_post['href'] = getUrl('topic', ['topic' => $row_board['id_topic'], 'start' => 'msg' . ($this->_user['is_guest'] ? $row_board['id_msg'] : $row_board['new_from']), 'subject' => $row_board['subject'], 0 => empty($row_board['is_read']) ? 'boardseen' : '']) . '#new';
437
			$this_last_post['link'] = '<a href="' . $this_last_post['href'] . '" title="' . Util::htmlspecialchars($row_board['subject']) . '">' . $row_board['short_subject'] . '</a>';
438
			$this_last_post['last_post_message'] = sprintf($txt['last_post_message'], $this_last_post['member']['link'], $this_last_post['link'], $this_last_post['html_time']);
439
		}
440
		else
441 2
		{
442
			$this_last_post['href'] = '';
443 2
			$this_last_post['link'] = $txt['not_applicable'];
444
			$this_last_post['last_post_message'] = '';
445
		}
446
447 4
		return $this_last_post;
448
	}
449 2
450
	/**
451
	 * Assign last post info to the right board (and child board if applicable)
452
	 */
453
	private function _assignLastPost(array $row_board, bool $isChild, array $this_last_post): void
454 4
	{
455
		if ((int) $row_board['id_parent'] === (int) $this->_options['parent_id'] || ($isChild && !empty($row_board['poster_time']) && $this->_current_boards[$row_board['id_parent']]['last_post']['timestamp'] < forum_time(true, $row_board['poster_time'])))
456 4
		{
457
			$this->_current_boards[$isChild ? $row_board['id_parent'] : $row_board['id_board']]['last_post'] = $this_last_post;
458
		}
459
460
		if ($isChild)
461
		{
462 2
			$this->_current_boards[$row_board['id_parent']]['children'][$row_board['id_board']]['last_post'] = $this_last_post;
463
			$this->_current_boards[$row_board['id_parent']]['children'][$row_board['id_board']]['new'] &= $row_board['poster_name'] !== '';
464 2
		}
465
		elseif ($row_board['poster_name'] === '')
466 2
		{
467 2
			$this->_current_boards[$row_board['id_board']]['new'] = false;
468
		}
469 2
	}
470
471 2
	/**
472
	 * Fetches and adds to the results the board moderators for the current boards
473
	 */
474
	private function _getBoardModerators(): void
475
	{
476
		global $txt;
477 2
478
		$boards = array_keys($this->_boards);
479
		$mod_cached = [];
480 2
481
		if (!Cache::instance()->getVar($mod_cached, 'localmods_' . md5(implode(',', $boards)), 3600))
482 2
		{
483
			$request = $this->_db->fetchQuery('
484
				SELECT 
485 2
					mods.id_board, COALESCE(mods_mem.id_member, 0) AS id_moderator, mods_mem.real_name AS mod_real_name
486
				FROM {db_prefix}moderators AS mods
487
					LEFT JOIN {db_prefix}members AS mods_mem ON (mods_mem.id_member = mods.id_member)
488
				WHERE mods.id_board IN ({array_int:id_boards})',
489
				[
490
					'id_boards' => $boards,
491
				]
492
			);
493
			$mod_cached = $request->fetch_all();
494
495
			Cache::instance()->put('localmods_' . md5(implode(',', $boards)), $mod_cached, 3600);
496
		}
497
498
		foreach ($mod_cached as $row_mods)
499
		{
500
			if ($this->_options['include_categories'])
501 2
			{
502
				$this->_current_boards = &$this->_categories[$this->_boards[$row_mods['id_board']]]['boards'];
503
			}
504
505
			$href = getUrl('profile', ['action' => 'profile', 'u' => $row_mods['id_moderator'], 'name' => $row_mods['mod_real_name']]);
506
			$this->_current_boards[$row_mods['id_board']]['moderators'][$row_mods['id_moderator']] = [
507
				'id' => $row_mods['id_moderator'],
508 2
				'name' => $row_mods['mod_real_name'],
509
				'href' => $href,
510 2
				'link' => '<a href="' . $href . '" title="' . $txt['board_moderator'] . '">' . $row_mods['mod_real_name'] . '</a>'
511
			];
512
			$this->_current_boards[$row_mods['id_board']]['link_moderators'][] = '<a href="' . $href . '" title="' . $txt['board_moderator'] . '">' . $row_mods['mod_real_name'] . '</a>';
513
		}
514
	}
515
516 2
	/**
517
	 * Returns the array containing the "latest post" information
518
	 *
519
	 * @return array
520
	 */
521
	public function getLatestPost(): array
522
	{
523
		if (empty($this->_latest_post) || empty($this->_latest_post['link']))
524
		{
525
			return [];
526
		}
527
528
		return $this->_latest_post;
529
	}
530
}
531