elkarte /
Elkarte
| 1 | <?php |
||||||
| 2 | |||||||
| 3 | /** |
||||||
| 4 | * Find and retrieve information about recently posted topics, messages, and the like. |
||||||
| 5 | * |
||||||
| 6 | * @package ElkArte Forum |
||||||
| 7 | * @copyright ElkArte Forum contributors |
||||||
| 8 | * @license BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file) |
||||||
| 9 | * |
||||||
| 10 | * This file contains code covered by: |
||||||
| 11 | * copyright: 2011 Simple Machines (http://www.simplemachines.org) |
||||||
| 12 | * |
||||||
| 13 | * @version 2.0 dev |
||||||
| 14 | * |
||||||
| 15 | */ |
||||||
| 16 | |||||||
| 17 | namespace ElkArte\Controller; |
||||||
| 18 | |||||||
| 19 | use ElkArte\AbstractController; |
||||||
| 20 | use ElkArte\Exceptions\Exception; |
||||||
| 21 | |||||||
| 22 | /** |
||||||
| 23 | * Handles the finding of Unread posts and replies |
||||||
| 24 | */ |
||||||
| 25 | class Unread extends AbstractController |
||||||
| 26 | { |
||||||
| 27 | /** @var array The board ids we are marking */ |
||||||
| 28 | private $_boards = []; |
||||||
| 29 | |||||||
| 30 | /** @var bool */ |
||||||
| 31 | private $_is_topics = false; |
||||||
| 32 | |||||||
| 33 | /** @var int Number of topics */ |
||||||
| 34 | private $_num_topics = 0; |
||||||
| 35 | |||||||
| 36 | /** @var string The action being performed */ |
||||||
| 37 | private $_action = 'unread'; |
||||||
| 38 | |||||||
| 39 | /** @var bool */ |
||||||
| 40 | private $_action_unread = false; |
||||||
| 41 | |||||||
| 42 | /** @var bool */ |
||||||
| 43 | private $_action_unreadreplies = false; |
||||||
| 44 | |||||||
| 45 | /** |
||||||
| 46 | * The object that will retrieve the data |
||||||
| 47 | * |
||||||
| 48 | * @var Unread |
||||||
| 49 | */ |
||||||
| 50 | private $_grabber; |
||||||
| 51 | |||||||
| 52 | /** |
||||||
| 53 | * Called before any other action method in this class. |
||||||
| 54 | * |
||||||
| 55 | * - Allows for initializations, such as default values or |
||||||
| 56 | * loading templates or language files. |
||||||
| 57 | * |
||||||
| 58 | * @uses template_unread() in Recent.template.php |
||||||
| 59 | */ |
||||||
| 60 | public function pre_dispatch() |
||||||
| 61 | { |
||||||
| 62 | global $txt, $scripturl, $context, $settings, $modSettings, $options; |
||||||
| 63 | |||||||
| 64 | // Guests can't have unread things, we don't know anything about them. |
||||||
| 65 | is_not_guest(); |
||||||
| 66 | |||||||
| 67 | // Pre-fetching + lots of MySQL work = bad mojo. |
||||||
| 68 | stop_prefetching(); |
||||||
| 69 | |||||||
| 70 | require_once(SUBSDIR . '/Recent.subs.php'); |
||||||
| 71 | require_once(SUBSDIR . '/Boards.subs.php'); |
||||||
| 72 | |||||||
| 73 | // Determine the action, unreadreplies or unread |
||||||
| 74 | $this->_action = $this->_req->getQuery('action') === 'unreadreplies' ? 'unreadreplies' : 'unread'; |
||||||
| 75 | $this->_action_unread = $this->_action === 'unread'; |
||||||
| 76 | $this->_action_unreadreplies = $this->_action !== 'unread'; |
||||||
| 77 | |||||||
| 78 | // Some goodies for template use |
||||||
| 79 | $context['showCheckboxes'] = !empty($options['display_quick_mod']) && $settings['show_mark_read']; |
||||||
| 80 | $context['showing_all_topics'] = isset($this->_req->query->all); |
||||||
| 81 | $context['start'] = $this->_req->getQuery('start', 'intval', 0); |
||||||
| 82 | $context['topics_per_page'] = (int) (empty($modSettings['disableCustomPerPage']) && !empty($options['topics_per_page']) ? $options['topics_per_page'] : $modSettings['defaultMaxTopics']); |
||||||
| 83 | |||||||
| 84 | // Initialize the Unread class |
||||||
| 85 | $this->_grabber = new \ElkArte\Unread($this->user->id, $modSettings['postmod_active'], $modSettings['enable_unwatch'], $context['showing_all_topics']); |
||||||
| 86 | |||||||
| 87 | // Make sure we can continue |
||||||
| 88 | $this->_checkServerLoad(); |
||||||
| 89 | |||||||
| 90 | // Set the right page title for the action we are performing |
||||||
| 91 | if ($this->_action_unread) |
||||||
| 92 | { |
||||||
| 93 | $context['page_title'] = $context['showing_all_topics'] ? $txt['unread_topics_all'] : $txt['unread_topics_visit']; |
||||||
| 94 | } |
||||||
| 95 | else |
||||||
| 96 | { |
||||||
| 97 | $context['page_title'] = $txt['unread_replies']; |
||||||
| 98 | } |
||||||
| 99 | |||||||
| 100 | // Are we specifying any specific board? |
||||||
| 101 | $this->_wanted_boards(); |
||||||
| 102 | $this->_sorting_conditions(); |
||||||
| 103 | |||||||
| 104 | if (!empty($this->_req->query->c) && is_array($this->_req->query->c) && count($this->_req->query->c) === 1) |
||||||
| 105 | { |
||||||
| 106 | require_once(SUBSDIR . '/Categories.subs.php'); |
||||||
| 107 | $name = categoryName((int) $this->_req->query->c[0]); |
||||||
| 108 | |||||||
| 109 | $context['breadcrumbs'][] = [ |
||||||
| 110 | 'url' => getUrl('action', $modSettings['default_forum_action']) . '#c' . (int) $this->_req->query->c[0], |
||||||
| 111 | 'name' => $name |
||||||
| 112 | ]; |
||||||
| 113 | } |
||||||
| 114 | |||||||
| 115 | $context['breadcrumbs'][] = [ |
||||||
| 116 | 'url' => $scripturl . '?action=' . $this->_action . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'], |
||||||
| 117 | 'name' => $this->_action_unread ? $txt['unread_topics_visit'] : $txt['unread_replies'] |
||||||
| 118 | ]; |
||||||
| 119 | |||||||
| 120 | // Prepare the template |
||||||
| 121 | theme()->getTemplates()->load('Recent'); |
||||||
| 122 | $context['sub_template'] = 'unread'; |
||||||
| 123 | $context['unread_header_title'] = $this->_action_unread ? ($context['showing_all_topics'] ? $txt['unread_topics_all'] : $txt['unread_topics_visit']) : $txt['unread_replies']; |
||||||
| 124 | $template_layers = theme()->getLayers(); |
||||||
| 125 | $template_layers->add($context['sub_template']); |
||||||
| 126 | |||||||
| 127 | $this->_is_topics = $this->_action_unread; |
||||||
| 128 | |||||||
| 129 | // If empty, no preview at all |
||||||
| 130 | if (!empty($modSettings['message_index_preview'])) |
||||||
| 131 | { |
||||||
| 132 | loadJavascriptFile('elk_toolTips.js', ['defer' => true]); |
||||||
| 133 | $context['message_index_preview'] = true; |
||||||
| 134 | |||||||
| 135 | // If 0 means everything |
||||||
| 136 | if (empty($modSettings['preview_characters'])) |
||||||
| 137 | { |
||||||
| 138 | $this->_grabber->bodyPreview(true); |
||||||
| 139 | } |
||||||
| 140 | // Default: a SUBSTRING |
||||||
| 141 | else |
||||||
| 142 | { |
||||||
| 143 | $this->_grabber->bodyPreview($modSettings['preview_characters']); |
||||||
| 144 | } |
||||||
| 145 | } |
||||||
| 146 | } |
||||||
| 147 | |||||||
| 148 | /** |
||||||
| 149 | * Validates the server can perform the required operation given its current loading |
||||||
| 150 | */ |
||||||
| 151 | private function _checkServerLoad(): void |
||||||
| 152 | { |
||||||
| 153 | global $context, $modSettings; |
||||||
| 154 | // Check for any server load issues |
||||||
| 155 | if ($context['showing_all_topics'] |
||||||
| 156 | && !empty($modSettings['loadavg_allunread']) |
||||||
| 157 | && $modSettings['current_load'] >= $modSettings['loadavg_allunread']) |
||||||
| 158 | { |
||||||
| 159 | throw new Exception('loadavg_allunread_disabled', false); |
||||||
| 160 | } |
||||||
| 161 | elseif ($this->_action_unreadreplies |
||||||
| 162 | && !empty($modSettings['loadavg_unreadreplies']) |
||||||
| 163 | && $modSettings['current_load'] >= $modSettings['loadavg_unreadreplies']) |
||||||
| 164 | { |
||||||
| 165 | throw new Exception('loadavg_unreadreplies_disabled', false); |
||||||
| 166 | } |
||||||
| 167 | elseif (!$context['showing_all_topics'] |
||||||
| 168 | && $this->_action_unread && !empty($modSettings['loadavg_unread']) |
||||||
| 169 | && $modSettings['current_load'] >= $modSettings['loadavg_unread']) |
||||||
| 170 | { |
||||||
| 171 | throw new Exception('loadavg_unread_disabled', false); |
||||||
| 172 | } |
||||||
| 173 | } |
||||||
| 174 | |||||||
| 175 | /** |
||||||
| 176 | * Finds out the boards the user want. |
||||||
| 177 | */ |
||||||
| 178 | private function _wanted_boards(): void |
||||||
| 179 | { |
||||||
| 180 | global $board, $context; |
||||||
| 181 | |||||||
| 182 | if (isset($this->_req->query->children) && (!empty($board) || !empty($this->_req->query->boards))) |
||||||
| 183 | { |
||||||
| 184 | $this->_boards = []; |
||||||
| 185 | |||||||
| 186 | if (!empty($this->_req->query->boards)) |
||||||
| 187 | { |
||||||
| 188 | $this->_boards = array_map('intval', explode(',', $this->_req->query->boards)); |
||||||
| 189 | } |
||||||
| 190 | |||||||
| 191 | if (!empty($board)) |
||||||
| 192 | { |
||||||
| 193 | $this->_boards[] = (int) $board; |
||||||
| 194 | } |
||||||
| 195 | |||||||
| 196 | // The easiest thing is to just get all the boards they can see, |
||||||
| 197 | // but since we've specified the top of tree we ignore some of them |
||||||
| 198 | $this->_boards = addChildBoards($this->_boards); |
||||||
|
0 ignored issues
–
show
|
|||||||
| 199 | |||||||
| 200 | $context['querystring_board_limits'] = ';boards=' . implode(',', $this->_boards) . ';start=%d'; |
||||||
|
0 ignored issues
–
show
$this->_boards of type false is incompatible with the type array expected by parameter $pieces of implode().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 201 | } |
||||||
| 202 | elseif (!empty($board)) |
||||||
| 203 | { |
||||||
| 204 | $this->_boards = [$board]; |
||||||
| 205 | $context['querystring_board_limits'] = ';board=' . $board . '.%1$d'; |
||||||
| 206 | } |
||||||
| 207 | elseif (!empty($this->_req->query->boards)) |
||||||
| 208 | { |
||||||
| 209 | $selected_boards = array_map('intval', explode(',', $this->_req->query->boards)); |
||||||
| 210 | |||||||
| 211 | $this->_boards = accessibleBoards($selected_boards); |
||||||
| 212 | |||||||
| 213 | $context['querystring_board_limits'] = ';boards=' . implode(',', $this->_boards) . ';start=%1$d'; |
||||||
| 214 | } |
||||||
| 215 | elseif (!empty($this->_req->query->c)) |
||||||
| 216 | { |
||||||
| 217 | $categories = array_map('intval', explode(',', $this->_req->query->c)); |
||||||
| 218 | |||||||
| 219 | $this->_boards = array_keys(boardsPosts([], $categories, $this->_action_unread)); |
||||||
| 220 | |||||||
| 221 | $context['querystring_board_limits'] = ';c=' . $this->_req->query->c . ';start=%1$d'; |
||||||
| 222 | |||||||
| 223 | $this->_req->query->c = explode(',', $this->_req->query->c); |
||||||
| 224 | } |
||||||
| 225 | else |
||||||
| 226 | { |
||||||
| 227 | $see_board = $this->_action_unreadreplies ? 'query_see_board' : 'query_wanna_see_board'; |
||||||
| 228 | |||||||
| 229 | // Don't bother to show deleted posts! |
||||||
| 230 | $this->_boards = wantedBoards($see_board); |
||||||
| 231 | |||||||
| 232 | $context['querystring_board_limits'] = ';start=%1$d'; |
||||||
| 233 | $context['no_board_limits'] = true; |
||||||
| 234 | } |
||||||
| 235 | |||||||
| 236 | if (empty($this->_boards)) |
||||||
| 237 | { |
||||||
| 238 | throw new Exception('error_no_boards_selected'); |
||||||
| 239 | } |
||||||
| 240 | |||||||
| 241 | $this->_grabber->setBoards($this->_boards); |
||||||
|
0 ignored issues
–
show
The method
setBoards() does not exist on ElkArte\Controller\Unread.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||||||
| 242 | } |
||||||
| 243 | |||||||
| 244 | /** |
||||||
| 245 | * Set up the array for the sorting dropdown. |
||||||
| 246 | */ |
||||||
| 247 | private function _sorting_conditions(): void |
||||||
| 248 | { |
||||||
| 249 | global $context, $txt, $scripturl; |
||||||
| 250 | |||||||
| 251 | $sort_methods = [ |
||||||
| 252 | 'subject' => 'ms.subject', |
||||||
| 253 | 'starter' => 'COALESCE(mems.real_name, ms.poster_name)', |
||||||
| 254 | 'replies' => 't.num_replies', |
||||||
| 255 | 'views' => 't.num_views', |
||||||
| 256 | 'first_post' => 't.id_topic', |
||||||
| 257 | 'last_post' => 't.id_last_msg' |
||||||
| 258 | ]; |
||||||
| 259 | |||||||
| 260 | // The default is the most logical: newest first. |
||||||
| 261 | if (!isset($this->_req->query->sort) || !isset($sort_methods[$this->_req->query->sort])) |
||||||
| 262 | { |
||||||
| 263 | $context['sort_by'] = 'last_post'; |
||||||
| 264 | $ascending = isset($this->_req->query->asc); |
||||||
| 265 | |||||||
| 266 | $context['querystring_sort_limits'] = $ascending ? ';asc' : ''; |
||||||
| 267 | } |
||||||
| 268 | // But, for other methods the default sort is ascending. |
||||||
| 269 | else |
||||||
| 270 | { |
||||||
| 271 | $context['sort_by'] = $this->_req->query->sort; |
||||||
| 272 | $ascending = !isset($this->_req->query->desc); |
||||||
| 273 | |||||||
| 274 | $context['querystring_sort_limits'] = ';sort=' . $context['sort_by'] . ($ascending ? '' : ';desc'); |
||||||
| 275 | } |
||||||
| 276 | |||||||
| 277 | $this->_grabber->setSorting($sort_methods[$context['sort_by']], $ascending); |
||||||
|
0 ignored issues
–
show
The method
setSorting() does not exist on ElkArte\Controller\Unread.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||||||
| 278 | |||||||
| 279 | $context['sort_direction'] = $ascending ? 'up' : 'down'; |
||||||
| 280 | $context['sort_title'] = $ascending ? $txt['sort_desc'] : $txt['sort_asc']; |
||||||
| 281 | |||||||
| 282 | // Trick |
||||||
| 283 | $txt['starter'] = $txt['started_by']; |
||||||
| 284 | |||||||
| 285 | foreach (array_keys($sort_methods) as $key) |
||||||
| 286 | { |
||||||
| 287 | switch ($key) |
||||||
| 288 | { |
||||||
| 289 | case 'subject': |
||||||
| 290 | case 'starter': |
||||||
| 291 | $sorticon = 'alpha'; |
||||||
| 292 | break; |
||||||
| 293 | default: |
||||||
| 294 | $sorticon = 'numeric'; |
||||||
| 295 | } |
||||||
| 296 | |||||||
| 297 | $context['topics_headers'][$key] = ['url' => $scripturl . '?action=' . $this->_action . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], $this->_req->query->start) . ';sort=' . $key . ($context['sort_by'] == $key && $context['sort_direction'] === 'up' ? ';desc' : ''), 'sort_dir_img' => $context['sort_by'] == $key ? '<i class="icon icon-small i-sort-' . $sorticon . '-' . $context['sort_direction'] . '" title="' . $context['sort_title'] . '"></i>' : '',]; |
||||||
| 298 | } |
||||||
| 299 | } |
||||||
| 300 | |||||||
| 301 | /** |
||||||
| 302 | * Intended entry point for unread controller class. |
||||||
| 303 | * |
||||||
| 304 | * @see AbstractController::action_index |
||||||
| 305 | */ |
||||||
| 306 | public function action_index() |
||||||
| 307 | { |
||||||
| 308 | // Figure out what action to do .. Thinking, Thinking, OK unread |
||||||
| 309 | $this->action_unread(); |
||||||
| 310 | } |
||||||
| 311 | |||||||
| 312 | /** |
||||||
| 313 | * Find unread topics. |
||||||
| 314 | * |
||||||
| 315 | * Accessed by action=unread |
||||||
| 316 | */ |
||||||
| 317 | public function action_unread(): ?bool |
||||||
| 318 | { |
||||||
| 319 | global $context, $settings; |
||||||
| 320 | |||||||
| 321 | $this->_grabber->setAction(\ElkArte\Unread::UNREAD); |
||||||
|
0 ignored issues
–
show
The method
setAction() does not exist on ElkArte\Controller\Unread.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||||||
| 322 | $this->_grabber->setEarliestMsg($context['showing_all_topics'] ? earliest_msg() : 0); |
||||||
|
0 ignored issues
–
show
The method
setEarliestMsg() does not exist on ElkArte\Controller\Unread.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||||||
| 323 | |||||||
| 324 | // @todo Add modified_time in for log_time check? |
||||||
| 325 | if ($this->_is_topics) |
||||||
| 326 | { |
||||||
| 327 | $this->_num_topics = $this->_grabber->numUnreads(empty($_SESSION['first_login']), $_SESSION['id_msg_last_visit']); |
||||||
|
0 ignored issues
–
show
The method
numUnreads() does not exist on ElkArte\Controller\Unread.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||||||
| 328 | $type = 'topics'; |
||||||
| 329 | } |
||||||
| 330 | // Does it make sense?... Dunno. |
||||||
| 331 | else |
||||||
| 332 | { |
||||||
| 333 | $this->action_unreadreplies(); |
||||||
| 334 | return null; |
||||||
| 335 | } |
||||||
| 336 | |||||||
| 337 | if ($this->_num_topics == 0) |
||||||
| 338 | { |
||||||
| 339 | // Messages mark always, topics only if this is an all topics query |
||||||
| 340 | if ($type === 'message' || ($type === 'topics' && $context['showing_all_topics'])) |
||||||
| 341 | { |
||||||
| 342 | // Since there are no unread topics, mark the boards as read! |
||||||
| 343 | // @todo look at this... there are no more unread topics already. |
||||||
| 344 | // If clearing of log_topics is still needed, perhaps do it separately. |
||||||
| 345 | markBoardsRead($this->_boards, false, true); |
||||||
| 346 | } |
||||||
| 347 | |||||||
| 348 | $context['topics'] = []; |
||||||
| 349 | |||||||
| 350 | if ($context['querystring_board_limits'] === ';start=%1$d') |
||||||
| 351 | { |
||||||
| 352 | $context['querystring_board_limits'] = ''; |
||||||
| 353 | } |
||||||
| 354 | else |
||||||
| 355 | { |
||||||
| 356 | $context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $this->_req->query->start); |
||||||
| 357 | } |
||||||
| 358 | } |
||||||
| 359 | else |
||||||
| 360 | { |
||||||
| 361 | $context['topics'] = $this->_grabber->getUnreads($type, $this->_req->query->start, $context['topics_per_page'], $settings['avatars_on_indexes']); |
||||||
|
0 ignored issues
–
show
The method
getUnreads() does not exist on ElkArte\Controller\Unread.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||||||
| 362 | } |
||||||
| 363 | |||||||
| 364 | $this->_exiting_unread(); |
||||||
| 365 | |||||||
| 366 | return true; |
||||||
| 367 | } |
||||||
| 368 | |||||||
| 369 | /** |
||||||
| 370 | * Find unread replies. |
||||||
| 371 | * |
||||||
| 372 | * Accessed by action=unreadreplies |
||||||
| 373 | */ |
||||||
| 374 | public function action_unreadreplies(): void |
||||||
| 375 | { |
||||||
| 376 | global $scripturl, $context, $settings; |
||||||
| 377 | |||||||
| 378 | $this->_grabber->setAction(\ElkArte\Unread::UNREADREPLIES); |
||||||
| 379 | |||||||
| 380 | $this->_num_topics = $this->_grabber->numUnreads(); |
||||||
| 381 | |||||||
| 382 | if ($this->_num_topics == 0) |
||||||
| 383 | { |
||||||
| 384 | $context['topics'] = []; |
||||||
| 385 | if ($context['querystring_board_limits'] === ';start=%1$d') |
||||||
| 386 | { |
||||||
| 387 | $context['querystring_board_limits'] = ''; |
||||||
| 388 | } |
||||||
| 389 | else |
||||||
| 390 | { |
||||||
| 391 | $context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $this->_req->query->start); |
||||||
| 392 | } |
||||||
| 393 | } |
||||||
| 394 | else |
||||||
| 395 | { |
||||||
| 396 | $context['links'] += [ |
||||||
| 397 | 'first' => $this->_req->query->start >= $context['topics_per_page'] ? $scripturl . '?action=' . $this->_action . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'] : '', |
||||||
| 398 | 'last' => $this->_req->query->start + $context['topics_per_page'] < $this->_num_topics ? $scripturl . '?action=' . $this->_action . ($context['showing_all_topics'] ? ';all' : '') . sprintf($context['querystring_board_limits'], floor(($this->_num_topics - 1) / $context['topics_per_page']) * $context['topics_per_page']) . $context['querystring_sort_limits'] : '', |
||||||
| 399 | 'up' => $scripturl, |
||||||
| 400 | ]; |
||||||
| 401 | $context['topics'] = $this->_grabber->getUnreads(null, $this->_req->query->start, $context['topics_per_page'], $settings['avatars_on_indexes']); |
||||||
| 402 | |||||||
| 403 | if ($context['topics'] === false) |
||||||
| 404 | { |
||||||
| 405 | $context['topics'] = []; |
||||||
| 406 | |||||||
| 407 | if ($context['querystring_board_limits'] === ';start=%1$d') |
||||||
| 408 | { |
||||||
| 409 | $context['querystring_board_limits'] = ''; |
||||||
| 410 | } |
||||||
| 411 | else |
||||||
| 412 | { |
||||||
| 413 | $context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $this->_req->query->start); |
||||||
| 414 | } |
||||||
| 415 | |||||||
| 416 | return; |
||||||
| 417 | } |
||||||
| 418 | } |
||||||
| 419 | |||||||
| 420 | $this->_exiting_unread(); |
||||||
| 421 | } |
||||||
| 422 | |||||||
| 423 | /** |
||||||
| 424 | * Some common things done at the end of each action. |
||||||
| 425 | */ |
||||||
| 426 | private function _exiting_unread(): void |
||||||
| 427 | { |
||||||
| 428 | global $scripturl, $context, $settings, $modSettings, $txt; |
||||||
| 429 | |||||||
| 430 | $topic_ids = array_keys($context['topics']); |
||||||
| 431 | |||||||
| 432 | if ($this->_is_topics && !empty($modSettings['enableParticipation']) && !empty($topic_ids)) |
||||||
| 433 | { |
||||||
| 434 | require_once(SUBSDIR . '/MessageIndex.subs.php'); |
||||||
| 435 | $topics_participated_in = topicsParticipation($this->user->id, $topic_ids); |
||||||
|
0 ignored issues
–
show
The property
id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
|
|||||||
| 436 | |||||||
| 437 | foreach ($topics_participated_in as $topic) |
||||||
| 438 | { |
||||||
| 439 | if (empty($context['topics'][$topic['id_topic']]['is_posted_in'])) |
||||||
| 440 | { |
||||||
| 441 | $context['topics'][$topic['id_topic']]['is_posted_in'] = true; |
||||||
| 442 | $context['topics'][$topic['id_topic']]['class'] = 'my_' . $context['topics'][$topic['id_topic']]['class']; |
||||||
| 443 | } |
||||||
| 444 | } |
||||||
| 445 | } |
||||||
| 446 | |||||||
| 447 | $all = $context['showing_all_topics'] ? ';all' : ''; |
||||||
| 448 | |||||||
| 449 | // Make sure the starting place makes sense and construct the page index. |
||||||
| 450 | $context['page_index'] = constructPageIndex('{scripturl}?action=' . $this->_action . $all . $context['querystring_board_limits'] . $context['querystring_sort_limits'], $this->_req->query->start, $this->_num_topics, $context['topics_per_page'], true); |
||||||
| 451 | $context['current_page'] = (int) $this->_req->query->start / $context['topics_per_page']; |
||||||
| 452 | |||||||
| 453 | if ($context['showing_all_topics']) |
||||||
| 454 | { |
||||||
| 455 | $context['breadcrumbs'][] = [ |
||||||
| 456 | 'url' => $scripturl . '?action=' . $this->_action . ';all' . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'], |
||||||
| 457 | 'name' => $txt['unread_topics_all'] |
||||||
| 458 | ]; |
||||||
| 459 | |||||||
| 460 | $txt['unread_topics_visit_none'] = str_replace('{unread_all_url}', $scripturl . '?action=unread;all', $txt['unread_topics_visit_none']); |
||||||
| 461 | } |
||||||
| 462 | else |
||||||
| 463 | { |
||||||
| 464 | $txt['unread_topics_visit_none'] = str_replace('{unread_all_url}', $scripturl . '?action=unread;all' . sprintf($context['querystring_board_limits'], 0) . $context['querystring_sort_limits'], $txt['unread_topics_visit_none']); |
||||||
| 465 | } |
||||||
| 466 | |||||||
| 467 | $context['links'] += [ |
||||||
| 468 | 'prev' => $this->_req->query->start >= $context['topics_per_page'] ? $scripturl . '?action=' . $this->_action . $all . sprintf($context['querystring_board_limits'], $this->_req->query->start - $context['topics_per_page']) . $context['querystring_sort_limits'] : '', |
||||||
| 469 | 'next' => $this->_req->query->start + $context['topics_per_page'] < $this->_num_topics ? $scripturl . '?action=' . $this->_action . $all . sprintf($context['querystring_board_limits'], $this->_req->query->start + $context['topics_per_page']) . $context['querystring_sort_limits'] : '', |
||||||
| 470 | ]; |
||||||
| 471 | |||||||
| 472 | $context['querystring_board_limits'] = sprintf($context['querystring_board_limits'], $this->_req->query->start); |
||||||
| 473 | $topics_to_mark = implode('-', $topic_ids); |
||||||
| 474 | |||||||
| 475 | if ($settings['show_mark_read']) |
||||||
| 476 | { |
||||||
| 477 | $context['recent_buttons'] = $this->_buttonsArray($topics_to_mark); |
||||||
| 478 | } |
||||||
| 479 | |||||||
| 480 | $context['querystring_board_limits'] = 'action=' . $this->_action . $all . $context['querystring_board_limits']; |
||||||
| 481 | |||||||
| 482 | // Allow help desks and bug trackers and what not to add their own unread |
||||||
| 483 | // data (just add a template_layer to show custom stuff in the template!) |
||||||
| 484 | call_integration_hook('integrate_unread_list'); |
||||||
| 485 | } |
||||||
| 486 | |||||||
| 487 | /** |
||||||
| 488 | * Build the recent button array. |
||||||
| 489 | * |
||||||
| 490 | * @param string $topics_to_mark - An array of topic ids properly formatted |
||||||
| 491 | * into a string to use in an URL |
||||||
| 492 | * |
||||||
| 493 | * @return array |
||||||
| 494 | */ |
||||||
| 495 | private function _buttonsArray($topics_to_mark): array |
||||||
| 496 | { |
||||||
| 497 | global $context, $scripturl, $txt; |
||||||
| 498 | |||||||
| 499 | if ($this->_is_topics) |
||||||
| 500 | { |
||||||
| 501 | theme()->addJavascriptVar([ |
||||||
| 502 | 'txt_mark_as_read_confirm' => $txt['mark_these_as_read_confirm'] |
||||||
| 503 | ], true); |
||||||
| 504 | |||||||
| 505 | $recent_buttons = [ |
||||||
| 506 | 'markread' => [ |
||||||
| 507 | 'text' => empty($context['no_board_limits']) ? 'mark_read_short' : 'mark_as_read', |
||||||
| 508 | 'lang' => true, |
||||||
| 509 | 'custom' => 'onclick="return markunreadButton(this);"', |
||||||
| 510 | 'url' => $scripturl . '?action=markasread;sa=' . (empty($context['no_board_limits']) ? 'board' . $context['querystring_board_limits'] : 'all') . ';' . $context['session_var'] . '=' . $context['session_id'], |
||||||
| 511 | ], |
||||||
| 512 | ]; |
||||||
| 513 | |||||||
| 514 | if ($context['showCheckboxes']) |
||||||
| 515 | { |
||||||
| 516 | $recent_buttons['markselectread'] = [ |
||||||
| 517 | 'text' => 'quick_mod_markread', |
||||||
| 518 | 'lang' => true, |
||||||
| 519 | 'url' => 'javascript:document.quickModForm.submit();', |
||||||
| 520 | ]; |
||||||
| 521 | } |
||||||
| 522 | |||||||
| 523 | if (!empty($context['topics']) && !$context['showing_all_topics']) |
||||||
| 524 | { |
||||||
| 525 | $recent_buttons['readall'] = ['text' => 'unread_topics_all', |
||||||
| 526 | 'lang' => true, |
||||||
| 527 | 'url' => $scripturl . '?action=unread;all' . $context['querystring_board_limits'], |
||||||
| 528 | 'active' => true]; |
||||||
| 529 | } |
||||||
| 530 | } |
||||||
| 531 | elseif (!$this->_is_topics && isset($topics_to_mark)) |
||||||
| 532 | { |
||||||
| 533 | theme()->addJavascriptVar([ |
||||||
| 534 | 'txt_mark_as_read_confirm' => $txt['mark_these_as_read_confirm'] |
||||||
| 535 | ], true); |
||||||
| 536 | |||||||
| 537 | $recent_buttons = [ |
||||||
| 538 | 'markread' => [ |
||||||
| 539 | 'text' => 'mark_these_as_read', |
||||||
| 540 | 'lang' => true, |
||||||
| 541 | 'url' => $scripturl . '?action=markasread;sa=unreadreplies;topics=' . $topics_to_mark . ';' . $context['session_var'] . '=' . $context['session_id'], |
||||||
| 542 | ], |
||||||
| 543 | ]; |
||||||
| 544 | |||||||
| 545 | if ($context['showCheckboxes']) |
||||||
| 546 | { |
||||||
| 547 | $recent_buttons['markselectread'] = [ |
||||||
| 548 | 'text' => 'quick_mod_markread', |
||||||
| 549 | 'lang' => true, |
||||||
| 550 | 'url' => 'javascript:document.quickModForm.submit();', |
||||||
| 551 | ]; |
||||||
| 552 | } |
||||||
| 553 | } |
||||||
| 554 | |||||||
| 555 | // Allow mods to add additional buttons here |
||||||
| 556 | call_integration_hook('integrate_recent_buttons', [&$recent_buttons]); |
||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
| 557 | |||||||
| 558 | return $recent_buttons; |
||||||
| 559 | } |
||||||
| 560 | } |
||||||
| 561 |
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..