MessageIndex::quickModeration()   F
last analyzed

Complexity

Conditions 26
Paths > 20000

Size

Total Lines 46
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 702

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 26
eloc 28
nc 62257
nop 0
dl 0
loc 46
rs 0
c 1
b 0
f 1
ccs 0
cts 31
cp 0
crap 702

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 is what shows the listing of topics in a board.
5
 * It's just one or two functions, but don't underestimate it ;).
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 dev
15
 *
16
 */
17
18
namespace ElkArte\Controller;
19
20
use BBC\ParserWrapper;
21
use ElkArte\AbstractController;
22
use ElkArte\BoardsList;
23
use ElkArte\EventManager;
24
use ElkArte\FrontpageInterface;
25
use ElkArte\Helper\DataValidator;
26
use ElkArte\MembersList;
27
use ElkArte\Themes\TemplateLayers;
28
use ElkArte\TopicUtil;
29
use ElkArte\User;
30
31
/**
32
 * The all powerful messageindex, shows all the topics on a given board
33
 */
34
class MessageIndex extends AbstractController implements FrontpageInterface
35
{
36
	/** @var string The db column wer are going to sort */
37
	public $sort_column = '';
38
39
	/** @var array Know sort methods to db column */
40
	public $sort_methods = [];
41
42
	/** @var bool Sort direction asc or desc */
43
	public $ascending = '';
44
45
	/** @var TemplateLayers The template layers object */
46
	private $template_layers;
47
48
	/** @var bool if we are marking as read */
49
	public $is_marked_notify;
50
51
	/** @var string Chosen sort method from the request */
52
	public $sort_by;
53
54
	/** @var int Basically the page start */
55
	public $sort_start;
56
57
	/**
58
	 * {@inheritDoc}
59
	 */
60
	public static function frontPageHook(&$default_action)
61
	{
62
		add_integration_function('integrate_menu_buttons', '\\ElkArte\\Controller\\MessageIndex::addForumButton', '', false);
63
		add_integration_function('integrate_current_action', '\\ElkArte\\Controller\\MessageIndex::fixCurrentAction', '', false);
64
65
		$default_action = [
66
			'controller' => MessageIndex::class,
67
			'function' => 'action_messageindex_fp'
68
		];
69
	}
70
71
	/**
72
	 * {@inheritDoc}
73
	 */
74
	public static function frontPageOptions()
75
	{
76
		parent::frontPageOptions();
77
78
		theme()->addInlineJavascript('
79
			document.getElementById("front_page").addEventListener("change", function() {
80
			    let base = document.getElementById("message_index_frontpage").parentNode;
81
			
82
			    if (this.value.endsWith("MessageIndex")) 
83
			    {
84
			        base.fadeIn();
85
			        base.previousElementSibling.fadeIn();
86
			    }
87
			    else 
88
			    {
89
			        base.fadeOut();
90
			        base.previousElementSibling.fadeOut();
91
			    }
92
			});
93
			
94
			// Trigger change event
95
			let event = new Event("change");
96
			document.getElementById("front_page").dispatchEvent(event);', true);
97
98
		return [['select', 'message_index_frontpage', self::_getBoardsList()]];
99
	}
100
101
	/**
102
	 * Return the board listing for use in this class
103
	 *
104
	 * @return string[] list of boards with key = id and value = cat + name
105
	 * @uses getBoardList()
106
	 */
107
	protected static function _getBoardsList()
108
	{
109
		// Load the boards list.
110
		require_once(SUBSDIR . '/Boards.subs.php');
111
		$boards_list = getBoardList(['override_permissions' => true, 'not_redirection' => true], true);
112
113
		$boards = [];
114
		foreach ($boards_list as $board)
115 2
		{
116
			$boards[$board['id_board']] = $board['cat_name'] . ' - ' . $board['board_name'];
117
		}
118 2
119 2
		return $boards;
120
	}
121
122
	/**
123
	 * {@inheritDoc}
124
	 */
125
	public static function validateFrontPageOptions($post)
126 2
	{
127
		parent::validateFrontPageOptions($post);
128 2
		$boards = self::_getBoardsList();
129 2
130
		if (empty($post->message_index_frontpage) || !isset($boards[$post->message_index_frontpage]))
131
		{
132 2
			$post->front_page = null;
133
134
			return false;
135 2
		}
136
137
		return true;
138
	}
139
140
	/**
141 2
	 * Dispatches forward to message index handler.
142 2
	 *
143
	 * @see AbstractController::action_index
144 2
	 */
145
	public function action_index()
146 2
	{
147 2
		// Forward to message index, it's not like we know much more :P
148 2
		$this->action_messageindex();
149 2
	}
150
151
	/**
152 2
	 * Show the list of topics in this board, along with any sub-boards.
153
	 *
154
	 * @uses template_topic_listing() sub template of the MessageIndex template
155 2
	 */
156 2
	public function action_messageindex()
157 2
	{
158
		global $txt, $context, $board_info;
159
160 2
		// Check for redirection board, and if found, head off
161 2
		if ($board_info['redirect'])
162
		{
163
			$this->handleRedirectBoard();
164 2
		}
165
166 2
		// Load any necessary resources
167
		$this->loadSupportingResources();
168
169
		// Initialize $context
170 2
		$this->initializeContext();
171
172
		// Build a list of unapproved posts, if applicable
173
		if ($this->currentUserCanApprovePosts() && $this->hasUnapprovedPosts())
174
		{
175
			$context['unapproved_posts_message'] = $this->buildUnapprovedPostsMessage();
176 2
		}
177
178
		// Make sure the starting place makes sense and construct the page index
179
		$this->setPageNavigation();
180
181
		// Prepare profile links to those who can moderate on this board
182
		$this->setBoardModeratorLinks();
183
184 2
		// Mark current and parent boards as seen.
185
		$this->markCurrentAndParentBoardsAsSeen();
186
187 2
		// Load basic information about the boards children, aka sub boards
188 2
		$this->prepareSubBoardsForDisplay();
189
190
		// Who else is taking a look
191 2
		$this->prepareWhoViewing();
192
193
		// Setup topic sort icons/options for template use
194
		$this->setSortIcons();
195
196 2
		// Load the topic listing, accounting for sort, start page, etc.
197
		$this->loadBoardTopics();
198 2
199
		// What quick moderation options are available?
200
		$this->quickModeration();
201
202
		// Set template details/layers
203
		$this->template_layers = theme()->getLayers();
204
		if (!empty($context['boards']) && $this->sort_start === 0)
205
		{
206
			$this->template_layers->add('display_child_boards');
207 2
		}
208 2
209
		// If there are children, but no topics and no ability to post topics...
210
		$context['no_topic_listing'] = !empty($context['boards']) && empty($context['topics']) && !$context['can_post_new'];
211 2
212
		$this->template_layers->add('topic_listing');
213
214 2
		theme()->addJavascriptVar(['notification_board_notice' => $this->is_marked_notify ? $txt['notification_disable_board'] : $txt['notification_enable_board']], true);
215 2
216
		// Is Quick Topic available
217
		$this->quickTopic();
218 2
219 2
		// Finally action buttons like start new topic, notify, mark read ...
220 2
		$this->buildBoardButtons();
221
	}
222
223 2
	/**
224
	 * Handles redirection for a board. Increments the number of posts in the board
225
	 * and redirects to the specified board URL.
226
	 */
227
	private function handleRedirectBoard(): void
228
	{
229
		global $board, $board_info;
230 2
231 2
		// If this is a redirection board head off.
232 2
		require_once(SUBSDIR . '/Boards.subs.php');
233
234
		incrementBoard($board, 'num_posts');
235
		redirectexit($board_info['redirect']);
236
	}
237
238
	/**
239
	 * Initializes the context by setting various variables for the template.
240
	 */
241 2
	private function initializeContext(): void
242
	{
243
		global $txt, $context, $board_info, $modSettings;
244 2
245
		$description = ParserWrapper::instance()->parseBoard($board_info['description']);
246
247 2
		$context += [
248
			'name' => $board_info['name'],
249
			'sub_template' => 'topic_listing',
250
			'description' => $description,
251
			'robot_no_index' => $this->setRobotNoIndex(),
252
			// 'Print' the header and board info.
253
			'page_title' => strip_tags($board_info['name']),
254 2
			'page_description' => strip_tags($description),
255
			// Set the variables up for the template.
256
			'can_mark_notify' => $this->currentUserCanMarkNotify(),
257
			'can_post_new' => $this->currentUserCanPostNew(),
258 2
			'can_post_poll' => $this->currentUserCanPostPoll(),
259
			'can_moderate_forum' => $this->currentUserCanModerate(),
260
			'can_approve_posts' => $this->currentUserCanApprovePosts(),
261 2
			'jump_to' => [
262
				'label' => addslashes(un_htmlspecialchars($txt['jump_to'])),
263
				'board_name' => htmlspecialchars(strtr(strip_tags($board_info['name']), ['&amp;' => '&']), ENT_COMPAT, 'UTF-8'),
264
				'child_level' => $board_info['child_level'],
265
			],
266
			'message_index_preview' => !empty($modSettings['message_index_preview'])
267
		];
268
	}
269
270
	/**
271
	 * Sets if this is a page that we do, or do not, want bots to index
272
	 *
273 2
	 * @return bool
274
	 */
275
	public function setRobotNoIndex()
276
	{
277
		global $context;
278
279 2
		foreach ($this->_req->query as $k => $v)
280
		{
281
			// Don't index a sort result etc.
282
			if (!in_array($k, ['board', 'start', session_name()], true))
283
			{
284
				return true;
285
			}
286
		}
287 2
288
		return !empty($this->_req->query->start)
289
			&& (!is_numeric($this->_req->query->start) || $this->_req->query->start % $context['messages_per_page'] !== 0);
290 2
	}
291 2
292 2
	/**
293 2
	 * Checks whether the current user has permission to mark notifications
294 2
	 *
295
	 * @return bool True if the current user can mark notifications, false otherwise
296
	 */
297
	private function currentUserCanMarkNotify(): bool
298 2
	{
299 2
		return allowedTo('mark_notify') && $this->user->is_guest === false;
0 ignored issues
show
Bug Best Practice introduced by
The property is_guest does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
300 2
	}
301
302 2
	/**
303
	 * Checks if the current user is allowed to post new topics
304 2
	 *
305 2
	 * @return bool Returns true if the current user is allowed to post new topics, otherwise false.
306
	 */
307
	private function currentUserCanPostNew(): bool
308 2
	{
309
		global $modSettings;
310
311
		return allowedTo('post_new') || ($modSettings['postmod_active'] && allowedTo('post_unapproved_topics'));
312
	}
313
314
	/**
315 2
	 * Checks if the current user can post a poll
316
	 *
317 2
	 * @return bool Returns true if the current user can post a poll, false otherwise
318 2
	 */
319
	private function currentUserCanPostPoll(): bool
320
	{
321
		global $modSettings;
322
323
		return !empty($modSettings['pollMode']) && allowedTo('poll_post') && $this->currentUserCanPostNew();
324
	}
325
326
	/**
327 2
	 * Checks if the current user is allowed to moderate the forum
328
	 *
329 2
	 * @return bool Returns true if the current user is allowed to moderate the forum, false otherwise
330 2
	 */
331
	private function currentUserCanModerate(): bool
332
	{
333 2
		return allowedTo('moderate_forum');
334
	}
335
336 2
	/**
337
	 * Checks if the current user has the permission to approve posts
338 1
	 *
339
	 * @return bool True if the current user can approve posts, false otherwise
340 2
	 */
341 2
	private function currentUserCanApprovePosts(): bool
342 2
	{
343 2
		return allowedTo('approve_posts');
344 2
	}
345
346 2
	/**
347
	 * Check if the current user can restore a topic
348
	 *
349 2
	 * @return bool True if they can restore a topic
350 2
	 */
351 2
	private function currentUserCanRestore(): bool
352
	{
353
		global $modSettings, $board;
354
355
		return allowedTo('move_any') && !empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] == $board;
356 2
	}
357 2
358
	/**
359
	 * Loads supporting resources for the MessageIndex page.
360
	 */
361
	private function loadSupportingResources(): void
362
	{
363
		global $modSettings, $txt;
364
365
		// Fairly often, we'll work with boards. Current board, sub-boards.
366 2
		require_once(SUBSDIR . '/Boards.subs.php');
367
		require_once(SUBSDIR . '/MessageIndex.subs.php');
368
369 2
		theme()->getTemplates()->load('MessageIndex');
370
		loadJavascriptFile('topic.js');
371
372
		if (!empty($modSettings['message_index_preview']))
373 2
		{
374 2
			loadJavascriptFile('elk_toolTips.js', ['defer' => true]);
375 2
		}
376 2
377 2
		theme()->addJavascriptVar([
378
			'txt_mark_as_read_confirm' => $txt['mark_these_as_read_confirm']
379
		], true);
380
	}
381 2
382
	/**
383 2
	 * Checks if the current board has unapproved posts or topics.
384
	 *
385 2
	 * @return bool Returns true if the board has unapproved posts or topics, otherwise false.
386
	 */
387
	private function hasUnapprovedPosts(): bool
388 2
	{
389
		global $board_info;
390
391 2
		return $board_info['unapproved_topics'] || $board_info['unapproved_posts'];
392
	}
393
394
	/**
395
	 * Builds the message/links for the number of unapproved posts and topics in the current board.
396 2
	 *
397
	 * @return string The message containing the number of unapproved topics and posts.
398 2
	 */
399
	private function buildUnapprovedPostsMessage(): string
400 2
	{
401 2
		global $txt, $board_info, $board;
402
403
		$unApprovedTopics = $board_info['unapproved_topics'] ? '<a href="' . getUrl('action', ['action' => 'moderate', 'area' => 'postmod', 'sa' => 'topics', 'brd' => $board]) . '">' . $board_info['unapproved_topics'] . '</a>' : 0;
404
		$unApprovedPosts = $board_info['unapproved_posts'] ? '<a href="' . getUrl('action', ['action' => 'moderate', 'area' => 'postmod', 'sa' => 'posts', 'brd' => $board]) . '">' . ($board_info['unapproved_posts'] - $board_info['unapproved_topics']) . '</a>' : 0;
405
406
		return sprintf($txt['there_are_unapproved_topics'], $unApprovedTopics, $unApprovedPosts, getUrl('action', ['action' => 'moderate', 'area' => 'postmod', 'sa' => ($board_info['unapproved_topics'] ? 'topics' : 'posts'), 'brd' => $board]));
407
	}
408 2
409 2
	/**
410 2
	 * Sets up the page navigation for the board view.
411 2
	 */
412
	private function setPageNavigation()
413
	{
414
		global $board, $modSettings, $context, $options, $board_info;
415 2
416
		// How many topics do we have in total?
417
		$board_info['total_topics'] = $this->currentUserCanApprovePosts()
418
			? $board_info['num_topics'] + $board_info['unapproved_topics']
419
			: $board_info['num_topics'] + $board_info['unapproved_user_topics'];
420
421
		$all = $this->_req->isSet('all');
422
		$start = $this->_req->getQuery('start', 'intval', 0);
423
424
		// View all the topics, or just a few?
425
		$context['topics_per_page'] = empty($modSettings['disableCustomPerPage']) && !empty($options['topics_per_page']) ? $options['topics_per_page'] : $modSettings['defaultMaxTopics'];
426
		$context['messages_per_page'] = empty($modSettings['disableCustomPerPage']) && !empty($options['messages_per_page']) ? $options['messages_per_page'] : $modSettings['defaultMaxMessages'];
427
		$per_page = $all && !empty($modSettings['enableAllMessages']) ? $board_info['total_topics'] : $context['topics_per_page'];
428
429
		// Make sure the starting place makes sense and construct the page index.
430
		$context['page_index'] = constructPageIndex('{scripturl}?board=' . $board . '.%1$d' . $this->buildSortingString(), $start, $board_info['total_topics'], $per_page, true);
431
432
		// Set a canonical URL for this page.
433
		$context['canonical_url'] = getUrl('board', ['board' => $board, 'start' => $start, 'name' => $board_info['name']]);
434
435
		$context['links'] += [
436
			'prev' => $start >= $context['topics_per_page'] ? getUrl('board', ['board' => $board, 'start' => $start - $context['topics_per_page'], 'name' => $board_info['name']]) : '',
437
			'next' => $start + $context['topics_per_page'] < $board_info['total_topics'] ? getUrl('board', ['board' => $board, 'start' => $start + $context['topics_per_page'], 'name' => $board_info['name']]) : '',
438
		];
439
440
		if ($all && !empty($modSettings['enableAllMessages']) && $per_page > $modSettings['enableAllMessages'])
441
		{
442
			$per_page = $modSettings['enableAllMessages'];
443
			$start = 0;
444
		}
445
446
		$this->sort_start = $start;
447
		$context['start'] = $start;
448
		$context['per_page'] = $per_page;
449
	}
450
451
	/**
452
	 * Builds the sorting string for the message index page.
453
	 *
454
	 * @return string The sorting string with the chosen sort method and direction
455
	 */
456
	private function buildSortingString()
457
	{
458
		global $context, $txt;
459 2
460
		// Known sort methods.
461
		$this->sort_methods = messageIndexSort();
462
		$default_sort_method = 'last_post';
463
464
		// Requested a sorting method?
465 2
		$chosen_sort = $this->_req->getQuery('sort', 'trim', $default_sort_method);
466
467
		// We only know these.
468
		if (!isset($this->sort_methods[$chosen_sort]))
469
		{
470
			$chosen_sort = $default_sort_method;
471 2
		}
472 2
473
		$sort_string = ';sort=' . $chosen_sort . ($this->_req->isSet('desc') ? ';desc' : '');
474 2
		$this->sort_by = $chosen_sort;
475
		$this->ascending = $this->_req->isSet('asc');
476
		$this->sort_column = $this->sort_methods[$this->sort_by];
477 2
478 2
		$context['sort_by'] = $this->sort_by;
479 2
		$context['sort_direction'] = $this->ascending ? 'up' : 'down';
480
		$context['sort_title'] = $this->ascending ? $txt['sort_desc'] : $txt['sort_asc'];
481
482 2
		return $sort_string;
483 2
	}
484 2
485
	/**
486
	 * Loads board moderator links into the context for displaying on the template.
487 2
	 */
488
	private function setBoardModeratorLinks()
489 2
	{
490 2
		global $board_info, $context, $txt;
491 2
492
		// Build a list of the board's moderators.
493 2
		$context['moderators'] = &$board_info['moderators'];
494 2
		$context['link_moderators'] = [];
495
496
		if (!empty($board_info['moderators']))
497
		{
498
			foreach ($board_info['moderators'] as $mod)
499 2
			{
500 2
				$context['link_moderators'][] = '<a href="' . getUrl('profile', ['action' => 'profile', 'u' => $mod['id'], 'name' => $mod['name']]) . '" title="' . $txt . '">' . $mod['name'] . '</a>';
501
			}
502
		}
503
	}
504
505
	/**
506
	 * Marks the current board and its parent boards as seen for the current user
507
	 */
508
	public function markCurrentAndParentBoardsAsSeen()
509
	{
510
		global $board_info, $board;
511
512
		if ($this->user->is_guest)
0 ignored issues
show
Bug Best Practice introduced by
The property is_guest does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
513
		{
514
			$this->is_marked_notify = false;
515
			return;
516
		}
517
518
		// We can't know they read it if we allow prefetches.
519
		stop_prefetching();
520
521
		// Mark the board as read, and its parents.
522
		if (!empty($board_info['parent_boards']))
523
		{
524
			$board_list = array_keys($board_info['parent_boards']);
525
			$board_list[] = $board;
526
		}
527
		else
528
		{
529
			$board_list = [$board];
530
		}
531
532
		// Mark boards as read. Boards alone, no need for topics.
533
		markBoardsRead($board_list);
534
535
		// Clear topicseen cache
536
		if (!empty($board_info['parent_boards']))
537
		{
538
			// We've seen all these boards now!
539
			foreach ($board_info['parent_boards'] as $k => $dummy)
540
			{
541
				if (isset($_SESSION['topicseen_cache'][$k]))
542
				{
543
					unset($_SESSION['topicseen_cache'][$k]);
544
				}
545
			}
546
		}
547
548
		if (isset($_SESSION['topicseen_cache'][$board]))
549
		{
550
			unset($_SESSION['topicseen_cache'][$board]);
551
		}
552
553
		// From now on, they've seen it. So we reset notifications.
554
		$this->is_marked_notify = resetSentBoardNotification($this->user->id, $board);
555
	}
556
557
	/**
558
	 * Prepare and load sub-boards for display.
559
	 */
560
	private function prepareSubBoardsForDisplay()
561
	{
562
		global $board_info, $modSettings, $context;
563
564
		// Prepare sub-boards for display.
565
		$boardIndexOptions = [
566
			'include_categories' => false,
567
			'base_level' => $board_info['child_level'] + 1,
568
			'parent_id' => $board_info['id'],
569
			'set_latest_post' => false,
570
			'countChildPosts' => !empty($modSettings['countChildPosts']),
571
		];
572
573
		$boardList = new BoardsList($boardIndexOptions);
574
		$context['boards'] = $boardList->getBoards();
575
	}
576
577
	/**
578
	 * Prepares and loads into context the information about who is currently viewing the board
579
	 */
580
	private function prepareWhoViewing()
581
	{
582
		global $settings, $board;
583
584
		// Nosey, nosey - who's viewing this board?
585
		if (!empty($settings['display_who_viewing']))
586
		{
587
			require_once(SUBSDIR . '/Who.subs.php');
588
			formatViewers($board, 'board');
589
		}
590
	}
591
592
	/**
593
	 * Sets the sort icons for the topics headers in the context.
594
	 */
595
	private function setSortIcons()
596
	{
597
		global $context, $board, $board_info, $txt;
598
599
		// Trick
600
		$txt['starter'] = $txt['started_by'];
601
602
		// todo: Need to move this to theme.
603
		foreach ($this->sort_methods as $key => $val)
604
		{
605
			$sortIcon = match ($key)
606
			{
607
				'subject', 'starter', 'last_poster' => 'alpha',
608
				default => 'numeric',
609
			};
610
611
			$context['topics_headers'][$key] = [
612
				'url' => getUrl('board', ['board' => $board, 'start' => $this->sort_start, 'sort' => $key, 'name' => $board_info['name'], $this->sort_by === $key && $this->ascending ? 'desc' : 'asc']),
613
				'sort_dir_img' => $this->sort_by === $key ? '<i class="icon icon-small i-sort-' . $sortIcon . '-' . $context['sort_direction'] . '" title="' . $context['sort_title'] . '"><s>' . $context['sort_title'] . '</s></i>' : '',
614
			];
615
		}
616
	}
617
618
	/**
619
	 * Loads board topics into the context
620
	 */
621
	private function loadBoardTopics()
622
	{
623
		global $board, $modSettings, $context, $settings, $board_info;
624
625
		// Calculate the fastest way to get the topics.
626
		$start = $this->_req->getQuery('start', 'intval', 0);
627
		$per_page = $context['per_page'];
628
		$fake_ascending = false;
629
		if ($start > ($board_info['total_topics'] - 1) / 2)
630
		{
631
			$this->ascending = !$this->ascending;
632
			$fake_ascending = true;
633
			$per_page = $board_info['total_topics'] < $start + $per_page + 1 ? $board_info['total_topics'] - $start : $per_page;
634
			$start = $board_info['total_topics'] < $start + $per_page + 1 ? 0 : $board_info['total_topics'] - $start - $per_page;
635
		}
636
637
		$context['topics'] = [];
638
639
		// Set up the query options
640
		$indexOptions = [
641
			'only_approved' => $modSettings['postmod_active'] && !allowedTo('approve_posts'),
642
			'previews' => empty($modSettings['message_index_preview']) ? 0 : (empty($modSettings['preview_characters']) ? -1 : $modSettings['preview_characters']),
643
			'include_avatars' => $settings['avatars_on_indexes'],
644
			'ascending' => $this->ascending,
645
			'fake_ascending' => $fake_ascending
646
		];
647
648
		// Allow integration to modify / add to the $indexOptions
649
		call_integration_hook('integrate_messageindex_topics', [&$this->sort_column, &$indexOptions]);
650
651
		$topics_info = messageIndexTopics($board, $this->user->id, $start, $per_page, $this->sort_by, $this->sort_column, $indexOptions);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
652
653
		$context['topics'] = TopicUtil::prepareContext($topics_info, false, empty($modSettings['preview_characters']) ? 128 : $modSettings['preview_characters']);
654
655
		// Allow addons to add to the $context['topics']
656
		call_integration_hook('integrate_messageindex_listing', [$topics_info]);
657
658
		// Fix the sequence of topics if they were retrieved in the wrong order. (for speed reasons...)
659
		if ($fake_ascending)
660
		{
661
			$context['topics'] = array_reverse($context['topics'], true);
662
		}
663
664
		$topic_ids = array_keys($context['topics']);
665
666
		if (!empty($modSettings['enableParticipation']) && $this->user->is_guest === false && !empty($topic_ids))
0 ignored issues
show
Bug Best Practice introduced by
The property is_guest does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
667
		{
668
			$topics_participated_in = topicsParticipation($this->user->id, $topic_ids);
669
			foreach ($topics_participated_in as $participated)
670
			{
671
				$context['topics'][$participated['id_topic']]['is_posted_in'] = true;
672
				$context['topics'][$participated['id_topic']]['class'] = 'my_' . $context['topics'][$participated['id_topic']]['class'];
673
			}
674
		}
675
676
		// Trigger a topic loaded event
677
		$this->_events->trigger('topicinfo', ['callbacks' => &$context['topics']]);
678
	}
679
680
	/**
681
	 * Determines which quick moderation actions are available for this user.
682
	 * Loads which actions are available, on a per-topic basis, into $context.
683
	 */
684
	private function quickModeration()
685
	{
686
		global $modSettings, $context, $options, $board_info;
687
688
		// Is Quick Moderation active/needed?
689
		if (!empty($options['display_quick_mod']) && !empty($context['topics']))
690
		{
691
			$context += [
692
				'can_markread' => $context['user']['is_logged'],
693
				'can_lock' => allowedTo('lock_any'),
694
				'can_sticky' => allowedTo('make_sticky'),
695
				'can_move' => allowedTo('move_any'),
696
				'can_remove' => allowedTo('remove_any'),
697
				'can_merge' => allowedTo('merge_any'),
698
			];
699
700
			// Ignore approving own topics as it's unlikely to come up...
701
			$context['can_approve'] = $modSettings['postmod_active'] && allowedTo('approve_posts') && !empty($board_info['unapproved_topics']);
702
703
			// Can we restore topics?
704
			$context['can_restore'] = $this->currentUserCanRestore();
705
706
			// Set permissions for all the topics.
707
			foreach ($context['topics'] as $t => $topic)
708
			{
709
				$started = (int) $topic['first_post']['member']['id'] === $this->user->id;
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
710
				$context['topics'][$t]['quick_mod'] = [
711
					'lock' => allowedTo('lock_any') || ($started && allowedTo('lock_own')),
712
					'sticky' => allowedTo('make_sticky'),
713
					'move' => allowedTo('move_any') || ($started && allowedTo('move_own')),
714
					'modify' => allowedTo('modify_any') || ($started && allowedTo('modify_own')),
715
					'remove' => allowedTo('remove_any') || ($started && allowedTo('remove_own')),
716
					'approve' => $context['can_approve'] && $topic['unapproved_posts']
717
				];
718
				$context['can_lock'] |= ($started && allowedTo('lock_own'));
719
				$context['can_move'] |= ($started && allowedTo('move_own'));
720
				$context['can_remove'] |= ($started && allowedTo('remove_own'));
721
			}
722
723
			// Can we even use quick moderation on this batch?
724
			$context['can_quick_mod'] = $context['user']['is_logged'] || $context['can_approve'] || $context['can_remove'] || $context['can_lock'] || $context['can_sticky'] || $context['can_move'] || $context['can_merge'] || $context['can_restore'];
725
			if (!empty($context['can_quick_mod']))
726
			{
727
				$this->buildQuickModerationButtons();
728
				$context['qmod_actions'] = ['approve', 'remove', 'lock', 'sticky', 'move', 'merge', 'restore', 'markread'];
729
				call_integration_hook('integrate_quick_mod_actions');
730
			}
731
		}
732
	}
733
734
	/**
735
	 * Loads into $context the moderation button array for template use.
736
	 * Call integrate_message_index_mod_buttons hook
737
	 */
738
	public function buildQuickModerationButtons()
739
	{
740
		global $context;
741
742
		$context['can_show'] = false;
743
		$quickMod = array_column($context['topics'], 'quick_mod', 'id');
744
		$context['show_qm_message_checkbox'] = array_column($context['topics'], 'id');
745
746
		// Build valid topic id's by action
747
		$keys = array_keys($quickMod);
748
		foreach (['move', 'lock', 'remove', 'approve'] as $area)
749
		{
750
			// e.g. get topic id's where this quick_mod action xxx value is valid
751
			$temp = array_combine($keys, array_column($quickMod, $area));
752
			$context['allow_qm']['can_' . $area] = array_keys($temp, true);
753
			${'show_' . $area} = !empty($context['allow_qm']['can_' . $area]);
754
		}
755
756
		// Build the mod button array with buttons that are valid for, at least some, of the messages
757
		$context['mod_buttons'] = [
758
			'move' => [
759
				'test' => $show_move ? 'can_move' : 'can_show',
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $show_move seems to be never defined.
Loading history...
760
				'text' => 'move_topic',
761
				'id' => 'move',
762
				'lang' => true,
763
				'url' => 'javascript:void(0);',
764
			],
765
			'remove' => [
766
				'test' => $show_remove ? 'can_remove' : 'can_show',
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $show_remove seems to be never defined.
Loading history...
767
				'text' => 'remove_topic',
768
				'id' => 'remove',
769
				'lang' => true,
770
				'url' => 'javascript:void(0);',
771
			],
772
			'lock' => [
773
				'test' => $show_lock ? 'can_lock' : 'can_show',
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $show_lock seems to be never defined.
Loading history...
774
				'text' => 'set_lock',
775
				'id' => 'lock',
776
				'lang' => true,
777
				'url' => 'javascript:void(0);',
778
			],
779
			'approve' => [
780
				'test' => $show_approve ? 'can_approve' : 'can_show',
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $show_approve seems to be never defined.
Loading history...
781
				'text' => 'approve',
782
				'id' => 'approve',
783
				'lang' => true,
784
				'url' => 'javascript:void(0);',
785
			],
786
			'sticky' => [
787
				'test' => 'can_sticky',
788
				'text' => 'set_sticky',
789
				'id' => 'sticky',
790
				'lang' => true,
791
				'url' => 'javascript:void(0);',
792
			],
793
			'merge' => [
794
				'test' => 'can_merge',
795
				'text' => 'merge',
796
				'id' => 'merge',
797
				'lang' => true,
798
				'url' => 'javascript:void(0);',
799
			],
800
			'markread' => [
801
				'test' => 'can_markread',
802
				'text' => 'mark_read_short',
803
				'id' => 'markread',
804
				'lang' => true,
805
				'url' => 'javascript:void(0);',
806
			],
807
		];
808
809
		// Restore a topic, maybe even some doxing !
810
		if ($context['can_restore'])
811
		{
812
			$context['mod_buttons']['restore'] = [
813
				'text' => 'restore_topic',
814
				'lang' => true,
815
				'url' => 'javascript:void(0);',
816
			];
817
		}
818
819
		// Allow adding new buttons easily.
820
		call_integration_hook('integrate_message_index_quickmod_buttons');
821
822
		$context['mod_buttons'] = array_reverse($context['mod_buttons']);
823
	}
824
825
	/**
826
	 * Similar to Quick Reply, this is Quick Topic.
827
	 * Allows a way to start a new topic from the boards message index.
828
	 */
829
	private function quickTopic(): void
830
	{
831
		global $txt, $modSettings, $context, $options;
832
833
		// Quick topic enabled?
834
		if ($context['can_post_new'] && !empty($options['display_quick_reply']))
835
		{
836
			$this->prepareQuickTopic();
837
838
			checkSubmitOnce('register');
839
840
			$context['becomes_approved'] = true;
841
			if ($modSettings['postmod_active'] && !allowedTo('post_new') && allowedTo('post_unapproved_topics'))
842
			{
843
				$context['becomes_approved'] = false;
844
			}
845
			else
846
			{
847
				isAllowedTo('post_new');
848
			}
849
850
			require_once(SUBSDIR . '/Editor.subs.php');
851
			// Create the editor for the QT area
852
			$editorOptions = [
853
				'id' => 'message',
854
				'value' => '',
855
				'labels' => [
856
					'post_button' => $txt['post'],
857
				],
858
				'height' => '200px',
859
				'width' => '100%',
860
				'smiley_container' => 'smileyBox_message',
861
				'bbc_container' => 'bbcBox_message',
862
				// We submit/switch to full post page for the preview
863
				'preview_type' => 1,
864
				'buttons' => [
865
					'more' => [
866
						'type' => 'submit',
867
						'name' => 'more_options',
868
						'value' => $txt['post_options'],
869
						'options' => ''
870
					]
871
				],
872
			];
873
874
			// Trigger the prepare_context event for modules that have tied in to it
875
			$this->_events->trigger('prepare_context', ['editorOptions' => &$editorOptions, 'use_quick_reply' => !empty($options['display_quick_reply'])]);
876
877
			create_control_richedit($editorOptions);
878
879
			theme()->getTemplates()->load('GenericMessages');
880
		}
881
	}
882
883
	/**
884
	 * If Quick Topic is on, we need to load user information into $context so the poster sidebar renders
885
	 */
886
	private function prepareQuickTopic(): void
887
	{
888
		global $options, $context, $modSettings;
889
890
		if (empty($options['hide_poster_area']) && $options['display_quick_reply'])
891
		{
892
			MembersList::load(User::$info->id);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
893
			$thisUser = MembersList::get(User::$info->id);
894
			$thisUser->loadContext();
895
896
			$context['thisMember'] = [
897
				'id' => 'new',
898
				'is_message_author' => true,
899
				'member' => $thisUser->toArray()['data']
900
			];
901
			$context['can_issue_warning'] = allowedTo('issue_warning') && featureEnabled('w') && !empty($modSettings['warning_enable']);
902
			$context['can_send_pm'] = allowedTo('pm_send');
903
		}
904
	}
905
906
	/**
907
	 * Build the board buttons for the message index page.
908
	 */
909
	private function buildBoardButtons(): void
910
	{
911
		global $context, $settings, $board;
912
913
		// Build the message index button array.
914
		$context['normal_buttons'] = [
915
			'new_topic' => [
916
				'test' => 'can_post_new',
917
				'text' => 'new_topic',
918
				'lang' => true,
919
				'url' => getUrl('action', ['action' => 'post', 'board' => $board . '.0']),
920
				'active' => true],
921
			'notify' => [
922
				'test' => 'can_mark_notify',
923
				'text' => $this->is_marked_notify ? 'unnotify' : 'notify',
924
				'lang' => true, 'custom' => 'onclick="return notifyboardButton(this);"',
925
				'url' => getUrl('action', ['action' => 'notifyboard', 'sa' => ($this->is_marked_notify ? 'off' : 'on'), 'board' => $board . '.' . $this->sort_start, '{session_data}'])],
926
		];
927
928
		// They can only mark read if they are logged in, and it's enabled!
929
		if ($this->user->is_guest === false && $settings['show_mark_read'])
0 ignored issues
show
Bug Best Practice introduced by
The property is_guest does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
930
		{
931
			$context['normal_buttons']['markread'] = [
932
				'text' => 'mark_read_short',
933
				'lang' => true,
934
				'url' => getUrl('action', ['action' => 'markasread', 'sa' => 'board', 'board' => $board . '.0', '{session_data}']),
935
				'custom' => 'onclick="return markboardreadButton(this);"'
936
			];
937
		}
938
939
		// Allow adding new buttons easily.
940
		call_integration_hook('integrate_messageindex_buttons');
941
942
		// Trigger a post load event with quick access to normal buttons
943
		$this->_events->trigger('post_load', ['callbacks' => &$context['normal_buttons']]);
944
	}
945
946
	/**
947
	 * Show the list of topics in this board, along with any sub-boards.
948
	 *
949
	 * @uses template_topic_listing() sub template of the MessageIndex template
950
	 */
951
	public function action_messageindex_fp()
952
	{
953
		global $modSettings, $board;
954
955
		$board = $modSettings['message_index_frontpage'];
956
		loadBoard();
957
958
		$this->action_messageindex();
959
	}
960
961
	/**
962
	 * Allows for moderation from the message index.
963
	 *
964
	 * @todo refactor this...
965
	 */
966
	public function action_quickmod()
967
	{
968
		global $board, $modSettings, $context;
969
970
		// Check the session = get or post.
971
		checkSession('request');
972
973
		// Cleanup
974
		$validator = new DataValidator();
975
		$validator->sanitation_rules([
976
			'topics' => 'intval',
977
			'qaction' => 'trim',
978
			'move_to' => 'intval',
979
			'redirect_topic' => 'intval',
980
			'redirect_expires' => 'intval',
981
		]);
982
		$validator->input_processing(['topics' => 'array']);
983
		$validator->validate($this->_req->post);
984
985
		$selected_topics = $validator->topics;
986
		$selected_qaction = $validator->qaction;
987
988
		// Lets go straight to the restore area.
989
		if ($selected_qaction === 'restore' && !empty($selected_topics))
990
		{
991
			redirectexit('action=restoretopic;topics=' . implode(',', $selected_topics) . ';' . $context['session_var'] . '=' . $context['session_id']);
992
		}
993
994
		if (isset($_SESSION['topicseen_cache']))
995
		{
996
			$_SESSION['topicseen_cache'] = [];
997
		}
998
999
		// Remember the last board they moved things to.
1000
		if (!empty($validator->move_to))
1001
		{
1002
			$_SESSION['move_to_topic'] = [
1003
				'move_to' => $validator->move_to,
1004
				// And remember the last expiry period too.
1005
				'redirect_topic' => $validator->redirect_topic,
1006
				'redirect_expires' => $validator->redirect_expires,
1007
			];
1008
		}
1009
1010
		// This is going to be needed to send off the notifications and for updateLastMessages().
1011
		require_once(SUBSDIR . '/Post.subs.php');
1012
		require_once(SUBSDIR . '/Notification.subs.php');
1013
		require_once(SUBSDIR . '/Topic.subs.php');
1014
1015
		// Only a few possible actions.
1016
		$actions = [];
1017
1018
		// Permissions on this board
1019
		if (!empty($board))
1020
		{
1021
			$boards_can = [
1022
				'make_sticky' => allowedTo('make_sticky') ? [$board] : [],
1023
				'move_any' => allowedTo('move_any') ? [$board] : [],
1024
				'move_own' => allowedTo('move_own') ? [$board] : [],
1025
				'remove_any' => allowedTo('remove_any') ? [$board] : [],
1026
				'remove_own' => allowedTo('remove_own') ? [$board] : [],
1027
				'lock_any' => allowedTo('lock_any') ? [$board] : [],
1028
				'lock_own' => allowedTo('lock_own') ? [$board] : [],
1029
				'merge_any' => allowedTo('merge_any') ? [$board] : [],
1030
				'approve_posts' => allowedTo('approve_posts') ? [$board] : [],
1031
			];
1032
1033
			$redirect_url = 'board=' . $board . '.' . $this->_req->query->start;
1034
		}
1035
		else
1036
		{
1037
			$boards_can = boardsAllowedTo(['make_sticky', 'move_any', 'move_own', 'remove_any', 'remove_own', 'lock_any', 'lock_own', 'merge_any', 'approve_posts'], true, false);
1038
			$redirect_url = $this->_req->post->redirect_url ?? ($_SESSION['old_url'] ?? getUrlQuery('action', $modSettings['default_forum_action']));
1039
		}
1040
1041
		// Just what actions can they do?, approve, move, remove, lock, sticky, lock, merge, mark read?
1042
		$possibleActions = $this->setPossibleQmActions($boards_can);
1043
1044
		// Two methods:
1045
		// $_REQUEST['actions'] (id_topic => action), and
1046
		// $_REQUEST['topics'] and $this->_req->post->qaction.
1047
		// (if action is 'move', $_REQUEST['move_to'] or $_REQUEST['move_tos'][$topic] is used.)
1048
		if (!empty($selected_topics))
1049
		{
1050
			// If the action isn't valid, just quit now.
1051
			if (empty($selected_qaction) || !in_array($selected_qaction, $possibleActions, true))
1052
			{
1053
				redirectexit($redirect_url);
1054
			}
1055
1056
			// Merge requires all topics as one parameter and can be done at once.
1057
			if ($selected_qaction === 'merge')
1058
			{
1059
				// Merge requires at least two topics.
1060
				if (count($selected_topics) < 2)
1061
				{
1062
					redirectexit($redirect_url);
1063
				}
1064
1065
				$controller = new MergeTopics(new EventManager());
1066
				$controller->setUser(User::$info);
1067
				$controller->pre_dispatch();
1068
1069
				return $controller->action_mergeExecute($selected_topics);
1070
			}
1071
1072
			// Just convert to the other method, to make it easier.
1073
			foreach ($selected_topics as $topic)
1074
			{
1075
				$actions[$topic] = $selected_qaction;
1076
			}
1077
		}
1078
		else
1079
		{
1080
			$actions = $this->_req->getRequest('actions');
1081
		}
1082
1083
		// Weird... how'd you get here?
1084
		if (empty($actions))
1085
		{
1086
			redirectexit($redirect_url);
1087
		}
1088
1089
		// Validate each action.
1090
		$all_actions = [];
1091
		$action = '';
1092
		foreach ($actions as $topic => $action)
1093
		{
1094
			if (in_array($action, $possibleActions, true))
1095
			{
1096
				$all_actions[(int) $topic] = $action;
1097
			}
1098
		}
1099
1100
		$stickyCache = [];
1101
		$moveCache = [0 => [], 1 => []];
1102
		$removeCache = [];
1103
		$lockCache = [];
1104
		$markCache = [];
1105
		$approveCache = [];
1106
1107
		if (!empty($all_actions))
1108
		{
1109
			// Find all topics...
1110
			$topics_info = topicsDetails(array_keys($all_actions));
1111
1112
			foreach ($topics_info as $row)
1113
			{
1114
				if (!empty($board) && ($row['id_board'] != $board || ($modSettings['postmod_active'] && !$row['approved'] && !allowedTo('approve_posts'))))
1115
				{
1116
					continue;
1117
				}
1118
1119
				// Don't allow them to act on unapproved posts they can't see...
1120
				if ($modSettings['postmod_active'] && !$row['approved'] && !in_array(0, $boards_can['approve_posts']) && !in_array($row['id_board'], $boards_can['approve_posts']))
1121
				{
1122
					continue;
1123
				}
1124
1125
				// Goodness, this is fun.  We need to validate the action.
1126
				if ($all_actions[$row['id_topic']] === 'sticky' && !$this->canMakeSticky($boards_can, $row))
1127
				{
1128
					continue;
1129
				}
1130
1131
				if ($all_actions[$row['id_topic']] === 'move' && !$this->canMove($boards_can, $row))
1132
				{
1133
					continue;
1134
				}
1135
1136
				if ($all_actions[$row['id_topic']] === 'remove' && !$this->canRemove($boards_can, $row))
1137
				{
1138
					continue;
1139
				}
1140
1141
				if ($all_actions[$row['id_topic']] === 'lock' && !$this->canLock($boards_can, $row))
1142
				{
1143
					continue;
1144
				}
1145
1146
				// Separate the actions.
1147
				switch ($action)
1148
				{
1149
					case 'markread':
1150
						$markCache[] = $row['id_topic'];
1151
						break;
1152
					case 'sticky':
1153
						$stickyCache[] = $row['id_topic'];
1154
						break;
1155
					case 'move':
1156
						if (isset($this->_req->query->current_board))
1157
						{
1158
							moveTopicConcurrence((int) $this->_req->query->current_board, $board, $row['id_topic']);
1159
						}
1160
1161
						// $moveCache[0] is the topic, $moveCache[1] is the board to move to.
1162
						$moveCache[1][$row['id_topic']] = (int) ($this->_req->post->move_tos[$row['id_topic']] ?? $this->_req->post->move_to);
1163
1164
						if (!empty($moveCache[1][$row['id_topic']]))
1165
						{
1166
							$moveCache[0][] = $row['id_topic'];
1167
						}
1168
1169
						break;
1170
					case 'remove':
1171
						$removeCache[] = $row['id_topic'];
1172
						break;
1173
					case 'lock':
1174
						$lockCache[] = $row['id_topic'];
1175
						break;
1176
					case 'approve':
1177
						$approveCache[] = $row['id_topic'];
1178
						break;
1179
				}
1180
			}
1181
		}
1182
1183
		$affectedBoards = empty($board) ? [] : [(int) $board => [0, 0]];
1184
1185
		// Do all the stickies...
1186
		if (!empty($stickyCache))
1187
		{
1188
			toggleTopicSticky($stickyCache, true);
1189
		}
1190
1191
		// Move sucka! (this is, by the by, probably the most complicated part....)
1192
		if (!empty($moveCache[0]))
1193
		{
1194
			moveTopicsPermissions($moveCache);
1195
		}
1196
1197
		// Now delete the topics...
1198
		if (!empty($removeCache))
1199
		{
1200
			removeTopicsPermissions($removeCache);
1201
		}
1202
1203
		// Approve the topics...
1204
		if (!empty($approveCache))
1205
		{
1206
			approveTopics($approveCache, true, true);
1207
		}
1208
1209
		// And (almost) lastly, lock the topics...
1210
		if (!empty($lockCache))
1211
		{
1212
			toggleTopicsLock($lockCache, true);
1213
		}
1214
1215
		if (!empty($markCache))
1216
		{
1217
			$logged_topics = getLoggedTopics($this->user->id, $markCache);
1218
1219
			$markArray = [];
1220
			foreach ($markCache as $topic)
1221
			{
1222
				$markArray[] = [$this->user->id, $topic, $modSettings['maxMsgID'], (int) !empty($logged_topics[$topic])];
1223
			}
1224
1225
			markTopicsRead($markArray, true);
1226
		}
1227
1228
		updateTopicStats();
1229
		require_once(SUBSDIR . '/Messages.subs.php');
1230
		updateMessageStats();
1231
		updateSettings(['calendar_updated' => time(),]);
1232
1233
		if (!empty($affectedBoards))
1234
		{
1235
			updateLastMessages(array_keys($affectedBoards));
1236
		}
1237
1238
		redirectexit($redirect_url);
1239
	}
1240
1241
	/**
1242
	 * Just what actions can they perform on this board
1243
	 *
1244
	 * Checks if they can markread, sticky, move, remove, lock or merge
1245
	 *
1246
	 * @param array $boards_can
1247
	 * @return array
1248
	 */
1249
	public function setPossibleQmActions($boards_can)
1250
	{
1251
		$possibleActions = [];
1252
1253
		if ($this->user->is_guest === false)
0 ignored issues
show
Bug Best Practice introduced by
The property is_guest does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
1254
		{
1255
			$possibleActions[] = 'markread';
1256
		}
1257
1258
		if (!empty($boards_can['make_sticky']))
1259
		{
1260
			$possibleActions[] = 'sticky';
1261
		}
1262
1263
		if (!empty($boards_can['move_any']) || !empty($boards_can['move_own']))
1264
		{
1265
			$possibleActions[] = 'move';
1266
		}
1267
1268
		if (!empty($boards_can['remove_any']) || !empty($boards_can['remove_own']))
1269
		{
1270
			$possibleActions[] = 'remove';
1271
		}
1272
1273
		if (!empty($boards_can['lock_any']) || !empty($boards_can['lock_own']))
1274
		{
1275
			$possibleActions[] = 'lock';
1276
		}
1277
1278
		if (!empty($boards_can['merge_any']))
1279
		{
1280
			$possibleActions[] = 'merge';
1281
		}
1282
1283
		if (!empty($boards_can['approve_posts']))
1284
		{
1285
			$possibleActions[] = 'approve';
1286
		}
1287
1288
		return $possibleActions;
1289
	}
1290
1291
	/**
1292
	 * Can they sticky a topic
1293
	 *
1294
	 * @param array $boards_can
1295
	 * @param array $row
1296
	 * @return bool
1297
	 */
1298
	public function canMakeSticky($boards_can, $row)
1299
	{
1300
		return in_array(0, $boards_can['make_sticky'])
1301
			|| in_array($row['id_board'], $boards_can['make_sticky']);
1302
	}
1303
1304
	/**
1305
	 * Can they move a topic
1306
	 *
1307
	 * @param array $boards_can
1308
	 * @param array $row
1309
	 * @return bool
1310
	 */
1311
	public function canMove($boards_can, $row)
1312
	{
1313
		return in_array(0, $boards_can['move_any'])
1314
			|| in_array($row['id_board'], $boards_can['move_any'])
1315
			|| ($row['id_member_started'] == $this->user->id
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
1316
				&& (in_array(0, $boards_can['move_own']) || in_array($row['id_board'], $boards_can['move_own'])));
1317
	}
1318
1319
	/**
1320
	 * Can they remove a topic
1321
	 *
1322
	 * @param array $boards_can
1323
	 * @param array $row
1324
	 * @return bool
1325
	 */
1326
	public function canRemove($boards_can, $row)
1327
	{
1328
		return in_array(0, $boards_can['remove_any'])
1329
			|| in_array($row['id_board'], $boards_can['remove_any'])
1330
			|| ($row['id_member_started'] == $this->user->id
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
1331
				&& (in_array(0, $boards_can['remove_own']) || in_array($row['id_board'], $boards_can['remove_own'])));
1332
1333
	}
1334
1335
	/**
1336
	 * Can they lock a topic
1337
	 *
1338
	 * @param array $boards_can
1339
	 * @param array $row
1340
	 * @return bool
1341
	 */
1342
	public function canLock($boards_can, $row)
1343
	{
1344
		return in_array(0, $boards_can['lock_any'])
1345
			|| in_array($row['id_board'], $boards_can['lock_any'])
1346
			|| ($row['id_member_started'] == $this->user->id
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
1347
				&& $row['locked'] != 1
1348
				&& (in_array(0, $boards_can['lock_own']) || in_array($row['id_board'], $boards_can['lock_own'])));
1349
	}
1350
}