1 | <?php |
||
2 | |||
3 | /** |
||
4 | * This file is mainly concerned with minor tasks relating to boards, such as |
||
5 | * marking them read, collapsing categories, or quick moderation. |
||
6 | * |
||
7 | * Simple Machines Forum (SMF) |
||
8 | * |
||
9 | * @package SMF |
||
10 | * @author Simple Machines https://www.simplemachines.org |
||
11 | * @copyright 2022 Simple Machines and individual contributors |
||
12 | * @license https://www.simplemachines.org/about/smf/license.php BSD |
||
13 | * |
||
14 | * @version 2.1.0 |
||
15 | */ |
||
16 | |||
17 | if (!defined('SMF')) |
||
18 | die('No direct access...'); |
||
19 | |||
20 | /** |
||
21 | * Mark a board or multiple boards read. |
||
22 | * |
||
23 | * @param int|array $boards The ID of a single board or an array of boards |
||
24 | * @param bool $unread Whether we're marking them as unread |
||
25 | */ |
||
26 | function markBoardsRead($boards, $unread = false) |
||
27 | { |
||
28 | global $user_info, $modSettings, $smcFunc; |
||
29 | |||
30 | // Force $boards to be an array. |
||
31 | if (!is_array($boards)) |
||
32 | $boards = array($boards); |
||
33 | else |
||
34 | $boards = array_unique($boards); |
||
35 | |||
36 | // No boards, nothing to mark as read. |
||
37 | if (empty($boards)) |
||
38 | return; |
||
39 | |||
40 | // Allow the user to mark a board as unread. |
||
41 | if ($unread) |
||
42 | { |
||
43 | // Clear out all the places where this lovely info is stored. |
||
44 | // @todo Maybe not log_mark_read? |
||
45 | $smcFunc['db_query']('', ' |
||
46 | DELETE FROM {db_prefix}log_mark_read |
||
47 | WHERE id_board IN ({array_int:board_list}) |
||
48 | AND id_member = {int:current_member}', |
||
49 | array( |
||
50 | 'current_member' => $user_info['id'], |
||
51 | 'board_list' => $boards, |
||
52 | ) |
||
53 | ); |
||
54 | $smcFunc['db_query']('', ' |
||
55 | DELETE FROM {db_prefix}log_boards |
||
56 | WHERE id_board IN ({array_int:board_list}) |
||
57 | AND id_member = {int:current_member}', |
||
58 | array( |
||
59 | 'current_member' => $user_info['id'], |
||
60 | 'board_list' => $boards, |
||
61 | ) |
||
62 | ); |
||
63 | } |
||
64 | // Otherwise mark the board as read. |
||
65 | else |
||
66 | { |
||
67 | $markRead = array(); |
||
68 | foreach ($boards as $board) |
||
69 | $markRead[] = array($modSettings['maxMsgID'], $user_info['id'], $board); |
||
70 | |||
71 | // Update log_mark_read and log_boards. |
||
72 | $smcFunc['db_insert']('replace', |
||
73 | '{db_prefix}log_mark_read', |
||
74 | array('id_msg' => 'int', 'id_member' => 'int', 'id_board' => 'int'), |
||
75 | $markRead, |
||
76 | array('id_board', 'id_member') |
||
77 | ); |
||
78 | |||
79 | $smcFunc['db_insert']('replace', |
||
80 | '{db_prefix}log_boards', |
||
81 | array('id_msg' => 'int', 'id_member' => 'int', 'id_board' => 'int'), |
||
82 | $markRead, |
||
83 | array('id_board', 'id_member') |
||
84 | ); |
||
85 | } |
||
86 | |||
87 | // Get rid of useless log_topics data, because log_mark_read is better for it - even if marking unread - I think so... |
||
88 | // @todo look at this... |
||
89 | // The call to markBoardsRead() in Display() used to be simply |
||
90 | // marking log_boards (the previous query only) |
||
91 | $result = $smcFunc['db_query']('', ' |
||
92 | SELECT MIN(id_topic) |
||
93 | FROM {db_prefix}log_topics |
||
94 | WHERE id_member = {int:current_member}', |
||
95 | array( |
||
96 | 'current_member' => $user_info['id'], |
||
97 | ) |
||
98 | ); |
||
99 | list ($lowest_topic) = $smcFunc['db_fetch_row']($result); |
||
100 | $smcFunc['db_free_result']($result); |
||
101 | |||
102 | if (empty($lowest_topic)) |
||
103 | return; |
||
104 | |||
105 | // @todo SLOW This query seems to eat it sometimes. |
||
106 | $result = $smcFunc['db_query']('', ' |
||
107 | SELECT lt.id_topic |
||
108 | FROM {db_prefix}log_topics AS lt |
||
109 | INNER JOIN {db_prefix}topics AS t /*!40000 USE INDEX (PRIMARY) */ ON (t.id_topic = lt.id_topic |
||
110 | AND t.id_board IN ({array_int:board_list})) |
||
111 | WHERE lt.id_member = {int:current_member} |
||
112 | AND lt.id_topic >= {int:lowest_topic} |
||
113 | AND lt.unwatched != 1', |
||
114 | array( |
||
115 | 'current_member' => $user_info['id'], |
||
116 | 'board_list' => $boards, |
||
117 | 'lowest_topic' => $lowest_topic, |
||
118 | ) |
||
119 | ); |
||
120 | $topics = array(); |
||
121 | while ($row = $smcFunc['db_fetch_assoc']($result)) |
||
122 | $topics[] = $row['id_topic']; |
||
123 | $smcFunc['db_free_result']($result); |
||
124 | |||
125 | if (!empty($topics)) |
||
126 | $smcFunc['db_query']('', ' |
||
127 | DELETE FROM {db_prefix}log_topics |
||
128 | WHERE id_member = {int:current_member} |
||
129 | AND id_topic IN ({array_int:topic_list})', |
||
130 | array( |
||
131 | 'current_member' => $user_info['id'], |
||
132 | 'topic_list' => $topics, |
||
133 | ) |
||
134 | ); |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * Mark one or more boards as read. |
||
139 | */ |
||
140 | function MarkRead() |
||
141 | { |
||
142 | global $board, $topic, $user_info, $board_info, $modSettings, $smcFunc; |
||
143 | |||
144 | // No Guests allowed! |
||
145 | is_not_guest(); |
||
146 | |||
147 | checkSession('get'); |
||
148 | |||
149 | if (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'all') |
||
150 | { |
||
151 | // Find all the boards this user can see. |
||
152 | $result = $smcFunc['db_query']('', ' |
||
153 | SELECT b.id_board |
||
154 | FROM {db_prefix}boards AS b |
||
155 | WHERE {query_see_board}', |
||
156 | array( |
||
157 | ) |
||
158 | ); |
||
159 | $boards = array(); |
||
160 | while ($row = $smcFunc['db_fetch_assoc']($result)) |
||
161 | $boards[] = $row['id_board']; |
||
162 | $smcFunc['db_free_result']($result); |
||
163 | |||
164 | if (!empty($boards)) |
||
165 | markBoardsRead($boards, isset($_REQUEST['unread'])); |
||
166 | |||
167 | $_SESSION['id_msg_last_visit'] = $modSettings['maxMsgID']; |
||
168 | if (!empty($_SESSION['old_url']) && strpos($_SESSION['old_url'], 'action=unread') !== false) |
||
169 | redirectexit('action=unread'); |
||
170 | |||
171 | if (isset($_SESSION['topicseen_cache'])) |
||
172 | $_SESSION['topicseen_cache'] = array(); |
||
173 | |||
174 | redirectexit(); |
||
175 | } |
||
176 | elseif (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'unreadreplies') |
||
177 | { |
||
178 | // Make sure all the topics are integers! |
||
179 | $topics = array_map('intval', explode('-', $_REQUEST['topics'])); |
||
180 | |||
181 | $request = $smcFunc['db_query']('', ' |
||
182 | SELECT id_topic, unwatched |
||
183 | FROM {db_prefix}log_topics |
||
184 | WHERE id_topic IN ({array_int:selected_topics}) |
||
185 | AND id_member = {int:current_user}', |
||
186 | array( |
||
187 | 'selected_topics' => $topics, |
||
188 | 'current_user' => $user_info['id'], |
||
189 | ) |
||
190 | ); |
||
191 | $logged_topics = array(); |
||
192 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
193 | $logged_topics[$row['id_topic']] = $row['unwatched']; |
||
194 | $smcFunc['db_free_result']($request); |
||
195 | |||
196 | $markRead = array(); |
||
197 | foreach ($topics as $id_topic) |
||
198 | $markRead[] = array($modSettings['maxMsgID'], $user_info['id'], $id_topic, (isset($logged_topics[$topic]) ? $logged_topics[$topic] : 0)); |
||
199 | |||
200 | $smcFunc['db_insert']('replace', |
||
201 | '{db_prefix}log_topics', |
||
202 | array('id_msg' => 'int', 'id_member' => 'int', 'id_topic' => 'int', 'unwatched' => 'int'), |
||
203 | $markRead, |
||
204 | array('id_member', 'id_topic') |
||
205 | ); |
||
206 | |||
207 | if (isset($_SESSION['topicseen_cache'])) |
||
208 | $_SESSION['topicseen_cache'] = array(); |
||
209 | |||
210 | redirectexit('action=unreadreplies'); |
||
211 | } |
||
212 | |||
213 | // Special case: mark a topic unread! |
||
214 | elseif (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'topic') |
||
215 | { |
||
216 | // First, let's figure out what the latest message is. |
||
217 | $result = $smcFunc['db_query']('', ' |
||
218 | SELECT t.id_first_msg, t.id_last_msg, COALESCE(lt.unwatched, 0) as unwatched |
||
219 | FROM {db_prefix}topics as t |
||
220 | LEFT JOIN {db_prefix}log_topics as lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member}) |
||
221 | WHERE t.id_topic = {int:current_topic}', |
||
222 | array( |
||
223 | 'current_topic' => $topic, |
||
224 | 'current_member' => $user_info['id'], |
||
225 | ) |
||
226 | ); |
||
227 | $topicinfo = $smcFunc['db_fetch_assoc']($result); |
||
228 | $smcFunc['db_free_result']($result); |
||
229 | |||
230 | if (!empty($_GET['t'])) |
||
231 | { |
||
232 | // If they read the whole topic, go back to the beginning. |
||
233 | if ($_GET['t'] >= $topicinfo['id_last_msg']) |
||
234 | $earlyMsg = 0; |
||
235 | // If they want to mark the whole thing read, same. |
||
236 | elseif ($_GET['t'] <= $topicinfo['id_first_msg']) |
||
237 | $earlyMsg = 0; |
||
238 | // Otherwise, get the latest message before the named one. |
||
239 | else |
||
240 | { |
||
241 | $result = $smcFunc['db_query']('', ' |
||
242 | SELECT MAX(id_msg) |
||
243 | FROM {db_prefix}messages |
||
244 | WHERE id_topic = {int:current_topic} |
||
245 | AND id_msg >= {int:id_first_msg} |
||
246 | AND id_msg < {int:topic_msg_id}', |
||
247 | array( |
||
248 | 'current_topic' => $topic, |
||
249 | 'topic_msg_id' => (int) $_GET['t'], |
||
250 | 'id_first_msg' => $topicinfo['id_first_msg'], |
||
251 | ) |
||
252 | ); |
||
253 | list ($earlyMsg) = $smcFunc['db_fetch_row']($result); |
||
254 | $smcFunc['db_free_result']($result); |
||
255 | } |
||
256 | } |
||
257 | // Marking read from first page? That's the whole topic. |
||
258 | elseif ($_REQUEST['start'] == 0) |
||
259 | $earlyMsg = 0; |
||
260 | else |
||
261 | { |
||
262 | $result = $smcFunc['db_query']('', ' |
||
263 | SELECT id_msg |
||
264 | FROM {db_prefix}messages |
||
265 | WHERE id_topic = {int:current_topic} |
||
266 | ORDER BY id_msg |
||
267 | LIMIT {int:start}, 1', |
||
268 | array( |
||
269 | 'current_topic' => $topic, |
||
270 | 'start' => (int) $_REQUEST['start'], |
||
271 | ) |
||
272 | ); |
||
273 | list ($earlyMsg) = $smcFunc['db_fetch_row']($result); |
||
274 | $smcFunc['db_free_result']($result); |
||
275 | |||
276 | $earlyMsg--; |
||
277 | } |
||
278 | |||
279 | // Blam, unread! |
||
280 | $smcFunc['db_insert']('replace', |
||
281 | '{db_prefix}log_topics', |
||
282 | array('id_msg' => 'int', 'id_member' => 'int', 'id_topic' => 'int', 'unwatched' => 'int'), |
||
283 | array($earlyMsg, $user_info['id'], $topic, $topicinfo['unwatched']), |
||
284 | array('id_member', 'id_topic') |
||
285 | ); |
||
286 | |||
287 | redirectexit('board=' . $board . '.0'); |
||
288 | } |
||
289 | else |
||
290 | { |
||
291 | $categories = array(); |
||
292 | $boards = array(); |
||
293 | |||
294 | if (isset($_REQUEST['c'])) |
||
295 | { |
||
296 | $_REQUEST['c'] = explode(',', $_REQUEST['c']); |
||
297 | foreach ($_REQUEST['c'] as $c) |
||
298 | $categories[] = (int) $c; |
||
299 | } |
||
300 | if (isset($_REQUEST['boards'])) |
||
301 | { |
||
302 | $_REQUEST['boards'] = explode(',', $_REQUEST['boards']); |
||
303 | foreach ($_REQUEST['boards'] as $b) |
||
304 | $boards[] = (int) $b; |
||
305 | } |
||
306 | if (!empty($board)) |
||
307 | $boards[] = (int) $board; |
||
308 | |||
309 | if (isset($_REQUEST['children']) && !empty($boards)) |
||
310 | { |
||
311 | // They want to mark the entire tree starting with the boards specified |
||
312 | // The easiest thing is to just get all the boards they can see, but since we've specified the top of tree we ignore some of them |
||
313 | |||
314 | $request = $smcFunc['db_query']('', ' |
||
315 | SELECT b.id_board, b.id_parent |
||
316 | FROM {db_prefix}boards AS b |
||
317 | WHERE {query_see_board} |
||
318 | AND b.child_level > {int:no_parents} |
||
319 | AND b.id_board NOT IN ({array_int:board_list}) |
||
320 | ORDER BY child_level ASC', |
||
321 | array( |
||
322 | 'no_parents' => 0, |
||
323 | 'board_list' => $boards, |
||
324 | ) |
||
325 | ); |
||
326 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
327 | if (in_array($row['id_parent'], $boards)) |
||
328 | $boards[] = $row['id_board']; |
||
329 | |||
330 | $smcFunc['db_free_result']($request); |
||
331 | } |
||
332 | |||
333 | $clauses = array(); |
||
334 | $clauseParameters = array(); |
||
335 | if (!empty($categories)) |
||
336 | { |
||
337 | $clauses[] = 'id_cat IN ({array_int:category_list})'; |
||
338 | $clauseParameters['category_list'] = $categories; |
||
339 | } |
||
340 | if (!empty($boards)) |
||
341 | { |
||
342 | $clauses[] = 'id_board IN ({array_int:board_list})'; |
||
343 | $clauseParameters['board_list'] = $boards; |
||
344 | } |
||
345 | |||
346 | if (empty($clauses)) |
||
347 | redirectexit(); |
||
348 | |||
349 | $request = $smcFunc['db_query']('', ' |
||
350 | SELECT b.id_board |
||
351 | FROM {db_prefix}boards AS b |
||
352 | WHERE {query_see_board} |
||
353 | AND b.' . implode(' OR b.', $clauses), |
||
354 | array_merge($clauseParameters, array( |
||
355 | )) |
||
356 | ); |
||
357 | $boards = array(); |
||
358 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
359 | $boards[] = $row['id_board']; |
||
360 | $smcFunc['db_free_result']($request); |
||
361 | |||
362 | if (empty($boards)) |
||
363 | redirectexit(); |
||
364 | |||
365 | markBoardsRead($boards, isset($_REQUEST['unread'])); |
||
366 | |||
367 | foreach ($boards as $b) |
||
368 | { |
||
369 | if (isset($_SESSION['topicseen_cache'][$b])) |
||
370 | $_SESSION['topicseen_cache'][$b] = array(); |
||
371 | } |
||
372 | |||
373 | if (!isset($_REQUEST['unread'])) |
||
374 | { |
||
375 | // Find all the boards this user can see. |
||
376 | $result = $smcFunc['db_query']('', ' |
||
377 | SELECT b.id_board |
||
378 | FROM {db_prefix}boards AS b |
||
379 | WHERE b.id_parent IN ({array_int:parent_list}) |
||
380 | AND {query_see_board}', |
||
381 | array( |
||
382 | 'parent_list' => $boards, |
||
383 | ) |
||
384 | ); |
||
385 | if ($smcFunc['db_num_rows']($result) > 0) |
||
386 | { |
||
387 | $logBoardInserts = array(); |
||
388 | while ($row = $smcFunc['db_fetch_assoc']($result)) |
||
389 | $logBoardInserts[] = array($modSettings['maxMsgID'], $user_info['id'], $row['id_board']); |
||
390 | |||
391 | $smcFunc['db_insert']('replace', |
||
392 | '{db_prefix}log_boards', |
||
393 | array('id_msg' => 'int', 'id_member' => 'int', 'id_board' => 'int'), |
||
394 | $logBoardInserts, |
||
395 | array('id_member', 'id_board') |
||
396 | ); |
||
397 | } |
||
398 | $smcFunc['db_free_result']($result); |
||
399 | |||
400 | if (empty($board)) |
||
401 | redirectexit(); |
||
402 | else |
||
403 | redirectexit('board=' . $board . '.0'); |
||
404 | } |
||
405 | else |
||
406 | { |
||
407 | if (empty($board_info['parent'])) |
||
408 | redirectexit(); |
||
409 | else |
||
410 | redirectexit('board=' . $board_info['parent'] . '.0'); |
||
411 | } |
||
412 | } |
||
413 | } |
||
414 | |||
415 | /** |
||
416 | * Get the id_member associated with the specified message. |
||
417 | * |
||
418 | * @param int $messageID The ID of the message |
||
419 | * @return int The ID of the member associated with that post |
||
420 | */ |
||
421 | function getMsgMemberID($messageID) |
||
422 | { |
||
423 | global $smcFunc; |
||
424 | |||
425 | // Find the topic and make sure the member still exists. |
||
426 | $result = $smcFunc['db_query']('', ' |
||
427 | SELECT COALESCE(mem.id_member, 0) |
||
428 | FROM {db_prefix}messages AS m |
||
429 | LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
||
430 | WHERE m.id_msg = {int:selected_message} |
||
431 | LIMIT 1', |
||
432 | array( |
||
433 | 'selected_message' => (int) $messageID, |
||
434 | ) |
||
435 | ); |
||
436 | if ($smcFunc['db_num_rows']($result) > 0) |
||
437 | list ($memberID) = $smcFunc['db_fetch_row']($result); |
||
438 | // The message doesn't even exist. |
||
439 | else |
||
440 | $memberID = 0; |
||
441 | |||
442 | $smcFunc['db_free_result']($result); |
||
443 | |||
444 | return (int) $memberID; |
||
445 | } |
||
446 | |||
447 | /** |
||
448 | * Modify the settings and position of a board. |
||
449 | * Used by ManageBoards.php to change the settings of a board. |
||
450 | * |
||
451 | * @param int $board_id The ID of the board |
||
452 | * @param array &$boardOptions An array of options related to the board |
||
453 | */ |
||
454 | function modifyBoard($board_id, &$boardOptions) |
||
455 | { |
||
456 | global $cat_tree, $boards, $smcFunc, $context, $txt; |
||
457 | |||
458 | // Get some basic information about all boards and categories. |
||
459 | getBoardTree(); |
||
460 | |||
461 | // Make sure given boards and categories exist. |
||
462 | if (!isset($boards[$board_id]) || (isset($boardOptions['target_board']) && !isset($boards[$boardOptions['target_board']])) || (isset($boardOptions['target_category']) && !isset($cat_tree[$boardOptions['target_category']]))) |
||
463 | fatal_lang_error('no_board'); |
||
464 | |||
465 | $id = $board_id; |
||
466 | call_integration_hook('integrate_pre_modify_board', array($id, &$boardOptions)); |
||
467 | |||
468 | // All things that will be updated in the database will be in $boardUpdates. |
||
469 | $boardUpdates = array(); |
||
470 | $boardUpdateParameters = array(); |
||
471 | |||
472 | // In case the board has to be moved |
||
473 | if (isset($boardOptions['move_to'])) |
||
474 | { |
||
475 | // Move the board to the top of a given category. |
||
476 | if ($boardOptions['move_to'] == 'top') |
||
477 | { |
||
478 | $id_cat = $boardOptions['target_category']; |
||
479 | $child_level = 0; |
||
480 | $id_parent = 0; |
||
481 | $after = $cat_tree[$id_cat]['last_board_order']; |
||
482 | } |
||
483 | |||
484 | // Move the board to the bottom of a given category. |
||
485 | elseif ($boardOptions['move_to'] == 'bottom') |
||
486 | { |
||
487 | $id_cat = $boardOptions['target_category']; |
||
488 | $child_level = 0; |
||
489 | $id_parent = 0; |
||
490 | $after = 0; |
||
491 | foreach ($cat_tree[$id_cat]['children'] as $id_board => $dummy) |
||
492 | $after = max($after, $boards[$id_board]['order']); |
||
493 | } |
||
494 | |||
495 | // Make the board a child of a given board. |
||
496 | elseif ($boardOptions['move_to'] == 'child') |
||
497 | { |
||
498 | $id_cat = $boards[$boardOptions['target_board']]['category']; |
||
499 | $child_level = $boards[$boardOptions['target_board']]['level'] + 1; |
||
500 | $id_parent = $boardOptions['target_board']; |
||
501 | |||
502 | // People can be creative, in many ways... |
||
503 | if (isChildOf($id_parent, $board_id)) |
||
504 | fatal_lang_error('mboards_parent_own_child_error', false); |
||
505 | |||
506 | elseif ($id_parent == $board_id) |
||
507 | fatal_lang_error('mboards_board_own_child_error', false); |
||
508 | |||
509 | $after = $boards[$boardOptions['target_board']]['order']; |
||
510 | |||
511 | // Check if there are already children and (if so) get the max board order. |
||
512 | if (!empty($boards[$id_parent]['tree']['children']) && empty($boardOptions['move_first_child'])) |
||
513 | foreach ($boards[$id_parent]['tree']['children'] as $childBoard_id => $dummy) |
||
514 | $after = max($after, $boards[$childBoard_id]['order']); |
||
515 | } |
||
516 | |||
517 | // Place a board before or after another board, on the same child level. |
||
518 | elseif (in_array($boardOptions['move_to'], array('before', 'after'))) |
||
519 | { |
||
520 | $id_cat = $boards[$boardOptions['target_board']]['category']; |
||
521 | $child_level = $boards[$boardOptions['target_board']]['level']; |
||
522 | $id_parent = $boards[$boardOptions['target_board']]['parent']; |
||
523 | $after = $boards[$boardOptions['target_board']]['order'] - ($boardOptions['move_to'] == 'before' ? 1 : 0); |
||
524 | } |
||
525 | |||
526 | // Oops...? |
||
527 | else |
||
528 | { |
||
529 | loadLanguage('Errors'); |
||
530 | trigger_error(sprintf($txt['modify_board_incorrect_move_to'], $boardOptions['move_to']), E_USER_ERROR); |
||
531 | } |
||
532 | |||
533 | // Get a list of children of this board. |
||
534 | $childList = array(); |
||
535 | recursiveBoards($childList, $boards[$board_id]['tree']); |
||
536 | |||
537 | // See if there are changes that affect children. |
||
538 | $childUpdates = array(); |
||
539 | $levelDiff = $child_level - $boards[$board_id]['level']; |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
![]() |
|||
540 | |||
541 | if ($levelDiff != 0) |
||
542 | $childUpdates[] = 'child_level = child_level ' . ($levelDiff > 0 ? '+ ' : '') . '{int:level_diff}'; |
||
543 | |||
544 | if ($id_cat != $boards[$board_id]['category']) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
545 | $childUpdates[] = 'id_cat = {int:category}'; |
||
546 | |||
547 | // Fix the children of this board. |
||
548 | if (!empty($childList) && !empty($childUpdates)) |
||
549 | $smcFunc['db_query']('', ' |
||
550 | UPDATE {db_prefix}boards |
||
551 | SET ' . implode(', |
||
552 | ', $childUpdates) . ' |
||
553 | WHERE id_board IN ({array_int:board_list})', |
||
554 | array( |
||
555 | 'board_list' => $childList, |
||
556 | 'category' => $id_cat, |
||
557 | 'level_diff' => $levelDiff, |
||
558 | ) |
||
559 | ); |
||
560 | |||
561 | // Make some room for this spot. |
||
562 | $smcFunc['db_query']('', ' |
||
563 | UPDATE {db_prefix}boards |
||
564 | SET board_order = board_order + {int:new_order} |
||
565 | WHERE board_order > {int:insert_after} |
||
566 | AND id_board != {int:selected_board}', |
||
567 | array( |
||
568 | 'insert_after' => $after, |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
569 | 'selected_board' => $board_id, |
||
570 | 'new_order' => 1 + count($childList), |
||
571 | ) |
||
572 | ); |
||
573 | |||
574 | $boardUpdates[] = 'id_cat = {int:id_cat}'; |
||
575 | $boardUpdates[] = 'id_parent = {int:id_parent}'; |
||
576 | $boardUpdates[] = 'child_level = {int:child_level}'; |
||
577 | $boardUpdates[] = 'board_order = {int:board_order}'; |
||
578 | $boardUpdateParameters += array( |
||
579 | 'id_cat' => $id_cat, |
||
580 | 'id_parent' => $id_parent, |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
581 | 'child_level' => $child_level, |
||
582 | 'board_order' => $after + 1, |
||
583 | ); |
||
584 | } |
||
585 | |||
586 | // This setting is a little twisted in the database... |
||
587 | if (isset($boardOptions['posts_count'])) |
||
588 | { |
||
589 | $boardUpdates[] = 'count_posts = {int:count_posts}'; |
||
590 | $boardUpdateParameters['count_posts'] = $boardOptions['posts_count'] ? 0 : 1; |
||
591 | } |
||
592 | |||
593 | // Set the theme for this board. |
||
594 | if (isset($boardOptions['board_theme'])) |
||
595 | { |
||
596 | $boardUpdates[] = 'id_theme = {int:id_theme}'; |
||
597 | $boardUpdateParameters['id_theme'] = (int) $boardOptions['board_theme']; |
||
598 | } |
||
599 | |||
600 | // Should the board theme override the user preferred theme? |
||
601 | if (isset($boardOptions['override_theme'])) |
||
602 | { |
||
603 | $boardUpdates[] = 'override_theme = {int:override_theme}'; |
||
604 | $boardUpdateParameters['override_theme'] = $boardOptions['override_theme'] ? 1 : 0; |
||
605 | } |
||
606 | |||
607 | // Who's allowed to access this board. |
||
608 | if (isset($boardOptions['access_groups'])) |
||
609 | { |
||
610 | $boardUpdates[] = 'member_groups = {string:member_groups}'; |
||
611 | $boardUpdateParameters['member_groups'] = implode(',', $boardOptions['access_groups']); |
||
612 | } |
||
613 | |||
614 | // And who isn't. |
||
615 | if (isset($boardOptions['deny_groups'])) |
||
616 | { |
||
617 | $boardUpdates[] = 'deny_member_groups = {string:deny_groups}'; |
||
618 | $boardUpdateParameters['deny_groups'] = implode(',', $boardOptions['deny_groups']); |
||
619 | } |
||
620 | |||
621 | if (isset($boardOptions['board_name'])) |
||
622 | { |
||
623 | $boardUpdates[] = 'name = {string:board_name}'; |
||
624 | $boardUpdateParameters['board_name'] = $boardOptions['board_name']; |
||
625 | } |
||
626 | |||
627 | if (isset($boardOptions['board_description'])) |
||
628 | { |
||
629 | $boardUpdates[] = 'description = {string:board_description}'; |
||
630 | $boardUpdateParameters['board_description'] = $boardOptions['board_description']; |
||
631 | } |
||
632 | |||
633 | if (isset($boardOptions['profile'])) |
||
634 | { |
||
635 | $boardUpdates[] = 'id_profile = {int:profile}'; |
||
636 | $boardUpdateParameters['profile'] = (int) $boardOptions['profile']; |
||
637 | } |
||
638 | |||
639 | if (isset($boardOptions['redirect'])) |
||
640 | { |
||
641 | $boardUpdates[] = 'redirect = {string:redirect}'; |
||
642 | $boardUpdateParameters['redirect'] = $boardOptions['redirect']; |
||
643 | } |
||
644 | |||
645 | if (isset($boardOptions['num_posts'])) |
||
646 | { |
||
647 | $boardUpdates[] = 'num_posts = {int:num_posts}'; |
||
648 | $boardUpdateParameters['num_posts'] = (int) $boardOptions['num_posts']; |
||
649 | } |
||
650 | |||
651 | $id = $board_id; |
||
652 | call_integration_hook('integrate_modify_board', array($id, $boardOptions, &$boardUpdates, &$boardUpdateParameters)); |
||
653 | |||
654 | // Do the updates (if any). |
||
655 | if (!empty($boardUpdates)) |
||
656 | $smcFunc['db_query']('', ' |
||
657 | UPDATE {db_prefix}boards |
||
658 | SET |
||
659 | ' . implode(', |
||
660 | ', $boardUpdates) . ' |
||
661 | WHERE id_board = {int:selected_board}', |
||
662 | array_merge($boardUpdateParameters, array( |
||
663 | 'selected_board' => $board_id, |
||
664 | )) |
||
665 | ); |
||
666 | |||
667 | // Before we add new access_groups or deny_groups, remove all of the old entries |
||
668 | $smcFunc['db_query']('', ' |
||
669 | DELETE FROM {db_prefix}board_permissions_view |
||
670 | WHERE id_board = {int:selected_board}', |
||
671 | array( |
||
672 | 'selected_board' => $board_id, |
||
673 | ) |
||
674 | ); |
||
675 | |||
676 | // Do permission sync |
||
677 | if (!empty($boardOptions['deny_groups'])) |
||
678 | { |
||
679 | $insert = array(); |
||
680 | foreach ($boardOptions['deny_groups'] as $value) |
||
681 | $insert[] = array($value, $board_id, 1); |
||
682 | |||
683 | $smcFunc['db_insert']('insert', |
||
684 | '{db_prefix}board_permissions_view', |
||
685 | array('id_group' => 'int', 'id_board' => 'int', 'deny' => 'int'), |
||
686 | $insert, |
||
687 | array('id_group', 'id_board', 'deny') |
||
688 | ); |
||
689 | } |
||
690 | |||
691 | if (!empty($boardOptions['access_groups'])) |
||
692 | { |
||
693 | $insert = array(); |
||
694 | foreach ($boardOptions['access_groups'] as $value) |
||
695 | $insert[] = array($value, $board_id, 0); |
||
696 | |||
697 | $smcFunc['db_insert']('insert', |
||
698 | '{db_prefix}board_permissions_view', |
||
699 | array('id_group' => 'int', 'id_board' => 'int', 'deny' => 'int'), |
||
700 | $insert, |
||
701 | array('id_group', 'id_board', 'deny') |
||
702 | ); |
||
703 | } |
||
704 | |||
705 | // Set moderators of this board. |
||
706 | if (isset($boardOptions['moderators']) || isset($boardOptions['moderator_string']) || isset($boardOptions['moderator_groups']) || isset($boardOptions['moderator_group_string'])) |
||
707 | { |
||
708 | // Reset current moderators for this board - if there are any! |
||
709 | $smcFunc['db_query']('', ' |
||
710 | DELETE FROM {db_prefix}moderators |
||
711 | WHERE id_board = {int:board_list}', |
||
712 | array( |
||
713 | 'board_list' => $board_id, |
||
714 | ) |
||
715 | ); |
||
716 | |||
717 | // Validate and get the IDs of the new moderators. |
||
718 | if (isset($boardOptions['moderator_string']) && trim($boardOptions['moderator_string']) != '') |
||
719 | { |
||
720 | // Divvy out the usernames, remove extra space. |
||
721 | $moderator_string = strtr($smcFunc['htmlspecialchars']($boardOptions['moderator_string'], ENT_QUOTES), array('"' => '"')); |
||
722 | preg_match_all('~"([^"]+)"~', $moderator_string, $matches); |
||
723 | $moderators = array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $moderator_string))); |
||
724 | for ($k = 0, $n = count($moderators); $k < $n; $k++) |
||
725 | { |
||
726 | $moderators[$k] = trim($moderators[$k]); |
||
727 | |||
728 | if (strlen($moderators[$k]) == 0) |
||
729 | unset($moderators[$k]); |
||
730 | } |
||
731 | |||
732 | // Find all the id_member's for the member_name's in the list. |
||
733 | if (empty($boardOptions['moderators'])) |
||
734 | $boardOptions['moderators'] = array(); |
||
735 | if (!empty($moderators)) |
||
736 | { |
||
737 | $request = $smcFunc['db_query']('', ' |
||
738 | SELECT id_member |
||
739 | FROM {db_prefix}members |
||
740 | WHERE member_name IN ({array_string:moderator_list}) OR real_name IN ({array_string:moderator_list}) |
||
741 | LIMIT {int:limit}', |
||
742 | array( |
||
743 | 'moderator_list' => $moderators, |
||
744 | 'limit' => count($moderators), |
||
745 | ) |
||
746 | ); |
||
747 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
748 | $boardOptions['moderators'][] = $row['id_member']; |
||
749 | $smcFunc['db_free_result']($request); |
||
750 | } |
||
751 | } |
||
752 | |||
753 | // Add the moderators to the board. |
||
754 | if (!empty($boardOptions['moderators'])) |
||
755 | { |
||
756 | $inserts = array(); |
||
757 | foreach ($boardOptions['moderators'] as $moderator) |
||
758 | $inserts[] = array($board_id, $moderator); |
||
759 | |||
760 | $smcFunc['db_insert']('insert', |
||
761 | '{db_prefix}moderators', |
||
762 | array('id_board' => 'int', 'id_member' => 'int'), |
||
763 | $inserts, |
||
764 | array('id_board', 'id_member') |
||
765 | ); |
||
766 | } |
||
767 | |||
768 | // Reset current moderator groups for this board - if there are any! |
||
769 | $smcFunc['db_query']('', ' |
||
770 | DELETE FROM {db_prefix}moderator_groups |
||
771 | WHERE id_board = {int:board_list}', |
||
772 | array( |
||
773 | 'board_list' => $board_id, |
||
774 | ) |
||
775 | ); |
||
776 | |||
777 | // Validate and get the IDs of the new moderator groups. |
||
778 | if (isset($boardOptions['moderator_group_string']) && trim($boardOptions['moderator_group_string']) != '') |
||
779 | { |
||
780 | // Divvy out the group names, remove extra space. |
||
781 | $moderator_group_string = strtr($smcFunc['htmlspecialchars']($boardOptions['moderator_group_string'], ENT_QUOTES), array('"' => '"')); |
||
782 | preg_match_all('~"([^"]+)"~', $moderator_group_string, $matches); |
||
783 | $moderator_groups = array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $moderator_group_string))); |
||
784 | for ($k = 0, $n = count($moderator_groups); $k < $n; $k++) |
||
785 | { |
||
786 | $moderator_groups[$k] = trim($moderator_groups[$k]); |
||
787 | |||
788 | if (strlen($moderator_groups[$k]) == 0) |
||
789 | unset($moderator_groups[$k]); |
||
790 | } |
||
791 | |||
792 | /* Find all the id_group's for all the group names in the list |
||
793 | But skip any invalid ones (invisible/post groups/Administrator/Moderator) */ |
||
794 | if (empty($boardOptions['moderator_groups'])) |
||
795 | $boardOptions['moderator_groups'] = array(); |
||
796 | if (!empty($moderator_groups)) |
||
797 | { |
||
798 | $request = $smcFunc['db_query']('', ' |
||
799 | SELECT id_group |
||
800 | FROM {db_prefix}membergroups |
||
801 | WHERE group_name IN ({array_string:moderator_group_list}) |
||
802 | AND hidden = {int:visible} |
||
803 | AND min_posts = {int:negative_one} |
||
804 | AND id_group NOT IN ({array_int:invalid_groups}) |
||
805 | LIMIT {int:limit}', |
||
806 | array( |
||
807 | 'visible' => 0, |
||
808 | 'negative_one' => -1, |
||
809 | 'invalid_groups' => array(1, 3), |
||
810 | 'moderator_group_list' => $moderator_groups, |
||
811 | 'limit' => count($moderator_groups), |
||
812 | ) |
||
813 | ); |
||
814 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
815 | { |
||
816 | $boardOptions['moderator_groups'][] = $row['id_group']; |
||
817 | } |
||
818 | $smcFunc['db_free_result']($request); |
||
819 | } |
||
820 | } |
||
821 | |||
822 | // Add the moderator groups to the board. |
||
823 | if (!empty($boardOptions['moderator_groups'])) |
||
824 | { |
||
825 | $inserts = array(); |
||
826 | foreach ($boardOptions['moderator_groups'] as $moderator_group) |
||
827 | $inserts[] = array($board_id, $moderator_group); |
||
828 | |||
829 | $smcFunc['db_insert']('insert', |
||
830 | '{db_prefix}moderator_groups', |
||
831 | array('id_board' => 'int', 'id_group' => 'int'), |
||
832 | $inserts, |
||
833 | array('id_board', 'id_group') |
||
834 | ); |
||
835 | } |
||
836 | |||
837 | // Note that caches can now be wrong! |
||
838 | updateSettings(array('settings_updated' => time())); |
||
839 | } |
||
840 | |||
841 | if (isset($boardOptions['move_to'])) |
||
842 | reorderBoards(); |
||
843 | |||
844 | $parsed_boards_cat_id = isset($id_cat) ? $id_cat : $boardOptions['old_id_cat']; |
||
845 | $already_parsed_boards = getBoardsParsedDescription($parsed_boards_cat_id); |
||
846 | |||
847 | if (isset($boardOptions['board_description'])) |
||
848 | $already_parsed_boards[$board_id] = parse_bbc( |
||
849 | $boardOptions['board_description'], |
||
850 | false, |
||
851 | |||
852 | '', |
||
853 | $context['description_allowed_tags']); |
||
854 | |||
855 | clean_cache('data'); |
||
856 | |||
857 | cache_put_data('parsed_boards_descriptions_'. $parsed_boards_cat_id, $already_parsed_boards, 864000); |
||
858 | |||
859 | if (empty($boardOptions['dont_log'])) |
||
860 | logAction('edit_board', array('board' => $board_id), 'admin'); |
||
861 | } |
||
862 | |||
863 | /** |
||
864 | * Create a new board and set its properties and position. |
||
865 | * Allows (almost) the same options as the modifyBoard() function. |
||
866 | * With the option inherit_permissions set, the parent board permissions |
||
867 | * will be inherited. |
||
868 | * |
||
869 | * @param array $boardOptions An array of information for the new board |
||
870 | * @return int The ID of the new board |
||
871 | */ |
||
872 | function createBoard($boardOptions) |
||
873 | { |
||
874 | global $boards, $smcFunc, $txt; |
||
875 | |||
876 | // Trigger an error if one of the required values is not set. |
||
877 | if (!isset($boardOptions['board_name']) || trim($boardOptions['board_name']) == '' || !isset($boardOptions['move_to']) || !isset($boardOptions['target_category'])) |
||
878 | { |
||
879 | loadLanguage('Errors'); |
||
880 | trigger_error($txt['create_board_missing_options'], E_USER_ERROR); |
||
881 | } |
||
882 | |||
883 | if (in_array($boardOptions['move_to'], array('child', 'before', 'after')) && !isset($boardOptions['target_board'])) |
||
884 | { |
||
885 | loadLanguage('Errors'); |
||
886 | trigger_error($txt['move_board_no_target'], E_USER_ERROR); |
||
887 | } |
||
888 | |||
889 | // Set every optional value to its default value. |
||
890 | $boardOptions += array( |
||
891 | 'posts_count' => true, |
||
892 | 'override_theme' => false, |
||
893 | 'board_theme' => 0, |
||
894 | 'access_groups' => array(), |
||
895 | 'board_description' => '', |
||
896 | 'profile' => 1, |
||
897 | 'moderators' => '', |
||
898 | 'inherit_permissions' => true, |
||
899 | 'dont_log' => true, |
||
900 | ); |
||
901 | |||
902 | $default_memgrps = '-1,0'; |
||
903 | |||
904 | $board_columns = array( |
||
905 | 'id_cat' => 'int', 'name' => 'string-255', 'description' => 'string', 'board_order' => 'int', |
||
906 | 'member_groups' => 'string', 'redirect' => 'string', |
||
907 | ); |
||
908 | $board_parameters = array( |
||
909 | $boardOptions['target_category'], $boardOptions['board_name'], '', 0, |
||
910 | $default_memgrps, '', |
||
911 | ); |
||
912 | |||
913 | call_integration_hook('integrate_create_board', array(&$boardOptions, &$board_columns, &$board_parameters)); |
||
914 | |||
915 | // Insert a board, the settings are dealt with later. |
||
916 | $board_id = $smcFunc['db_insert']('', |
||
917 | '{db_prefix}boards', |
||
918 | $board_columns, |
||
919 | $board_parameters, |
||
920 | array('id_board'), |
||
921 | 1 |
||
922 | ); |
||
923 | |||
924 | $insert = array(); |
||
925 | |||
926 | foreach (explode(',', $default_memgrps) as $value) |
||
927 | $insert[] = array($value, $board_id, 0); |
||
928 | |||
929 | $smcFunc['db_insert']('', |
||
930 | '{db_prefix}board_permissions_view', |
||
931 | array('id_group' => 'int', 'id_board' => 'int', 'deny' => 'int'), |
||
932 | $insert, |
||
933 | array('id_group', 'id_board', 'deny'), |
||
934 | 1 |
||
935 | ); |
||
936 | |||
937 | if (empty($board_id)) |
||
938 | return 0; |
||
939 | |||
940 | // Change the board according to the given specifications. |
||
941 | modifyBoard($board_id, $boardOptions); |
||
942 | |||
943 | // Do we want the parent permissions to be inherited? |
||
944 | if ($boardOptions['inherit_permissions']) |
||
945 | { |
||
946 | getBoardTree(); |
||
947 | |||
948 | if (!empty($boards[$board_id]['parent'])) |
||
949 | { |
||
950 | $request = $smcFunc['db_query']('', ' |
||
951 | SELECT id_profile |
||
952 | FROM {db_prefix}boards |
||
953 | WHERE id_board = {int:board_parent} |
||
954 | LIMIT 1', |
||
955 | array( |
||
956 | 'board_parent' => (int) $boards[$board_id]['parent'], |
||
957 | ) |
||
958 | ); |
||
959 | list ($boardOptions['profile']) = $smcFunc['db_fetch_row']($request); |
||
960 | $smcFunc['db_free_result']($request); |
||
961 | |||
962 | $smcFunc['db_query']('', ' |
||
963 | UPDATE {db_prefix}boards |
||
964 | SET id_profile = {int:new_profile} |
||
965 | WHERE id_board = {int:current_board}', |
||
966 | array( |
||
967 | 'new_profile' => $boardOptions['profile'], |
||
968 | 'current_board' => $board_id, |
||
969 | ) |
||
970 | ); |
||
971 | } |
||
972 | } |
||
973 | |||
974 | // Clean the data cache. |
||
975 | clean_cache('data'); |
||
976 | |||
977 | // Created it. |
||
978 | logAction('add_board', array('board' => $board_id), 'admin'); |
||
979 | |||
980 | // Here you are, a new board, ready to be spammed. |
||
981 | return $board_id; |
||
982 | } |
||
983 | |||
984 | /** |
||
985 | * Remove one or more boards. |
||
986 | * Allows to move the children of the board before deleting it |
||
987 | * if moveChildrenTo is set to null, the child boards will be deleted. |
||
988 | * Deletes: |
||
989 | * - all topics that are on the given boards; |
||
990 | * - all information that's associated with the given boards; |
||
991 | * updates the statistics to reflect the new situation. |
||
992 | * |
||
993 | * @param array $boards_to_remove The boards to remove |
||
994 | * @param int $moveChildrenTo The ID of the board to move the child boards to (null to remove the child boards, 0 to make them a top-level board) |
||
995 | */ |
||
996 | function deleteBoards($boards_to_remove, $moveChildrenTo = null) |
||
997 | { |
||
998 | global $sourcedir, $boards, $smcFunc; |
||
999 | |||
1000 | // No boards to delete? Return! |
||
1001 | if (empty($boards_to_remove)) |
||
1002 | return; |
||
1003 | |||
1004 | getBoardTree(); |
||
1005 | |||
1006 | call_integration_hook('integrate_delete_board', array($boards_to_remove, &$moveChildrenTo)); |
||
1007 | |||
1008 | // If $moveChildrenTo is set to null, include the children in the removal. |
||
1009 | if ($moveChildrenTo === null) |
||
1010 | { |
||
1011 | // Get a list of the child boards that will also be removed. |
||
1012 | $child_boards_to_remove = array(); |
||
1013 | foreach ($boards_to_remove as $board_to_remove) |
||
1014 | recursiveBoards($child_boards_to_remove, $boards[$board_to_remove]['tree']); |
||
1015 | |||
1016 | // Merge the children with their parents. |
||
1017 | if (!empty($child_boards_to_remove)) |
||
1018 | $boards_to_remove = array_unique(array_merge($boards_to_remove, $child_boards_to_remove)); |
||
1019 | } |
||
1020 | // Move the children to a safe home. |
||
1021 | else |
||
1022 | { |
||
1023 | foreach ($boards_to_remove as $id_board) |
||
1024 | { |
||
1025 | // @todo Separate category? |
||
1026 | if ($moveChildrenTo === 0) |
||
1027 | fixChildren($id_board, 0, 0); |
||
1028 | else |
||
1029 | fixChildren($id_board, $boards[$moveChildrenTo]['level'] + 1, $moveChildrenTo); |
||
1030 | } |
||
1031 | } |
||
1032 | |||
1033 | // Delete ALL topics in the selected boards (done first so topics can't be marooned.) |
||
1034 | $request = $smcFunc['db_query']('', ' |
||
1035 | SELECT id_topic |
||
1036 | FROM {db_prefix}topics |
||
1037 | WHERE id_board IN ({array_int:boards_to_remove})', |
||
1038 | array( |
||
1039 | 'boards_to_remove' => $boards_to_remove, |
||
1040 | ) |
||
1041 | ); |
||
1042 | $topics = array(); |
||
1043 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
1044 | $topics[] = $row['id_topic']; |
||
1045 | $smcFunc['db_free_result']($request); |
||
1046 | |||
1047 | require_once($sourcedir . '/RemoveTopic.php'); |
||
1048 | removeTopics($topics, false); |
||
1049 | |||
1050 | // Delete the board's logs. |
||
1051 | $smcFunc['db_query']('', ' |
||
1052 | DELETE FROM {db_prefix}log_mark_read |
||
1053 | WHERE id_board IN ({array_int:boards_to_remove})', |
||
1054 | array( |
||
1055 | 'boards_to_remove' => $boards_to_remove, |
||
1056 | ) |
||
1057 | ); |
||
1058 | $smcFunc['db_query']('', ' |
||
1059 | DELETE FROM {db_prefix}log_boards |
||
1060 | WHERE id_board IN ({array_int:boards_to_remove})', |
||
1061 | array( |
||
1062 | 'boards_to_remove' => $boards_to_remove, |
||
1063 | ) |
||
1064 | ); |
||
1065 | $smcFunc['db_query']('', ' |
||
1066 | DELETE FROM {db_prefix}log_notify |
||
1067 | WHERE id_board IN ({array_int:boards_to_remove})', |
||
1068 | array( |
||
1069 | 'boards_to_remove' => $boards_to_remove, |
||
1070 | ) |
||
1071 | ); |
||
1072 | |||
1073 | // Delete this board's moderators. |
||
1074 | $smcFunc['db_query']('', ' |
||
1075 | DELETE FROM {db_prefix}moderators |
||
1076 | WHERE id_board IN ({array_int:boards_to_remove})', |
||
1077 | array( |
||
1078 | 'boards_to_remove' => $boards_to_remove, |
||
1079 | ) |
||
1080 | ); |
||
1081 | |||
1082 | // Delete this board's moderator groups. |
||
1083 | $smcFunc['db_query']('', ' |
||
1084 | DELETE FROM {db_prefix}moderator_groups |
||
1085 | WHERE id_board IN ({array_int:boards_to_remove})', |
||
1086 | array( |
||
1087 | 'boards_to_remove' => $boards_to_remove, |
||
1088 | ) |
||
1089 | ); |
||
1090 | |||
1091 | // Delete any extra events in the calendar. |
||
1092 | $smcFunc['db_query']('', ' |
||
1093 | DELETE FROM {db_prefix}calendar |
||
1094 | WHERE id_board IN ({array_int:boards_to_remove})', |
||
1095 | array( |
||
1096 | 'boards_to_remove' => $boards_to_remove, |
||
1097 | ) |
||
1098 | ); |
||
1099 | |||
1100 | // Delete any message icons that only appear on these boards. |
||
1101 | $smcFunc['db_query']('', ' |
||
1102 | DELETE FROM {db_prefix}message_icons |
||
1103 | WHERE id_board IN ({array_int:boards_to_remove})', |
||
1104 | array( |
||
1105 | 'boards_to_remove' => $boards_to_remove, |
||
1106 | ) |
||
1107 | ); |
||
1108 | |||
1109 | // Delete the boards. |
||
1110 | $smcFunc['db_query']('', ' |
||
1111 | DELETE FROM {db_prefix}boards |
||
1112 | WHERE id_board IN ({array_int:boards_to_remove})', |
||
1113 | array( |
||
1114 | 'boards_to_remove' => $boards_to_remove, |
||
1115 | ) |
||
1116 | ); |
||
1117 | |||
1118 | // Delete permissions |
||
1119 | $smcFunc['db_query']('', ' |
||
1120 | DELETE FROM {db_prefix}board_permissions_view |
||
1121 | WHERE id_board IN ({array_int:boards_to_remove})', |
||
1122 | array( |
||
1123 | 'boards_to_remove' => $boards_to_remove, |
||
1124 | ) |
||
1125 | ); |
||
1126 | |||
1127 | // Latest message/topic might not be there anymore. |
||
1128 | updateStats('message'); |
||
1129 | updateStats('topic'); |
||
1130 | updateSettings(array( |
||
1131 | 'calendar_updated' => time(), |
||
1132 | )); |
||
1133 | |||
1134 | // Plus reset the cache to stop people getting odd results. |
||
1135 | updateSettings(array('settings_updated' => time())); |
||
1136 | |||
1137 | // Clean the cache as well. |
||
1138 | clean_cache('data'); |
||
1139 | |||
1140 | // Let's do some serious logging. |
||
1141 | foreach ($boards_to_remove as $id_board) |
||
1142 | logAction('delete_board', array('boardname' => $boards[$id_board]['name']), 'admin'); |
||
1143 | |||
1144 | reorderBoards(); |
||
1145 | } |
||
1146 | |||
1147 | /** |
||
1148 | * Put all boards in the right order and sorts the records of the boards table. |
||
1149 | * Used by modifyBoard(), deleteBoards(), modifyCategory(), and deleteCategories() functions |
||
1150 | */ |
||
1151 | function reorderBoards() |
||
1152 | { |
||
1153 | global $cat_tree, $boardList, $boards, $smcFunc; |
||
1154 | |||
1155 | getBoardTree(); |
||
1156 | |||
1157 | // Set the board order for each category. |
||
1158 | $board_order = 0; |
||
1159 | foreach ($cat_tree as $catID => $dummy) |
||
1160 | { |
||
1161 | foreach ($boardList[$catID] as $boardID) |
||
1162 | if ($boards[$boardID]['order'] != ++$board_order) |
||
1163 | $smcFunc['db_query']('', ' |
||
1164 | UPDATE {db_prefix}boards |
||
1165 | SET board_order = {int:new_order} |
||
1166 | WHERE id_board = {int:selected_board}', |
||
1167 | array( |
||
1168 | 'new_order' => $board_order, |
||
1169 | 'selected_board' => $boardID, |
||
1170 | ) |
||
1171 | ); |
||
1172 | } |
||
1173 | |||
1174 | // Empty the board order cache |
||
1175 | cache_put_data('board_order', null, -3600); |
||
1176 | } |
||
1177 | |||
1178 | /** |
||
1179 | * Fixes the children of a board by setting their child_levels to new values. |
||
1180 | * Used when a board is deleted or moved, to affect its children. |
||
1181 | * |
||
1182 | * @param int $parent The ID of the parent board |
||
1183 | * @param int $newLevel The new child level for each of the child boards |
||
1184 | * @param int $newParent The ID of the new parent board |
||
1185 | */ |
||
1186 | function fixChildren($parent, $newLevel, $newParent) |
||
1187 | { |
||
1188 | global $smcFunc; |
||
1189 | |||
1190 | // Grab all children of $parent... |
||
1191 | $result = $smcFunc['db_query']('', ' |
||
1192 | SELECT id_board |
||
1193 | FROM {db_prefix}boards |
||
1194 | WHERE id_parent = {int:parent_board}', |
||
1195 | array( |
||
1196 | 'parent_board' => $parent, |
||
1197 | ) |
||
1198 | ); |
||
1199 | $children = array(); |
||
1200 | while ($row = $smcFunc['db_fetch_assoc']($result)) |
||
1201 | $children[] = $row['id_board']; |
||
1202 | $smcFunc['db_free_result']($result); |
||
1203 | |||
1204 | // ...and set it to a new parent and child_level. |
||
1205 | $smcFunc['db_query']('', ' |
||
1206 | UPDATE {db_prefix}boards |
||
1207 | SET id_parent = {int:new_parent}, child_level = {int:new_child_level} |
||
1208 | WHERE id_parent = {int:parent_board}', |
||
1209 | array( |
||
1210 | 'new_parent' => $newParent, |
||
1211 | 'new_child_level' => $newLevel, |
||
1212 | 'parent_board' => $parent, |
||
1213 | ) |
||
1214 | ); |
||
1215 | |||
1216 | // Recursively fix the children of the children. |
||
1217 | foreach ($children as $child) |
||
1218 | fixChildren($child, $newLevel + 1, $child); |
||
1219 | } |
||
1220 | |||
1221 | /** |
||
1222 | * Tries to load up the entire board order and category very very quickly |
||
1223 | * Returns an array with two elements, cats and boards |
||
1224 | * |
||
1225 | * @return array An array of categories and boards |
||
1226 | */ |
||
1227 | function getTreeOrder() |
||
1228 | { |
||
1229 | global $smcFunc; |
||
1230 | |||
1231 | static $tree_order = array( |
||
1232 | 'cats' => array(), |
||
1233 | 'boards' => array(), |
||
1234 | ); |
||
1235 | |||
1236 | if (!empty($tree_order['boards'])) |
||
1237 | return $tree_order; |
||
1238 | |||
1239 | if (($cached = cache_get_data('board_order', 86400)) !== null) |
||
1240 | { |
||
1241 | $tree_order = $cached; |
||
1242 | return $cached; |
||
1243 | } |
||
1244 | |||
1245 | $request = $smcFunc['db_query']('', ' |
||
1246 | SELECT b.id_board, b.id_cat |
||
1247 | FROM {db_prefix}categories AS c |
||
1248 | JOIN {db_prefix}boards AS b ON (b.id_cat = c.id_cat) |
||
1249 | ORDER BY c.cat_order, b.board_order' |
||
1250 | ); |
||
1251 | |||
1252 | foreach ($smcFunc['db_fetch_all']($request) as $row) |
||
1253 | { |
||
1254 | if (!in_array($row['id_cat'], $tree_order['cats'])) |
||
1255 | $tree_order['cats'][] = $row['id_cat']; |
||
1256 | $tree_order['boards'][] = $row['id_board']; |
||
1257 | } |
||
1258 | $smcFunc['db_free_result']($request); |
||
1259 | |||
1260 | cache_put_data('board_order', $tree_order, 86400); |
||
1261 | |||
1262 | return $tree_order; |
||
1263 | } |
||
1264 | |||
1265 | /** |
||
1266 | * Takes a board array and sorts it |
||
1267 | * |
||
1268 | * @param array &$boards The boards |
||
1269 | */ |
||
1270 | function sortBoards(array &$boards) |
||
1271 | { |
||
1272 | $tree = getTreeOrder(); |
||
1273 | |||
1274 | $ordered = array(); |
||
1275 | foreach ($tree['boards'] as $board) |
||
1276 | if (!empty($boards[$board])) |
||
1277 | { |
||
1278 | $ordered[$board] = $boards[$board]; |
||
1279 | |||
1280 | if (is_array($ordered[$board]) && !empty($ordered[$board]['boards'])) |
||
1281 | sortBoards($ordered[$board]['boards']); |
||
1282 | |||
1283 | if (is_array($ordered[$board]) && !empty($ordered[$board]['children'])) |
||
1284 | sortBoards($ordered[$board]['children']); |
||
1285 | } |
||
1286 | |||
1287 | $boards = $ordered; |
||
1288 | } |
||
1289 | |||
1290 | /** |
||
1291 | * Takes a category array and sorts it |
||
1292 | * |
||
1293 | * @param array &$categories The categories |
||
1294 | */ |
||
1295 | function sortCategories(array &$categories) |
||
1296 | { |
||
1297 | $tree = getTreeOrder(); |
||
1298 | |||
1299 | $ordered = array(); |
||
1300 | foreach ($tree['cats'] as $cat) |
||
1301 | if (!empty($categories[$cat])) |
||
1302 | { |
||
1303 | $ordered[$cat] = $categories[$cat]; |
||
1304 | if (!empty($ordered[$cat]['boards'])) |
||
1305 | sortBoards($ordered[$cat]['boards']); |
||
1306 | } |
||
1307 | |||
1308 | $categories = $ordered; |
||
1309 | } |
||
1310 | |||
1311 | /** |
||
1312 | * Returns the given board's moderators, with their names and links |
||
1313 | * |
||
1314 | * @param array $boards The boards to get moderators of |
||
1315 | * @return array An array containing information about the moderators of each board |
||
1316 | */ |
||
1317 | function getBoardModerators(array $boards) |
||
1318 | { |
||
1319 | global $smcFunc, $scripturl, $txt; |
||
1320 | |||
1321 | if (empty($boards)) |
||
1322 | return array(); |
||
1323 | |||
1324 | $request = $smcFunc['db_query']('', ' |
||
1325 | SELECT mem.id_member, mem.real_name, mo.id_board |
||
1326 | FROM {db_prefix}moderators AS mo |
||
1327 | INNER JOIN {db_prefix}members AS mem ON (mem.id_member = mo.id_member) |
||
1328 | WHERE mo.id_board IN ({array_int:boards})', |
||
1329 | array( |
||
1330 | 'boards' => $boards, |
||
1331 | ) |
||
1332 | ); |
||
1333 | $moderators = array(); |
||
1334 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
1335 | { |
||
1336 | if (empty($moderators[$row['id_board']])) |
||
1337 | $moderators[$row['id_board']] = array(); |
||
1338 | |||
1339 | $moderators[$row['id_board']][] = array( |
||
1340 | 'id' => $row['id_member'], |
||
1341 | 'name' => $row['real_name'], |
||
1342 | 'href' => $scripturl . '?action=profile;u=' . $row['id_member'], |
||
1343 | 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '" title="' . $txt['board_moderator'] . '">' . $row['real_name'] . '</a>', |
||
1344 | ); |
||
1345 | } |
||
1346 | $smcFunc['db_free_result']($request); |
||
1347 | |||
1348 | return $moderators; |
||
1349 | } |
||
1350 | |||
1351 | /** |
||
1352 | * Returns board's moderator groups with their names and link |
||
1353 | * |
||
1354 | * @param array $boards The boards to get moderator groups of |
||
1355 | * @return array An array containing information about the groups assigned to moderate each board |
||
1356 | */ |
||
1357 | function getBoardModeratorGroups(array $boards) |
||
1358 | { |
||
1359 | global $smcFunc, $scripturl, $txt; |
||
1360 | |||
1361 | if (empty($boards)) |
||
1362 | return array(); |
||
1363 | |||
1364 | $request = $smcFunc['db_query']('', ' |
||
1365 | SELECT mg.id_group, mg.group_name, bg.id_board |
||
1366 | FROM {db_prefix}moderator_groups AS bg |
||
1367 | INNER JOIN {db_prefix}membergroups AS mg ON (mg.id_group = bg.id_group) |
||
1368 | WHERE bg.id_board IN ({array_int:boards})', |
||
1369 | array( |
||
1370 | 'boards' => $boards, |
||
1371 | ) |
||
1372 | ); |
||
1373 | $groups = array(); |
||
1374 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
1375 | { |
||
1376 | if (empty($groups[$row['id_board']])) |
||
1377 | $groups[$row['id_board']] = array(); |
||
1378 | |||
1379 | $groups[$row['id_board']][] = array( |
||
1380 | 'id' => $row['id_group'], |
||
1381 | 'name' => $row['group_name'], |
||
1382 | 'href' => $scripturl . '?action=groups;sa=members;group=' . $row['id_group'], |
||
1383 | 'link' => '<a href="' . $scripturl . '?action=groups;sa=members;group=' . $row['id_group'] . '" title="' . $txt['board_moderator'] . '">' . $row['group_name'] . '</a>', |
||
1384 | ); |
||
1385 | } |
||
1386 | |||
1387 | return $groups; |
||
1388 | } |
||
1389 | |||
1390 | /** |
||
1391 | * Load a lot of useful information regarding the boards and categories. |
||
1392 | * The information retrieved is stored in globals: |
||
1393 | * $boards properties of each board. |
||
1394 | * $boardList a list of boards grouped by category ID. |
||
1395 | * $cat_tree properties of each category. |
||
1396 | */ |
||
1397 | function getBoardTree() |
||
1398 | { |
||
1399 | global $cat_tree, $boards, $boardList, $smcFunc; |
||
1400 | |||
1401 | $boardColumns = array( |
||
1402 | 'COALESCE(b.id_board, 0) AS id_board', 'b.id_parent', 'b.name AS board_name', |
||
1403 | 'b.description', 'b.child_level', 'b.board_order', 'b.count_posts', 'b.member_groups', |
||
1404 | 'b.id_theme', 'b.override_theme', 'b.id_profile', 'b.redirect', 'b.num_posts', |
||
1405 | 'b.num_topics', 'b.deny_member_groups', 'c.id_cat', 'c.name AS cat_name', |
||
1406 | 'c.description AS cat_desc', 'c.cat_order', 'c.can_collapse', |
||
1407 | ); |
||
1408 | $boardParameters = array(); |
||
1409 | $boardJoins = array(); |
||
1410 | $boardWhere = array(); |
||
1411 | $boardOrder = array('c.cat_order', 'b.child_level', 'b.board_order'); |
||
1412 | |||
1413 | // Let mods add extra columns, parameters, etc., to the SELECT query |
||
1414 | call_integration_hook('integrate_pre_boardtree', array(&$boardColumns, &$boardParameters, &$boardJoins, &$boardWhere, &$boardOrder)); |
||
1415 | |||
1416 | $boardColumns = array_unique($boardColumns); |
||
1417 | $boardParameters = array_unique($boardParameters); |
||
1418 | $boardJoins = array_unique($boardJoins); |
||
1419 | $boardWhere = array_unique($boardWhere); |
||
1420 | $boardOrder = array_unique($boardOrder); |
||
1421 | |||
1422 | // Getting all the board and category information you'd ever wanted. |
||
1423 | $request = $smcFunc['db_query']('', ' |
||
1424 | SELECT |
||
1425 | ' . implode(', ', $boardColumns) . ' |
||
1426 | FROM {db_prefix}categories AS c |
||
1427 | LEFT JOIN {db_prefix}boards AS b ON (b.id_cat = c.id_cat)' . implode(' |
||
1428 | ', $boardJoins) . ' |
||
1429 | WHERE {query_see_board}' . (empty($boardWhere) ? '' : ' |
||
1430 | AND (' . implode(') AND (', $boardWhere) . ')') . ' |
||
1431 | ORDER BY ' . implode(', ', $boardOrder), |
||
1432 | $boardParameters |
||
1433 | ); |
||
1434 | $cat_tree = array(); |
||
1435 | $boards = array(); |
||
1436 | $last_board_order = 0; |
||
1437 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
1438 | { |
||
1439 | if (!isset($cat_tree[$row['id_cat']])) |
||
1440 | { |
||
1441 | $cat_tree[$row['id_cat']] = array( |
||
1442 | 'node' => array( |
||
1443 | 'id' => $row['id_cat'], |
||
1444 | 'name' => $row['cat_name'], |
||
1445 | 'description' => $row['cat_desc'], |
||
1446 | 'order' => $row['cat_order'], |
||
1447 | 'can_collapse' => $row['can_collapse'] |
||
1448 | ), |
||
1449 | 'is_first' => empty($cat_tree), |
||
1450 | 'last_board_order' => $last_board_order, |
||
1451 | 'children' => array() |
||
1452 | ); |
||
1453 | $prevBoard = 0; |
||
1454 | $curLevel = 0; |
||
1455 | } |
||
1456 | |||
1457 | if (!empty($row['id_board'])) |
||
1458 | { |
||
1459 | if ($row['child_level'] != $curLevel) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
1460 | $prevBoard = 0; |
||
1461 | |||
1462 | $boards[$row['id_board']] = array( |
||
1463 | 'id' => $row['id_board'], |
||
1464 | 'category' => $row['id_cat'], |
||
1465 | 'parent' => $row['id_parent'], |
||
1466 | 'level' => $row['child_level'], |
||
1467 | 'order' => $row['board_order'], |
||
1468 | 'name' => $row['board_name'], |
||
1469 | 'member_groups' => explode(',', $row['member_groups']), |
||
1470 | 'deny_groups' => explode(',', $row['deny_member_groups']), |
||
1471 | 'description' => $row['description'], |
||
1472 | 'count_posts' => empty($row['count_posts']), |
||
1473 | 'posts' => $row['num_posts'], |
||
1474 | 'topics' => $row['num_topics'], |
||
1475 | 'theme' => $row['id_theme'], |
||
1476 | 'override_theme' => $row['override_theme'], |
||
1477 | 'profile' => $row['id_profile'], |
||
1478 | 'redirect' => $row['redirect'], |
||
1479 | 'prev_board' => $prevBoard |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
1480 | ); |
||
1481 | $prevBoard = $row['id_board']; |
||
1482 | $last_board_order = $row['board_order']; |
||
1483 | |||
1484 | if (empty($row['child_level'])) |
||
1485 | { |
||
1486 | $cat_tree[$row['id_cat']]['children'][$row['id_board']] = array( |
||
1487 | 'node' => &$boards[$row['id_board']], |
||
1488 | 'is_first' => empty($cat_tree[$row['id_cat']]['children']), |
||
1489 | 'children' => array() |
||
1490 | ); |
||
1491 | $boards[$row['id_board']]['tree'] = &$cat_tree[$row['id_cat']]['children'][$row['id_board']]; |
||
1492 | } |
||
1493 | else |
||
1494 | { |
||
1495 | // Parent doesn't exist! |
||
1496 | if (!isset($boards[$row['id_parent']]['tree'])) |
||
1497 | fatal_lang_error('no_valid_parent', false, array($row['board_name'])); |
||
1498 | |||
1499 | // Wrong childlevel...we can silently fix this... |
||
1500 | if ($boards[$row['id_parent']]['tree']['node']['level'] != $row['child_level'] - 1) |
||
1501 | $smcFunc['db_query']('', ' |
||
1502 | UPDATE {db_prefix}boards |
||
1503 | SET child_level = {int:new_child_level} |
||
1504 | WHERE id_board = {int:selected_board}', |
||
1505 | array( |
||
1506 | 'new_child_level' => $boards[$row['id_parent']]['tree']['node']['level'] + 1, |
||
1507 | 'selected_board' => $row['id_board'], |
||
1508 | ) |
||
1509 | ); |
||
1510 | |||
1511 | $boards[$row['id_parent']]['tree']['children'][$row['id_board']] = array( |
||
1512 | 'node' => &$boards[$row['id_board']], |
||
1513 | 'is_first' => empty($boards[$row['id_parent']]['tree']['children']), |
||
1514 | 'children' => array() |
||
1515 | ); |
||
1516 | $boards[$row['id_board']]['tree'] = &$boards[$row['id_parent']]['tree']['children'][$row['id_board']]; |
||
1517 | } |
||
1518 | } |
||
1519 | |||
1520 | // If mods want to do anything with this board before we move on, now's the time |
||
1521 | call_integration_hook('integrate_boardtree_board', array($row)); |
||
1522 | } |
||
1523 | $smcFunc['db_free_result']($request); |
||
1524 | |||
1525 | // Get a list of all the boards in each category (using recursion). |
||
1526 | $boardList = array(); |
||
1527 | foreach ($cat_tree as $catID => $node) |
||
1528 | { |
||
1529 | $boardList[$catID] = array(); |
||
1530 | recursiveBoards($boardList[$catID], $node); |
||
1531 | } |
||
1532 | } |
||
1533 | |||
1534 | /** |
||
1535 | * Recursively get a list of boards. |
||
1536 | * Used by getBoardTree |
||
1537 | * |
||
1538 | * @param array &$_boardList The board list |
||
1539 | * @param array &$_tree The board tree |
||
1540 | */ |
||
1541 | function recursiveBoards(&$_boardList, &$_tree) |
||
1542 | { |
||
1543 | if (empty($_tree['children'])) |
||
1544 | return; |
||
1545 | |||
1546 | foreach ($_tree['children'] as $id => $node) |
||
1547 | { |
||
1548 | $_boardList[] = $id; |
||
1549 | recursiveBoards($_boardList, $node); |
||
1550 | } |
||
1551 | } |
||
1552 | |||
1553 | /** |
||
1554 | * Returns whether the child board id is actually a child of the parent (recursive). |
||
1555 | * |
||
1556 | * @param int $child The ID of the child board |
||
1557 | * @param int $parent The ID of a parent board |
||
1558 | * @return boolean Whether the specified child board is actually a child of the specified parent board. |
||
1559 | */ |
||
1560 | function isChildOf($child, $parent) |
||
1561 | { |
||
1562 | global $boards; |
||
1563 | |||
1564 | if (empty($boards[$child]['parent'])) |
||
1565 | return false; |
||
1566 | |||
1567 | if ($boards[$child]['parent'] == $parent) |
||
1568 | return true; |
||
1569 | |||
1570 | return isChildOf($boards[$child]['parent'], $parent); |
||
1571 | } |
||
1572 | |||
1573 | function setBoardParsedDescription($category_id = 0, $boards_info = array()) |
||
1574 | { |
||
1575 | global $context; |
||
1576 | |||
1577 | if (empty($category_id) || empty($boards_info)) |
||
1578 | return array(); |
||
1579 | |||
1580 | // Get the data we already parsed |
||
1581 | $already_parsed_boards = getBoardsParsedDescription($category_id); |
||
1582 | |||
1583 | foreach ($boards_info as $board_id => $board_description) |
||
1584 | $already_parsed_boards[$board_id] = parse_bbc( |
||
1585 | $board_description, |
||
1586 | false, |
||
1587 | '', |
||
1588 | $context['description_allowed_tags'] |
||
1589 | ); |
||
1590 | |||
1591 | cache_put_data('parsed_boards_descriptions_'. $category_id, $already_parsed_boards, 864000); |
||
1592 | |||
1593 | return $already_parsed_boards; |
||
1594 | } |
||
1595 | |||
1596 | function getBoardsParsedDescription($category_id = 0) |
||
1597 | { |
||
1598 | if (empty($category_id)) |
||
1599 | return array(); |
||
1600 | |||
1601 | return (array) cache_get_data('parsed_boards_descriptions_' . $category_id, 864000); |
||
1602 | } |
||
1603 | |||
1604 | ?> |