Mercurial > hg > vamp-website
comparison forum/Sources/Subs-Boards.php @ 76:e3e11437ecea website
Add forum code
author | Chris Cannam |
---|---|
date | Sun, 07 Jul 2013 11:25:48 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
75:72f59aa7e503 | 76:e3e11437ecea |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * Simple Machines Forum (SMF) | |
5 * | |
6 * @package SMF | |
7 * @author Simple Machines http://www.simplemachines.org | |
8 * @copyright 2011 Simple Machines | |
9 * @license http://www.simplemachines.org/about/smf/license.php BSD | |
10 * | |
11 * @version 2.0 | |
12 */ | |
13 | |
14 if (!defined('SMF')) | |
15 die('Hacking attempt...'); | |
16 | |
17 /* This file is mainly concerned with minor tasks relating to boards, such as | |
18 marking them read, collapsing categories, or quick moderation. It defines | |
19 the following list of functions: | |
20 | |
21 void markBoardsRead(array boards) | |
22 // !!! | |
23 | |
24 void MarkRead() | |
25 // !!! | |
26 | |
27 int getMsgMemberID(int id_msg) | |
28 // !!! | |
29 | |
30 void modifyBoard(int board_id, array boardOptions) | |
31 - general function to modify the settings and position of a board. | |
32 - used by ManageBoards.php to change the settings of a board. | |
33 | |
34 int createBoard(array boardOptions) | |
35 - general function to create a new board and set its position. | |
36 - allows (almost) the same options as the modifyBoard() function. | |
37 - with the option inherit_permissions set, the parent board permissions | |
38 will be inherited. | |
39 - returns the ID of the newly created board. | |
40 | |
41 void deleteBoards(array boards_to_remove, moveChildrenTo = null) | |
42 - general function to delete one or more boards. | |
43 - allows to move the children of the board before deleting it | |
44 - if moveChildrenTo is set to null, the child boards will be deleted. | |
45 - deletes all topics that are on the given boards. | |
46 - deletes all information that's associated with the given boards. | |
47 - updates the statistics to reflect the new situation. | |
48 | |
49 void reorderBoards() | |
50 - updates the database to put all boards in the right order. | |
51 - sorts the records of the boards table. | |
52 - used by modifyBoard(), deleteBoards(), modifyCategory(), and | |
53 deleteCategories() functions. | |
54 | |
55 void fixChildren(int parent, int newLevel, int newParent) | |
56 - recursively updates the children of parent's child_level and | |
57 id_parent to newLevel and newParent. | |
58 - used when a board is deleted or moved, to affect its children. | |
59 | |
60 bool isChildOf(int child, int parent) | |
61 - determines if child is a child of parent. | |
62 - recurses down the tree until there are no more parents. | |
63 - returns true if child is a child of parent. | |
64 | |
65 void getBoardTree() | |
66 - load information regarding the boards and categories. | |
67 - the information retrieved is stored in globals: | |
68 - $boards properties of each board. | |
69 - $boardList a list of boards grouped by category ID. | |
70 - $cat_tree properties of each category. | |
71 | |
72 void recursiveBoards() | |
73 - function used by getBoardTree to recursively get a list of boards. | |
74 | |
75 bool isChildOf(int child, int parent) | |
76 - determine if a certain board id is a child of another board. | |
77 - the parent might be several levels higher than the child. | |
78 */ | |
79 | |
80 // Mark a board or multiple boards read. | |
81 function markBoardsRead($boards, $unread = false) | |
82 { | |
83 global $user_info, $modSettings, $smcFunc; | |
84 | |
85 // Force $boards to be an array. | |
86 if (!is_array($boards)) | |
87 $boards = array($boards); | |
88 else | |
89 $boards = array_unique($boards); | |
90 | |
91 // No boards, nothing to mark as read. | |
92 if (empty($boards)) | |
93 return; | |
94 | |
95 // Allow the user to mark a board as unread. | |
96 if ($unread) | |
97 { | |
98 // Clear out all the places where this lovely info is stored. | |
99 // !! Maybe not log_mark_read? | |
100 $smcFunc['db_query']('', ' | |
101 DELETE FROM {db_prefix}log_mark_read | |
102 WHERE id_board IN ({array_int:board_list}) | |
103 AND id_member = {int:current_member}', | |
104 array( | |
105 'current_member' => $user_info['id'], | |
106 'board_list' => $boards, | |
107 ) | |
108 ); | |
109 $smcFunc['db_query']('', ' | |
110 DELETE FROM {db_prefix}log_boards | |
111 WHERE id_board IN ({array_int:board_list}) | |
112 AND id_member = {int:current_member}', | |
113 array( | |
114 'current_member' => $user_info['id'], | |
115 'board_list' => $boards, | |
116 ) | |
117 ); | |
118 } | |
119 // Otherwise mark the board as read. | |
120 else | |
121 { | |
122 $markRead = array(); | |
123 foreach ($boards as $board) | |
124 $markRead[] = array($modSettings['maxMsgID'], $user_info['id'], $board); | |
125 | |
126 // Update log_mark_read and log_boards. | |
127 $smcFunc['db_insert']('replace', | |
128 '{db_prefix}log_mark_read', | |
129 array('id_msg' => 'int', 'id_member' => 'int', 'id_board' => 'int'), | |
130 $markRead, | |
131 array('id_board', 'id_member') | |
132 ); | |
133 | |
134 $smcFunc['db_insert']('replace', | |
135 '{db_prefix}log_boards', | |
136 array('id_msg' => 'int', 'id_member' => 'int', 'id_board' => 'int'), | |
137 $markRead, | |
138 array('id_board', 'id_member') | |
139 ); | |
140 } | |
141 | |
142 // Get rid of useless log_topics data, because log_mark_read is better for it - even if marking unread - I think so... | |
143 $result = $smcFunc['db_query']('', ' | |
144 SELECT MIN(id_topic) | |
145 FROM {db_prefix}log_topics | |
146 WHERE id_member = {int:current_member}', | |
147 array( | |
148 'current_member' => $user_info['id'], | |
149 ) | |
150 ); | |
151 list ($lowest_topic) = $smcFunc['db_fetch_row']($result); | |
152 $smcFunc['db_free_result']($result); | |
153 | |
154 if (empty($lowest_topic)) | |
155 return; | |
156 | |
157 // !!!SLOW This query seems to eat it sometimes. | |
158 $result = $smcFunc['db_query']('', ' | |
159 SELECT lt.id_topic | |
160 FROM {db_prefix}log_topics AS lt | |
161 INNER JOIN {db_prefix}topics AS t /*!40000 USE INDEX (PRIMARY) */ ON (t.id_topic = lt.id_topic | |
162 AND t.id_board IN ({array_int:board_list})) | |
163 WHERE lt.id_member = {int:current_member} | |
164 AND lt.id_topic >= {int:lowest_topic}', | |
165 array( | |
166 'current_member' => $user_info['id'], | |
167 'board_list' => $boards, | |
168 'lowest_topic' => $lowest_topic, | |
169 ) | |
170 ); | |
171 $topics = array(); | |
172 while ($row = $smcFunc['db_fetch_assoc']($result)) | |
173 $topics[] = $row['id_topic']; | |
174 $smcFunc['db_free_result']($result); | |
175 | |
176 if (!empty($topics)) | |
177 $smcFunc['db_query']('', ' | |
178 DELETE FROM {db_prefix}log_topics | |
179 WHERE id_member = {int:current_member} | |
180 AND id_topic IN ({array_int:topic_list})', | |
181 array( | |
182 'current_member' => $user_info['id'], | |
183 'topic_list' => $topics, | |
184 ) | |
185 ); | |
186 } | |
187 | |
188 // Mark one or more boards as read. | |
189 function MarkRead() | |
190 { | |
191 global $board, $topic, $user_info, $board_info, $modSettings, $smcFunc; | |
192 | |
193 // No Guests allowed! | |
194 is_not_guest(); | |
195 | |
196 checkSession('get'); | |
197 | |
198 if (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'all') | |
199 { | |
200 // Find all the boards this user can see. | |
201 $result = $smcFunc['db_query']('', ' | |
202 SELECT b.id_board | |
203 FROM {db_prefix}boards AS b | |
204 WHERE {query_see_board}', | |
205 array( | |
206 ) | |
207 ); | |
208 $boards = array(); | |
209 while ($row = $smcFunc['db_fetch_assoc']($result)) | |
210 $boards[] = $row['id_board']; | |
211 $smcFunc['db_free_result']($result); | |
212 | |
213 if (!empty($boards)) | |
214 markBoardsRead($boards, isset($_REQUEST['unread'])); | |
215 | |
216 $_SESSION['id_msg_last_visit'] = $modSettings['maxMsgID']; | |
217 if (!empty($_SESSION['old_url']) && strpos($_SESSION['old_url'], 'action=unread') !== false) | |
218 redirectexit('action=unread'); | |
219 | |
220 if (isset($_SESSION['topicseen_cache'])) | |
221 $_SESSION['topicseen_cache'] = array(); | |
222 | |
223 redirectexit(); | |
224 } | |
225 elseif (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'unreadreplies') | |
226 { | |
227 // Make sure all the boards are integers! | |
228 $topics = explode('-', $_REQUEST['topics']); | |
229 | |
230 $markRead = array(); | |
231 foreach ($topics as $id_topic) | |
232 $markRead[] = array($modSettings['maxMsgID'], $user_info['id'], (int) $id_topic); | |
233 | |
234 $smcFunc['db_insert']('replace', | |
235 '{db_prefix}log_topics', | |
236 array('id_msg' => 'int', 'id_member' => 'int', 'id_topic' => 'int'), | |
237 $markRead, | |
238 array('id_member', 'id_topic') | |
239 ); | |
240 | |
241 if (isset($_SESSION['topicseen_cache'])) | |
242 $_SESSION['topicseen_cache'] = array(); | |
243 | |
244 redirectexit('action=unreadreplies'); | |
245 } | |
246 | |
247 // Special case: mark a topic unread! | |
248 elseif (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'topic') | |
249 { | |
250 // First, let's figure out what the latest message is. | |
251 $result = $smcFunc['db_query']('', ' | |
252 SELECT id_first_msg, id_last_msg | |
253 FROM {db_prefix}topics | |
254 WHERE id_topic = {int:current_topic}', | |
255 array( | |
256 'current_topic' => $topic, | |
257 ) | |
258 ); | |
259 $topicinfo = $smcFunc['db_fetch_assoc']($result); | |
260 $smcFunc['db_free_result']($result); | |
261 | |
262 if (!empty($_GET['t'])) | |
263 { | |
264 // If they read the whole topic, go back to the beginning. | |
265 if ($_GET['t'] >= $topicinfo['id_last_msg']) | |
266 $earlyMsg = 0; | |
267 // If they want to mark the whole thing read, same. | |
268 elseif ($_GET['t'] <= $topicinfo['id_first_msg']) | |
269 $earlyMsg = 0; | |
270 // Otherwise, get the latest message before the named one. | |
271 else | |
272 { | |
273 $result = $smcFunc['db_query']('', ' | |
274 SELECT MAX(id_msg) | |
275 FROM {db_prefix}messages | |
276 WHERE id_topic = {int:current_topic} | |
277 AND id_msg >= {int:id_first_msg} | |
278 AND id_msg < {int:topic_msg_id}', | |
279 array( | |
280 'current_topic' => $topic, | |
281 'topic_msg_id' => (int) $_GET['t'], | |
282 'id_first_msg' => $topicinfo['id_first_msg'], | |
283 ) | |
284 ); | |
285 list ($earlyMsg) = $smcFunc['db_fetch_row']($result); | |
286 $smcFunc['db_free_result']($result); | |
287 } | |
288 } | |
289 // Marking read from first page? That's the whole topic. | |
290 elseif ($_REQUEST['start'] == 0) | |
291 $earlyMsg = 0; | |
292 else | |
293 { | |
294 $result = $smcFunc['db_query']('', ' | |
295 SELECT id_msg | |
296 FROM {db_prefix}messages | |
297 WHERE id_topic = {int:current_topic} | |
298 ORDER BY id_msg | |
299 LIMIT ' . (int) $_REQUEST['start'] . ', 1', | |
300 array( | |
301 'current_topic' => $topic, | |
302 ) | |
303 ); | |
304 list ($earlyMsg) = $smcFunc['db_fetch_row']($result); | |
305 $smcFunc['db_free_result']($result); | |
306 | |
307 $earlyMsg--; | |
308 } | |
309 | |
310 // Blam, unread! | |
311 $smcFunc['db_insert']('replace', | |
312 '{db_prefix}log_topics', | |
313 array('id_msg' => 'int', 'id_member' => 'int', 'id_topic' => 'int'), | |
314 array($earlyMsg, $user_info['id'], $topic), | |
315 array('id_member', 'id_topic') | |
316 ); | |
317 | |
318 redirectexit('board=' . $board . '.0'); | |
319 } | |
320 else | |
321 { | |
322 $categories = array(); | |
323 $boards = array(); | |
324 | |
325 if (isset($_REQUEST['c'])) | |
326 { | |
327 $_REQUEST['c'] = explode(',', $_REQUEST['c']); | |
328 foreach ($_REQUEST['c'] as $c) | |
329 $categories[] = (int) $c; | |
330 } | |
331 if (isset($_REQUEST['boards'])) | |
332 { | |
333 $_REQUEST['boards'] = explode(',', $_REQUEST['boards']); | |
334 foreach ($_REQUEST['boards'] as $b) | |
335 $boards[] = (int) $b; | |
336 } | |
337 if (!empty($board)) | |
338 $boards[] = (int) $board; | |
339 | |
340 if (isset($_REQUEST['children']) && !empty($boards)) | |
341 { | |
342 // They want to mark the entire tree starting with the boards specified | |
343 // The easist 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 | |
344 | |
345 $request = $smcFunc['db_query']('', ' | |
346 SELECT b.id_board, b.id_parent | |
347 FROM {db_prefix}boards AS b | |
348 WHERE {query_see_board} | |
349 AND b.child_level > {int:no_parents} | |
350 AND b.id_board NOT IN ({array_int:board_list}) | |
351 ORDER BY child_level ASC | |
352 ', | |
353 array( | |
354 'no_parents' => 0, | |
355 'board_list' => $boards, | |
356 ) | |
357 ); | |
358 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
359 if (in_array($row['id_parent'], $boards)) | |
360 $boards[] = $row['id_board']; | |
361 $smcFunc['db_free_result']($request); | |
362 } | |
363 | |
364 $clauses = array(); | |
365 $clauseParameters = array(); | |
366 if (!empty($categories)) | |
367 { | |
368 $clauses[] = 'id_cat IN ({array_int:category_list})'; | |
369 $clauseParameters['category_list'] = $categories; | |
370 } | |
371 if (!empty($boards)) | |
372 { | |
373 $clauses[] = 'id_board IN ({array_int:board_list})'; | |
374 $clauseParameters['board_list'] = $boards; | |
375 } | |
376 | |
377 if (empty($clauses)) | |
378 redirectexit(); | |
379 | |
380 $request = $smcFunc['db_query']('', ' | |
381 SELECT b.id_board | |
382 FROM {db_prefix}boards AS b | |
383 WHERE {query_see_board} | |
384 AND b.' . implode(' OR b.', $clauses), | |
385 array_merge($clauseParameters, array( | |
386 )) | |
387 ); | |
388 $boards = array(); | |
389 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
390 $boards[] = $row['id_board']; | |
391 $smcFunc['db_free_result']($request); | |
392 | |
393 if (empty($boards)) | |
394 redirectexit(); | |
395 | |
396 markBoardsRead($boards, isset($_REQUEST['unread'])); | |
397 | |
398 foreach ($boards as $b) | |
399 { | |
400 if (isset($_SESSION['topicseen_cache'][$b])) | |
401 $_SESSION['topicseen_cache'][$b] = array(); | |
402 } | |
403 | |
404 if (!isset($_REQUEST['unread'])) | |
405 { | |
406 // Find all the boards this user can see. | |
407 $result = $smcFunc['db_query']('', ' | |
408 SELECT b.id_board | |
409 FROM {db_prefix}boards AS b | |
410 WHERE b.id_parent IN ({array_int:parent_list}) | |
411 AND {query_see_board}', | |
412 array( | |
413 'parent_list' => $boards, | |
414 ) | |
415 ); | |
416 if ($smcFunc['db_num_rows']($result) > 0) | |
417 { | |
418 $logBoardInserts = ''; | |
419 while ($row = $smcFunc['db_fetch_assoc']($result)) | |
420 $logBoardInserts[] = array($modSettings['maxMsgID'], $user_info['id'], $row['id_board']); | |
421 | |
422 $smcFunc['db_insert']('replace', | |
423 '{db_prefix}log_boards', | |
424 array('id_msg' => 'int', 'id_member' => 'int', 'id_board' => 'int'), | |
425 $logBoardInserts, | |
426 array('id_member', 'id_board') | |
427 ); | |
428 } | |
429 $smcFunc['db_free_result']($result); | |
430 | |
431 if (empty($board)) | |
432 redirectexit(); | |
433 else | |
434 redirectexit('board=' . $board . '.0'); | |
435 } | |
436 else | |
437 { | |
438 if (empty($board_info['parent'])) | |
439 redirectexit(); | |
440 else | |
441 redirectexit('board=' . $board_info['parent'] . '.0'); | |
442 } | |
443 } | |
444 } | |
445 | |
446 // Get the id_member associated with the specified message. | |
447 function getMsgMemberID($messageID) | |
448 { | |
449 global $smcFunc; | |
450 | |
451 // Find the topic and make sure the member still exists. | |
452 $result = $smcFunc['db_query']('', ' | |
453 SELECT IFNULL(mem.id_member, 0) | |
454 FROM {db_prefix}messages AS m | |
455 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) | |
456 WHERE m.id_msg = {int:selected_message} | |
457 LIMIT 1', | |
458 array( | |
459 'selected_message' => (int) $messageID, | |
460 ) | |
461 ); | |
462 if ($smcFunc['db_num_rows']($result) > 0) | |
463 list ($memberID) = $smcFunc['db_fetch_row']($result); | |
464 // The message doesn't even exist. | |
465 else | |
466 $memberID = 0; | |
467 $smcFunc['db_free_result']($result); | |
468 | |
469 return (int) $memberID; | |
470 } | |
471 | |
472 // Modify the settings and position of a board. | |
473 function modifyBoard($board_id, &$boardOptions) | |
474 { | |
475 global $sourcedir, $cat_tree, $boards, $boardList, $modSettings, $smcFunc; | |
476 | |
477 // Get some basic information about all boards and categories. | |
478 getBoardTree(); | |
479 | |
480 // Make sure given boards and categories exist. | |
481 if (!isset($boards[$board_id]) || (isset($boardOptions['target_board']) && !isset($boards[$boardOptions['target_board']])) || (isset($boardOptions['target_category']) && !isset($cat_tree[$boardOptions['target_category']]))) | |
482 fatal_lang_error('no_board'); | |
483 | |
484 // All things that will be updated in the database will be in $boardUpdates. | |
485 $boardUpdates = array(); | |
486 $boardUpdateParameters = array(); | |
487 | |
488 // In case the board has to be moved | |
489 if (isset($boardOptions['move_to'])) | |
490 { | |
491 // Move the board to the top of a given category. | |
492 if ($boardOptions['move_to'] == 'top') | |
493 { | |
494 $id_cat = $boardOptions['target_category']; | |
495 $child_level = 0; | |
496 $id_parent = 0; | |
497 $after = $cat_tree[$id_cat]['last_board_order']; | |
498 } | |
499 | |
500 // Move the board to the bottom of a given category. | |
501 elseif ($boardOptions['move_to'] == 'bottom') | |
502 { | |
503 $id_cat = $boardOptions['target_category']; | |
504 $child_level = 0; | |
505 $id_parent = 0; | |
506 $after = 0; | |
507 foreach ($cat_tree[$id_cat]['children'] as $id_board => $dummy) | |
508 $after = max($after, $boards[$id_board]['order']); | |
509 } | |
510 | |
511 // Make the board a child of a given board. | |
512 elseif ($boardOptions['move_to'] == 'child') | |
513 { | |
514 $id_cat = $boards[$boardOptions['target_board']]['category']; | |
515 $child_level = $boards[$boardOptions['target_board']]['level'] + 1; | |
516 $id_parent = $boardOptions['target_board']; | |
517 | |
518 // People can be creative, in many ways... | |
519 if (isChildOf($id_parent, $board_id)) | |
520 fatal_lang_error('mboards_parent_own_child_error', false); | |
521 elseif ($id_parent == $board_id) | |
522 fatal_lang_error('mboards_board_own_child_error', false); | |
523 | |
524 $after = $boards[$boardOptions['target_board']]['order']; | |
525 | |
526 // Check if there are already children and (if so) get the max board order. | |
527 if (!empty($boards[$id_parent]['tree']['children']) && empty($boardOptions['move_first_child'])) | |
528 foreach ($boards[$id_parent]['tree']['children'] as $childBoard_id => $dummy) | |
529 $after = max($after, $boards[$childBoard_id]['order']); | |
530 } | |
531 | |
532 // Place a board before or after another board, on the same child level. | |
533 elseif (in_array($boardOptions['move_to'], array('before', 'after'))) | |
534 { | |
535 $id_cat = $boards[$boardOptions['target_board']]['category']; | |
536 $child_level = $boards[$boardOptions['target_board']]['level']; | |
537 $id_parent = $boards[$boardOptions['target_board']]['parent']; | |
538 $after = $boards[$boardOptions['target_board']]['order'] - ($boardOptions['move_to'] == 'before' ? 1 : 0); | |
539 } | |
540 | |
541 // Oops...? | |
542 else | |
543 trigger_error('modifyBoard(): The move_to value \'' . $boardOptions['move_to'] . '\' is incorrect', E_USER_ERROR); | |
544 | |
545 // Get a list of children of this board. | |
546 $childList = array(); | |
547 recursiveBoards($childList, $boards[$board_id]['tree']); | |
548 | |
549 // See if there are changes that affect children. | |
550 $childUpdates = array(); | |
551 $levelDiff = $child_level - $boards[$board_id]['level']; | |
552 if ($levelDiff != 0) | |
553 $childUpdates[] = 'child_level = child_level ' . ($levelDiff > 0 ? '+ ' : '') . '{int:level_diff}'; | |
554 if ($id_cat != $boards[$board_id]['category']) | |
555 $childUpdates[] = 'id_cat = {int:category}'; | |
556 | |
557 // Fix the children of this board. | |
558 if (!empty($childList) && !empty($childUpdates)) | |
559 $smcFunc['db_query']('', ' | |
560 UPDATE {db_prefix}boards | |
561 SET ' . implode(', | |
562 ', $childUpdates) . ' | |
563 WHERE id_board IN ({array_int:board_list})', | |
564 array( | |
565 'board_list' => $childList, | |
566 'category' => $id_cat, | |
567 'level_diff' => $levelDiff, | |
568 ) | |
569 ); | |
570 | |
571 // Make some room for this spot. | |
572 $smcFunc['db_query']('', ' | |
573 UPDATE {db_prefix}boards | |
574 SET board_order = board_order + {int:new_order} | |
575 WHERE board_order > {int:insert_after} | |
576 AND id_board != {int:selected_board}', | |
577 array( | |
578 'insert_after' => $after, | |
579 'selected_board' => $board_id, | |
580 'new_order' => 1 + count($childList), | |
581 ) | |
582 ); | |
583 | |
584 $boardUpdates[] = 'id_cat = {int:id_cat}'; | |
585 $boardUpdates[] = 'id_parent = {int:id_parent}'; | |
586 $boardUpdates[] = 'child_level = {int:child_level}'; | |
587 $boardUpdates[] = 'board_order = {int:board_order}'; | |
588 $boardUpdateParameters += array( | |
589 'id_cat' => $id_cat, | |
590 'id_parent' => $id_parent, | |
591 'child_level' => $child_level, | |
592 'board_order' => $after + 1, | |
593 ); | |
594 } | |
595 | |
596 // This setting is a little twisted in the database... | |
597 if (isset($boardOptions['posts_count'])) | |
598 { | |
599 $boardUpdates[] = 'count_posts = {int:count_posts}'; | |
600 $boardUpdateParameters['count_posts'] = $boardOptions['posts_count'] ? 0 : 1; | |
601 } | |
602 | |
603 // Set the theme for this board. | |
604 if (isset($boardOptions['board_theme'])) | |
605 { | |
606 $boardUpdates[] = 'id_theme = {int:id_theme}'; | |
607 $boardUpdateParameters['id_theme'] = (int) $boardOptions['board_theme']; | |
608 } | |
609 | |
610 // Should the board theme override the user preferred theme? | |
611 if (isset($boardOptions['override_theme'])) | |
612 { | |
613 $boardUpdates[] = 'override_theme = {int:override_theme}'; | |
614 $boardUpdateParameters['override_theme'] = $boardOptions['override_theme'] ? 1 : 0; | |
615 } | |
616 | |
617 // Who's allowed to access this board. | |
618 if (isset($boardOptions['access_groups'])) | |
619 { | |
620 $boardUpdates[] = 'member_groups = {string:member_groups}'; | |
621 $boardUpdateParameters['member_groups'] = implode(',', $boardOptions['access_groups']); | |
622 } | |
623 | |
624 if (isset($boardOptions['board_name'])) | |
625 { | |
626 $boardUpdates[] = 'name = {string:board_name}'; | |
627 $boardUpdateParameters['board_name'] = $boardOptions['board_name']; | |
628 } | |
629 | |
630 if (isset($boardOptions['board_description'])) | |
631 { | |
632 $boardUpdates[] = 'description = {string:board_description}'; | |
633 $boardUpdateParameters['board_description'] = $boardOptions['board_description']; | |
634 } | |
635 | |
636 if (isset($boardOptions['profile'])) | |
637 { | |
638 $boardUpdates[] = 'id_profile = {int:profile}'; | |
639 $boardUpdateParameters['profile'] = (int) $boardOptions['profile']; | |
640 } | |
641 | |
642 if (isset($boardOptions['redirect'])) | |
643 { | |
644 $boardUpdates[] = 'redirect = {string:redirect}'; | |
645 $boardUpdateParameters['redirect'] = $boardOptions['redirect']; | |
646 } | |
647 | |
648 if (isset($boardOptions['num_posts'])) | |
649 { | |
650 $boardUpdates[] = 'num_posts = {int:num_posts}'; | |
651 $boardUpdateParameters['num_posts'] = (int) $boardOptions['num_posts']; | |
652 } | |
653 | |
654 // Do the updates (if any). | |
655 if (!empty($boardUpdates)) | |
656 $request = $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 // Set moderators of this board. | |
668 if (isset($boardOptions['moderators']) || isset($boardOptions['moderator_string'])) | |
669 { | |
670 // Reset current moderators for this board - if there are any! | |
671 $smcFunc['db_query']('', ' | |
672 DELETE FROM {db_prefix}moderators | |
673 WHERE id_board = {int:board_list}', | |
674 array( | |
675 'board_list' => $board_id, | |
676 ) | |
677 ); | |
678 | |
679 // Validate and get the IDs of the new moderators. | |
680 if (isset($boardOptions['moderator_string']) && trim($boardOptions['moderator_string']) != '') | |
681 { | |
682 // Divvy out the usernames, remove extra space. | |
683 $moderator_string = strtr($smcFunc['htmlspecialchars']($boardOptions['moderator_string'], ENT_QUOTES), array('"' => '"')); | |
684 preg_match_all('~"([^"]+)"~', $moderator_string, $matches); | |
685 $moderators = array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $moderator_string))); | |
686 for ($k = 0, $n = count($moderators); $k < $n; $k++) | |
687 { | |
688 $moderators[$k] = trim($moderators[$k]); | |
689 | |
690 if (strlen($moderators[$k]) == 0) | |
691 unset($moderators[$k]); | |
692 } | |
693 | |
694 // Find all the id_member's for the member_name's in the list. | |
695 if (empty($boardOptions['moderators'])) | |
696 $boardOptions['moderators'] = array(); | |
697 if (!empty($moderators)) | |
698 { | |
699 $request = $smcFunc['db_query']('', ' | |
700 SELECT id_member | |
701 FROM {db_prefix}members | |
702 WHERE member_name IN ({array_string:moderator_list}) OR real_name IN ({array_string:moderator_list}) | |
703 LIMIT ' . count($moderators), | |
704 array( | |
705 'moderator_list' => $moderators, | |
706 ) | |
707 ); | |
708 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
709 $boardOptions['moderators'][] = $row['id_member']; | |
710 $smcFunc['db_free_result']($request); | |
711 } | |
712 } | |
713 | |
714 // Add the moderators to the board. | |
715 if (!empty($boardOptions['moderators'])) | |
716 { | |
717 $inserts = array(); | |
718 foreach ($boardOptions['moderators'] as $moderator) | |
719 $inserts[] = array($board_id, $moderator); | |
720 | |
721 $smcFunc['db_insert']('insert', | |
722 '{db_prefix}moderators', | |
723 array('id_board' => 'int', 'id_member' => 'int'), | |
724 $inserts, | |
725 array('id_board', 'id_member') | |
726 ); | |
727 } | |
728 | |
729 // Note that caches can now be wrong! | |
730 updateSettings(array('settings_updated' => time())); | |
731 } | |
732 | |
733 if (isset($boardOptions['move_to'])) | |
734 reorderBoards(); | |
735 | |
736 clean_cache('data'); | |
737 | |
738 if (empty($boardOptions['dont_log'])) | |
739 logAction('edit_board', array('board' => $board_id), 'admin'); | |
740 } | |
741 | |
742 // Create a new board and set its properties and position. | |
743 function createBoard($boardOptions) | |
744 { | |
745 global $boards, $modSettings, $smcFunc; | |
746 | |
747 // Trigger an error if one of the required values is not set. | |
748 if (!isset($boardOptions['board_name']) || trim($boardOptions['board_name']) == '' || !isset($boardOptions['move_to']) || !isset($boardOptions['target_category'])) | |
749 trigger_error('createBoard(): One or more of the required options is not set', E_USER_ERROR); | |
750 | |
751 if (in_array($boardOptions['move_to'], array('child', 'before', 'after')) && !isset($boardOptions['target_board'])) | |
752 trigger_error('createBoard(): Target board is not set', E_USER_ERROR); | |
753 | |
754 // Set every optional value to its default value. | |
755 $boardOptions += array( | |
756 'posts_count' => true, | |
757 'override_theme' => false, | |
758 'board_theme' => 0, | |
759 'access_groups' => array(), | |
760 'board_description' => '', | |
761 'profile' => 1, | |
762 'moderators' => '', | |
763 'inherit_permissions' => true, | |
764 'dont_log' => true, | |
765 ); | |
766 | |
767 // Insert a board, the settings are dealt with later. | |
768 $smcFunc['db_insert']('', | |
769 '{db_prefix}boards', | |
770 array( | |
771 'id_cat' => 'int', 'name' => 'string-255', 'description' => 'string', 'board_order' => 'int', | |
772 'member_groups' => 'string', 'redirect' => 'string', | |
773 ), | |
774 array( | |
775 $boardOptions['target_category'], $boardOptions['board_name'] , '', 0, | |
776 '-1,0', '', | |
777 ), | |
778 array('id_board') | |
779 ); | |
780 $board_id = $smcFunc['db_insert_id']('{db_prefix}boards', 'id_board'); | |
781 | |
782 if (empty($board_id)) | |
783 return 0; | |
784 | |
785 // Change the board according to the given specifications. | |
786 modifyBoard($board_id, $boardOptions); | |
787 | |
788 // Do we want the parent permissions to be inherited? | |
789 if ($boardOptions['inherit_permissions']) | |
790 { | |
791 getBoardTree(); | |
792 | |
793 if (!empty($boards[$board_id]['parent'])) | |
794 { | |
795 $request = $smcFunc['db_query']('', ' | |
796 SELECT id_profile | |
797 FROM {db_prefix}boards | |
798 WHERE id_board = {int:board_parent} | |
799 LIMIT 1', | |
800 array( | |
801 'board_parent' => (int) $boards[$board_id]['parent'], | |
802 ) | |
803 ); | |
804 list ($boardOptions['profile']) = $smcFunc['db_fetch_row']($request); | |
805 $smcFunc['db_free_result']($request); | |
806 | |
807 $smcFunc['db_query']('', ' | |
808 UPDATE {db_prefix}boards | |
809 SET id_profile = {int:new_profile} | |
810 WHERE id_board = {int:current_board}', | |
811 array( | |
812 'new_profile' => $boardOptions['profile'], | |
813 'current_board' => $board_id, | |
814 ) | |
815 ); | |
816 } | |
817 } | |
818 | |
819 // Clean the data cache. | |
820 clean_cache('data'); | |
821 | |
822 // Created it. | |
823 logAction('add_board', array('board' => $board_id), 'admin'); | |
824 | |
825 // Here you are, a new board, ready to be spammed. | |
826 return $board_id; | |
827 } | |
828 | |
829 // Remove one or more boards. | |
830 function deleteBoards($boards_to_remove, $moveChildrenTo = null) | |
831 { | |
832 global $sourcedir, $boards, $smcFunc; | |
833 | |
834 // No boards to delete? Return! | |
835 if (empty($boards_to_remove)) | |
836 return; | |
837 | |
838 getBoardTree(); | |
839 | |
840 // If $moveChildrenTo is set to null, include the children in the removal. | |
841 if ($moveChildrenTo === null) | |
842 { | |
843 // Get a list of the child boards that will also be removed. | |
844 $child_boards_to_remove = array(); | |
845 foreach ($boards_to_remove as $board_to_remove) | |
846 recursiveBoards($child_boards_to_remove, $boards[$board_to_remove]['tree']); | |
847 | |
848 // Merge the children with their parents. | |
849 if (!empty($child_boards_to_remove)) | |
850 $boards_to_remove = array_unique(array_merge($boards_to_remove, $child_boards_to_remove)); | |
851 } | |
852 // Move the children to a safe home. | |
853 else | |
854 { | |
855 foreach ($boards_to_remove as $id_board) | |
856 { | |
857 // !!! Separate category? | |
858 if ($moveChildrenTo === 0) | |
859 fixChildren($id_board, 0, 0); | |
860 else | |
861 fixChildren($id_board, $boards[$moveChildrenTo]['level'] + 1, $moveChildrenTo); | |
862 } | |
863 } | |
864 | |
865 // Delete ALL topics in the selected boards (done first so topics can't be marooned.) | |
866 $request = $smcFunc['db_query']('', ' | |
867 SELECT id_topic | |
868 FROM {db_prefix}topics | |
869 WHERE id_board IN ({array_int:boards_to_remove})', | |
870 array( | |
871 'boards_to_remove' => $boards_to_remove, | |
872 ) | |
873 ); | |
874 $topics = array(); | |
875 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
876 $topics[] = $row['id_topic']; | |
877 $smcFunc['db_free_result']($request); | |
878 | |
879 require_once($sourcedir . '/RemoveTopic.php'); | |
880 removeTopics($topics, false); | |
881 | |
882 // Delete the board's logs. | |
883 $smcFunc['db_query']('', ' | |
884 DELETE FROM {db_prefix}log_mark_read | |
885 WHERE id_board IN ({array_int:boards_to_remove})', | |
886 array( | |
887 'boards_to_remove' => $boards_to_remove, | |
888 ) | |
889 ); | |
890 $smcFunc['db_query']('', ' | |
891 DELETE FROM {db_prefix}log_boards | |
892 WHERE id_board IN ({array_int:boards_to_remove})', | |
893 array( | |
894 'boards_to_remove' => $boards_to_remove, | |
895 ) | |
896 ); | |
897 $smcFunc['db_query']('', ' | |
898 DELETE FROM {db_prefix}log_notify | |
899 WHERE id_board IN ({array_int:boards_to_remove})', | |
900 array( | |
901 'boards_to_remove' => $boards_to_remove, | |
902 ) | |
903 ); | |
904 | |
905 // Delete this board's moderators. | |
906 $smcFunc['db_query']('', ' | |
907 DELETE FROM {db_prefix}moderators | |
908 WHERE id_board IN ({array_int:boards_to_remove})', | |
909 array( | |
910 'boards_to_remove' => $boards_to_remove, | |
911 ) | |
912 ); | |
913 | |
914 // Delete any extra events in the calendar. | |
915 $smcFunc['db_query']('', ' | |
916 DELETE FROM {db_prefix}calendar | |
917 WHERE id_board IN ({array_int:boards_to_remove})', | |
918 array( | |
919 'boards_to_remove' => $boards_to_remove, | |
920 ) | |
921 ); | |
922 | |
923 // Delete any message icons that only appear on these boards. | |
924 $smcFunc['db_query']('', ' | |
925 DELETE FROM {db_prefix}message_icons | |
926 WHERE id_board IN ({array_int:boards_to_remove})', | |
927 array( | |
928 'boards_to_remove' => $boards_to_remove, | |
929 ) | |
930 ); | |
931 | |
932 // Delete the boards. | |
933 $smcFunc['db_query']('', ' | |
934 DELETE FROM {db_prefix}boards | |
935 WHERE id_board IN ({array_int:boards_to_remove})', | |
936 array( | |
937 'boards_to_remove' => $boards_to_remove, | |
938 ) | |
939 ); | |
940 | |
941 // Latest message/topic might not be there anymore. | |
942 updateStats('message'); | |
943 updateStats('topic'); | |
944 updateSettings(array( | |
945 'calendar_updated' => time(), | |
946 )); | |
947 | |
948 // Plus reset the cache to stop people getting odd results. | |
949 updateSettings(array('settings_updated' => time())); | |
950 | |
951 // Clean the cache as well. | |
952 clean_cache('data'); | |
953 | |
954 // Let's do some serious logging. | |
955 foreach ($boards_to_remove as $id_board) | |
956 logAction('delete_board', array('boardname' => $boards[$id_board]['name']), 'admin'); | |
957 | |
958 reorderBoards(); | |
959 } | |
960 | |
961 // Put all boards in the right order. | |
962 function reorderBoards() | |
963 { | |
964 global $cat_tree, $boardList, $boards, $smcFunc; | |
965 | |
966 getBoardTree(); | |
967 | |
968 // Set the board order for each category. | |
969 $board_order = 0; | |
970 foreach ($cat_tree as $catID => $dummy) | |
971 { | |
972 foreach ($boardList[$catID] as $boardID) | |
973 if ($boards[$boardID]['order'] != ++$board_order) | |
974 $smcFunc['db_query']('', ' | |
975 UPDATE {db_prefix}boards | |
976 SET board_order = {int:new_order} | |
977 WHERE id_board = {int:selected_board}', | |
978 array( | |
979 'new_order' => $board_order, | |
980 'selected_board' => $boardID, | |
981 ) | |
982 ); | |
983 } | |
984 | |
985 // Sort the records of the boards table on the board_order value. | |
986 $smcFunc['db_query']('alter_table_boards', ' | |
987 ALTER TABLE {db_prefix}boards | |
988 ORDER BY board_order', | |
989 array( | |
990 'db_error_skip' => true, | |
991 ) | |
992 ); | |
993 } | |
994 | |
995 // Fixes the children of a board by setting their child_levels to new values. | |
996 function fixChildren($parent, $newLevel, $newParent) | |
997 { | |
998 global $smcFunc; | |
999 | |
1000 // Grab all children of $parent... | |
1001 $result = $smcFunc['db_query']('', ' | |
1002 SELECT id_board | |
1003 FROM {db_prefix}boards | |
1004 WHERE id_parent = {int:parent_board}', | |
1005 array( | |
1006 'parent_board' => $parent, | |
1007 ) | |
1008 ); | |
1009 $children = array(); | |
1010 while ($row = $smcFunc['db_fetch_assoc']($result)) | |
1011 $children[] = $row['id_board']; | |
1012 $smcFunc['db_free_result']($result); | |
1013 | |
1014 // ...and set it to a new parent and child_level. | |
1015 $smcFunc['db_query']('', ' | |
1016 UPDATE {db_prefix}boards | |
1017 SET id_parent = {int:new_parent}, child_level = {int:new_child_level} | |
1018 WHERE id_parent = {int:parent_board}', | |
1019 array( | |
1020 'new_parent' => $newParent, | |
1021 'new_child_level' => $newLevel, | |
1022 'parent_board' => $parent, | |
1023 ) | |
1024 ); | |
1025 | |
1026 // Recursively fix the children of the children. | |
1027 foreach ($children as $child) | |
1028 fixChildren($child, $newLevel + 1, $child); | |
1029 } | |
1030 | |
1031 // Load a lot of useful information regarding the boards and categories. | |
1032 function getBoardTree() | |
1033 { | |
1034 global $cat_tree, $boards, $boardList, $txt, $modSettings, $smcFunc; | |
1035 | |
1036 // Getting all the board and category information you'd ever wanted. | |
1037 $request = $smcFunc['db_query']('', ' | |
1038 SELECT | |
1039 IFNULL(b.id_board, 0) AS id_board, b.id_parent, b.name AS board_name, b.description, b.child_level, | |
1040 b.board_order, b.count_posts, b.member_groups, b.id_theme, b.override_theme, b.id_profile, b.redirect, | |
1041 b.num_posts, b.num_topics, c.id_cat, c.name AS cat_name, c.cat_order, c.can_collapse | |
1042 FROM {db_prefix}categories AS c | |
1043 LEFT JOIN {db_prefix}boards AS b ON (b.id_cat = c.id_cat) | |
1044 ORDER BY c.cat_order, b.child_level, b.board_order', | |
1045 array( | |
1046 ) | |
1047 ); | |
1048 $cat_tree = array(); | |
1049 $boards = array(); | |
1050 $last_board_order = 0; | |
1051 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
1052 { | |
1053 if (!isset($cat_tree[$row['id_cat']])) | |
1054 { | |
1055 $cat_tree[$row['id_cat']] = array( | |
1056 'node' => array( | |
1057 'id' => $row['id_cat'], | |
1058 'name' => $row['cat_name'], | |
1059 'order' => $row['cat_order'], | |
1060 'can_collapse' => $row['can_collapse'] | |
1061 ), | |
1062 'is_first' => empty($cat_tree), | |
1063 'last_board_order' => $last_board_order, | |
1064 'children' => array() | |
1065 ); | |
1066 $prevBoard = 0; | |
1067 $curLevel = 0; | |
1068 } | |
1069 | |
1070 if (!empty($row['id_board'])) | |
1071 { | |
1072 if ($row['child_level'] != $curLevel) | |
1073 $prevBoard = 0; | |
1074 | |
1075 $boards[$row['id_board']] = array( | |
1076 'id' => $row['id_board'], | |
1077 'category' => $row['id_cat'], | |
1078 'parent' => $row['id_parent'], | |
1079 'level' => $row['child_level'], | |
1080 'order' => $row['board_order'], | |
1081 'name' => $row['board_name'], | |
1082 'member_groups' => explode(',', $row['member_groups']), | |
1083 'description' => $row['description'], | |
1084 'count_posts' => empty($row['count_posts']), | |
1085 'posts' => $row['num_posts'], | |
1086 'topics' => $row['num_topics'], | |
1087 'theme' => $row['id_theme'], | |
1088 'override_theme' => $row['override_theme'], | |
1089 'profile' => $row['id_profile'], | |
1090 'redirect' => $row['redirect'], | |
1091 'prev_board' => $prevBoard | |
1092 ); | |
1093 $prevBoard = $row['id_board']; | |
1094 $last_board_order = $row['board_order']; | |
1095 | |
1096 if (empty($row['child_level'])) | |
1097 { | |
1098 $cat_tree[$row['id_cat']]['children'][$row['id_board']] = array( | |
1099 'node' => &$boards[$row['id_board']], | |
1100 'is_first' => empty($cat_tree[$row['id_cat']]['children']), | |
1101 'children' => array() | |
1102 ); | |
1103 $boards[$row['id_board']]['tree'] = &$cat_tree[$row['id_cat']]['children'][$row['id_board']]; | |
1104 } | |
1105 else | |
1106 { | |
1107 // Parent doesn't exist! | |
1108 if (!isset($boards[$row['id_parent']]['tree'])) | |
1109 fatal_lang_error('no_valid_parent', false, array($row['board_name'])); | |
1110 | |
1111 // Wrong childlevel...we can silently fix this... | |
1112 if ($boards[$row['id_parent']]['tree']['node']['level'] != $row['child_level'] - 1) | |
1113 $smcFunc['db_query']('', ' | |
1114 UPDATE {db_prefix}boards | |
1115 SET child_level = {int:new_child_level} | |
1116 WHERE id_board = {int:selected_board}', | |
1117 array( | |
1118 'new_child_level' => $boards[$row['id_parent']]['tree']['node']['level'] + 1, | |
1119 'selected_board' => $row['id_board'], | |
1120 ) | |
1121 ); | |
1122 | |
1123 $boards[$row['id_parent']]['tree']['children'][$row['id_board']] = array( | |
1124 'node' => &$boards[$row['id_board']], | |
1125 'is_first' => empty($boards[$row['id_parent']]['tree']['children']), | |
1126 'children' => array() | |
1127 ); | |
1128 $boards[$row['id_board']]['tree'] = &$boards[$row['id_parent']]['tree']['children'][$row['id_board']]; | |
1129 } | |
1130 } | |
1131 } | |
1132 $smcFunc['db_free_result']($request); | |
1133 | |
1134 // Get a list of all the boards in each category (using recursion). | |
1135 $boardList = array(); | |
1136 foreach ($cat_tree as $catID => $node) | |
1137 { | |
1138 $boardList[$catID] = array(); | |
1139 recursiveBoards($boardList[$catID], $node); | |
1140 } | |
1141 } | |
1142 | |
1143 // Recursively get a list of boards. | |
1144 function recursiveBoards(&$_boardList, &$_tree) | |
1145 { | |
1146 if (empty($_tree['children'])) | |
1147 return; | |
1148 | |
1149 foreach ($_tree['children'] as $id => $node) | |
1150 { | |
1151 $_boardList[] = $id; | |
1152 recursiveBoards($_boardList, $node); | |
1153 } | |
1154 } | |
1155 | |
1156 // Returns whether the child board id is actually a child of the parent (recursive). | |
1157 function isChildOf($child, $parent) | |
1158 { | |
1159 global $boards; | |
1160 | |
1161 if (empty($boards[$child]['parent'])) | |
1162 return false; | |
1163 | |
1164 if ($boards[$child]['parent'] == $parent) | |
1165 return true; | |
1166 | |
1167 return isChildOf($boards[$child]['parent'], $parent); | |
1168 } | |
1169 | |
1170 ?> |