1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Manage and maintain the boards and categories of the forum. |
||
5 | * |
||
6 | * Simple Machines Forum (SMF) |
||
7 | * |
||
8 | * @package SMF |
||
9 | * @author Simple Machines https://www.simplemachines.org |
||
10 | * @copyright 2022 Simple Machines and individual contributors |
||
11 | * @license https://www.simplemachines.org/about/smf/license.php BSD |
||
12 | * |
||
13 | * @version 2.1.0 |
||
14 | */ |
||
15 | |||
16 | if (!defined('SMF')) |
||
17 | die('No direct access...'); |
||
18 | |||
19 | /** |
||
20 | * The main dispatcher; doesn't do anything, just delegates. |
||
21 | * This is the main entry point for all the manageboards admin screens. |
||
22 | * Called by ?action=admin;area=manageboards. |
||
23 | * It checks the permissions, based on the sub-action, and calls a function based on the sub-action. |
||
24 | * |
||
25 | * Uses ManageBoards language file. |
||
26 | */ |
||
27 | function ManageBoards() |
||
28 | { |
||
29 | global $context, $txt; |
||
30 | |||
31 | // Everything's gonna need this. |
||
32 | loadLanguage('ManageBoards'); |
||
33 | |||
34 | // Format: 'sub-action' => array('function', 'permission') |
||
35 | $subActions = array( |
||
36 | 'board' => array('EditBoard', 'manage_boards'), |
||
37 | 'board2' => array('EditBoard2', 'manage_boards'), |
||
38 | 'cat' => array('EditCategory', 'manage_boards'), |
||
39 | 'cat2' => array('EditCategory2', 'manage_boards'), |
||
40 | 'main' => array('ManageBoardsMain', 'manage_boards'), |
||
41 | 'move' => array('ManageBoardsMain', 'manage_boards'), |
||
42 | 'newcat' => array('EditCategory', 'manage_boards'), |
||
43 | 'newboard' => array('EditBoard', 'manage_boards'), |
||
44 | 'settings' => array('EditBoardSettings', 'admin_forum'), |
||
45 | ); |
||
46 | |||
47 | // Create the tabs for the template. |
||
48 | $context[$context['admin_menu_name']]['tab_data'] = array( |
||
49 | 'title' => $txt['boards_and_cats'], |
||
50 | 'help' => 'manage_boards', |
||
51 | 'description' => $txt['boards_and_cats_desc'], |
||
52 | 'tabs' => array( |
||
53 | 'main' => array( |
||
54 | ), |
||
55 | 'newcat' => array( |
||
56 | ), |
||
57 | 'settings' => array( |
||
58 | 'description' => $txt['mboards_settings_desc'], |
||
59 | ), |
||
60 | ), |
||
61 | ); |
||
62 | |||
63 | call_integration_hook('integrate_manage_boards', array(&$subActions)); |
||
64 | |||
65 | // Default to sub action 'main' or 'settings' depending on permissions. |
||
66 | $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : (allowedTo('manage_boards') ? 'main' : 'settings'); |
||
67 | |||
68 | // Have you got the proper permissions? |
||
69 | isAllowedTo($subActions[$_REQUEST['sa']][1]); |
||
70 | |||
71 | call_helper($subActions[$_REQUEST['sa']][0]); |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * The main control panel thing, the screen showing all boards and categories. |
||
76 | * Called by ?action=admin;area=manageboards or ?action=admin;area=manageboards;sa=move. |
||
77 | * Requires manage_boards permission. |
||
78 | * It also handles the interface for moving boards. |
||
79 | * |
||
80 | * Uses ManageBoards template, main sub-template. |
||
81 | */ |
||
82 | function ManageBoardsMain() |
||
83 | { |
||
84 | global $txt, $context, $cat_tree, $boards, $boardList, $scripturl, $sourcedir, $smcFunc; |
||
85 | |||
86 | loadTemplate('ManageBoards'); |
||
87 | |||
88 | require_once($sourcedir . '/Subs-Boards.php'); |
||
89 | |||
90 | if (isset($_REQUEST['sa']) && $_REQUEST['sa'] == 'move' && in_array($_REQUEST['move_to'], array('child', 'before', 'after', 'top'))) |
||
91 | { |
||
92 | checkSession('get'); |
||
93 | validateToken('admin-bm-' . (int) $_REQUEST['src_board'], 'request'); |
||
94 | |||
95 | if ($_REQUEST['move_to'] === 'top') |
||
96 | $boardOptions = array( |
||
97 | 'move_to' => $_REQUEST['move_to'], |
||
98 | 'target_category' => (int) $_REQUEST['target_cat'], |
||
99 | 'move_first_child' => true, |
||
100 | ); |
||
101 | else |
||
102 | $boardOptions = array( |
||
103 | 'move_to' => $_REQUEST['move_to'], |
||
104 | 'target_board' => (int) $_REQUEST['target_board'], |
||
105 | 'move_first_child' => true, |
||
106 | ); |
||
107 | modifyBoard((int) $_REQUEST['src_board'], $boardOptions); |
||
108 | } |
||
109 | |||
110 | getBoardTree(); |
||
111 | |||
112 | $context['move_board'] = !empty($_REQUEST['move']) && isset($boards[(int) $_REQUEST['move']]) ? (int) $_REQUEST['move'] : 0; |
||
113 | |||
114 | $context['categories'] = array(); |
||
115 | foreach ($cat_tree as $catid => $tree) |
||
116 | { |
||
117 | $context['categories'][$catid] = array( |
||
118 | 'name' => &$tree['node']['name'], |
||
119 | 'id' => &$tree['node']['id'], |
||
120 | 'boards' => array() |
||
121 | ); |
||
122 | $move_cat = !empty($context['move_board']) && $boards[$context['move_board']]['category'] == $catid; |
||
123 | foreach ($boardList[$catid] as $boardid) |
||
124 | { |
||
125 | $context['categories'][$catid]['boards'][$boardid] = array( |
||
126 | 'id' => &$boards[$boardid]['id'], |
||
127 | 'name' => &$boards[$boardid]['name'], |
||
128 | 'description' => &$boards[$boardid]['description'], |
||
129 | 'child_level' => &$boards[$boardid]['level'], |
||
130 | 'move' => $move_cat && ($boardid == $context['move_board'] || isChildOf($boardid, $context['move_board'])), |
||
131 | 'permission_profile' => &$boards[$boardid]['profile'], |
||
132 | 'is_redirect' => !empty($boards[$boardid]['redirect']), |
||
133 | ); |
||
134 | } |
||
135 | } |
||
136 | |||
137 | if (!empty($context['move_board'])) |
||
138 | { |
||
139 | createToken('admin-bm-' . $context['move_board'], 'request'); |
||
140 | |||
141 | $context['move_title'] = sprintf($txt['mboards_select_destination'], $smcFunc['htmlspecialchars']($boards[$context['move_board']]['name'])); |
||
142 | foreach ($cat_tree as $catid => $tree) |
||
143 | { |
||
144 | $prev_child_level = 0; |
||
145 | $prev_board = 0; |
||
146 | $stack = array(); |
||
147 | // Just a shortcut, this is the same for all the urls |
||
148 | $security = $context['session_var'] . '=' . $context['session_id'] . ';' . $context['admin-bm-' . $context['move_board'] . '_token_var'] . '=' . $context['admin-bm-' . $context['move_board'] . '_token']; |
||
149 | foreach ($boardList[$catid] as $boardid) |
||
150 | { |
||
151 | if (!isset($context['categories'][$catid]['move_link'])) |
||
152 | $context['categories'][$catid]['move_link'] = array( |
||
153 | 'child_level' => 0, |
||
154 | 'label' => $txt['mboards_order_before'] . ' \'' . $smcFunc['htmlspecialchars']($boards[$boardid]['name']) . '\'', |
||
155 | 'href' => $scripturl . '?action=admin;area=manageboards;sa=move;src_board=' . $context['move_board'] . ';target_board=' . $boardid . ';move_to=before;' . $security, |
||
156 | ); |
||
157 | |||
158 | if (!$context['categories'][$catid]['boards'][$boardid]['move']) |
||
159 | $context['categories'][$catid]['boards'][$boardid]['move_links'] = array( |
||
160 | array( |
||
161 | 'child_level' => $boards[$boardid]['level'], |
||
162 | 'label' => $txt['mboards_order_after'] . '\'' . $smcFunc['htmlspecialchars']($boards[$boardid]['name']) . '\'', |
||
163 | 'href' => $scripturl . '?action=admin;area=manageboards;sa=move;src_board=' . $context['move_board'] . ';target_board=' . $boardid . ';move_to=after;' . $security, |
||
164 | 'class' => $boards[$boardid]['level'] > 0 ? 'above' : 'below', |
||
165 | ), |
||
166 | array( |
||
167 | 'child_level' => $boards[$boardid]['level'] + 1, |
||
168 | 'label' => $txt['mboards_order_child_of'] . ' \'' . $smcFunc['htmlspecialchars']($boards[$boardid]['name']) . '\'', |
||
169 | 'href' => $scripturl . '?action=admin;area=manageboards;sa=move;src_board=' . $context['move_board'] . ';target_board=' . $boardid . ';move_to=child;' . $security, |
||
170 | 'class' => 'here', |
||
171 | ), |
||
172 | ); |
||
173 | |||
174 | $difference = $boards[$boardid]['level'] - $prev_child_level; |
||
175 | if ($difference == 1) |
||
176 | array_push($stack, !empty($context['categories'][$catid]['boards'][$prev_board]['move_links']) ? array_shift($context['categories'][$catid]['boards'][$prev_board]['move_links']) : null); |
||
177 | elseif ($difference < 0) |
||
178 | { |
||
179 | if (empty($context['categories'][$catid]['boards'][$prev_board]['move_links'])) |
||
180 | $context['categories'][$catid]['boards'][$prev_board]['move_links'] = array(); |
||
181 | for ($i = 0; $i < -$difference; $i++) |
||
182 | if (($temp = array_pop($stack)) != null) |
||
183 | array_unshift($context['categories'][$catid]['boards'][$prev_board]['move_links'], $temp); |
||
184 | } |
||
185 | |||
186 | $prev_board = $boardid; |
||
187 | $prev_child_level = $boards[$boardid]['level']; |
||
188 | } |
||
189 | if (!empty($stack) && !empty($context['categories'][$catid]['boards'][$prev_board]['move_links'])) |
||
190 | $context['categories'][$catid]['boards'][$prev_board]['move_links'] = array_merge($stack, $context['categories'][$catid]['boards'][$prev_board]['move_links']); |
||
191 | elseif (!empty($stack)) |
||
192 | $context['categories'][$catid]['boards'][$prev_board]['move_links'] = $stack; |
||
193 | |||
194 | if (empty($boardList[$catid])) |
||
195 | $context['categories'][$catid]['move_link'] = array( |
||
196 | 'child_level' => 0, |
||
197 | 'label' => $txt['mboards_order_before'] . ' \'' . $smcFunc['htmlspecialchars']($tree['node']['name']) . '\'', |
||
198 | 'href' => $scripturl . '?action=admin;area=manageboards;sa=move;src_board=' . $context['move_board'] . ';target_cat=' . $catid . ';move_to=top;' . $security, |
||
199 | ); |
||
200 | } |
||
201 | } |
||
202 | |||
203 | call_integration_hook('integrate_boards_main'); |
||
204 | |||
205 | $context['page_title'] = $txt['boards_and_cats']; |
||
206 | $context['can_manage_permissions'] = allowedTo('manage_permissions'); |
||
207 | } |
||
208 | |||
209 | /** |
||
210 | * Modify a specific category. |
||
211 | * (screen for editing and repositioning a category.) |
||
212 | * Also used to show the confirm deletion of category screen |
||
213 | * (sub-template confirm_category_delete). |
||
214 | * Called by ?action=admin;area=manageboards;sa=cat |
||
215 | * Requires manage_boards permission. |
||
216 | * |
||
217 | * @uses template_modify_category() |
||
218 | */ |
||
219 | function EditCategory() |
||
220 | { |
||
221 | global $txt, $context, $cat_tree, $boardList, $boards, $smcFunc, $sourcedir; |
||
222 | |||
223 | loadTemplate('ManageBoards'); |
||
224 | require_once($sourcedir . '/Subs-Boards.php'); |
||
225 | require_once($sourcedir . '/Subs-Editor.php'); |
||
226 | getBoardTree(); |
||
227 | |||
228 | // id_cat must be a number.... if it exists. |
||
229 | $_REQUEST['cat'] = isset($_REQUEST['cat']) ? (int) $_REQUEST['cat'] : 0; |
||
230 | |||
231 | // Start with one - "In first place". |
||
232 | $context['category_order'] = array( |
||
233 | array( |
||
234 | 'id' => 0, |
||
235 | 'name' => $txt['mboards_order_first'], |
||
236 | 'selected' => !empty($_REQUEST['cat']) ? $cat_tree[$_REQUEST['cat']]['is_first'] : false, |
||
237 | 'true_name' => '' |
||
238 | ) |
||
239 | ); |
||
240 | |||
241 | // If this is a new category set up some defaults. |
||
242 | if ($_REQUEST['sa'] == 'newcat') |
||
243 | { |
||
244 | $context['category'] = array( |
||
245 | 'id' => 0, |
||
246 | 'name' => $txt['mboards_new_cat_name'], |
||
247 | 'editable_name' => $smcFunc['htmlspecialchars']($txt['mboards_new_cat_name']), |
||
248 | 'description' => '', |
||
249 | 'can_collapse' => true, |
||
250 | 'is_new' => true, |
||
251 | 'is_empty' => true |
||
252 | ); |
||
253 | } |
||
254 | // Category doesn't exist, man... sorry. |
||
255 | elseif (!isset($cat_tree[$_REQUEST['cat']])) |
||
256 | redirectexit('action=admin;area=manageboards'); |
||
257 | else |
||
258 | { |
||
259 | $context['category'] = array( |
||
260 | 'id' => $_REQUEST['cat'], |
||
261 | 'name' => $cat_tree[$_REQUEST['cat']]['node']['name'], |
||
262 | 'editable_name' => $cat_tree[$_REQUEST['cat']]['node']['name'], |
||
263 | 'description' => $cat_tree[$_REQUEST['cat']]['node']['description'], |
||
264 | 'can_collapse' => !empty($cat_tree[$_REQUEST['cat']]['node']['can_collapse']), |
||
265 | 'children' => array(), |
||
266 | 'is_empty' => empty($cat_tree[$_REQUEST['cat']]['children']) |
||
267 | ); |
||
268 | |||
269 | foreach ($boardList[$_REQUEST['cat']] as $child_board) |
||
270 | $context['category']['children'][] = str_repeat('-', $boards[$child_board]['level']) . ' ' . $boards[$child_board]['name']; |
||
271 | } |
||
272 | |||
273 | $prevCat = 0; |
||
274 | foreach ($cat_tree as $catid => $tree) |
||
275 | { |
||
276 | if ($catid == $_REQUEST['cat'] && $prevCat > 0) |
||
277 | $context['category_order'][$prevCat]['selected'] = true; |
||
278 | elseif ($catid != $_REQUEST['cat']) |
||
279 | $context['category_order'][$catid] = array( |
||
280 | 'id' => $catid, |
||
281 | 'name' => $txt['mboards_order_after'] . $tree['node']['name'], |
||
282 | 'selected' => false, |
||
283 | 'true_name' => $tree['node']['name'] |
||
284 | ); |
||
285 | $prevCat = $catid; |
||
286 | } |
||
287 | if (!isset($_REQUEST['delete'])) |
||
288 | { |
||
289 | $context['sub_template'] = 'modify_category'; |
||
290 | $context['page_title'] = $_REQUEST['sa'] == 'newcat' ? $txt['mboards_new_cat_name'] : $txt['cat_edit']; |
||
291 | } |
||
292 | else |
||
293 | { |
||
294 | $context['sub_template'] = 'confirm_category_delete'; |
||
295 | $context['page_title'] = $txt['mboards_delete_cat']; |
||
296 | } |
||
297 | |||
298 | // Create a special token. |
||
299 | createToken('admin-bc-' . $_REQUEST['cat']); |
||
300 | $context['token_check'] = 'admin-bc-' . $_REQUEST['cat']; |
||
301 | |||
302 | call_integration_hook('integrate_edit_category'); |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * Function for handling a submitted form saving the category. |
||
307 | * (complete the modifications to a specific category.) |
||
308 | * It also handles deletion of a category. |
||
309 | * It requires manage_boards permission. |
||
310 | * Called by ?action=admin;area=manageboards;sa=cat2 |
||
311 | * Redirects to ?action=admin;area=manageboards. |
||
312 | */ |
||
313 | function EditCategory2() |
||
314 | { |
||
315 | global $sourcedir, $smcFunc, $context; |
||
316 | |||
317 | checkSession(); |
||
318 | validateToken('admin-bc-' . $_REQUEST['cat']); |
||
319 | |||
320 | require_once($sourcedir . '/Subs-Categories.php'); |
||
321 | require_once($sourcedir . '/Subs-Editor.php'); |
||
322 | |||
323 | $_POST['cat'] = (int) $_POST['cat']; |
||
324 | |||
325 | // Add a new category or modify an existing one.. |
||
326 | if (isset($_POST['edit']) || isset($_POST['add'])) |
||
327 | { |
||
328 | $catOptions = array(); |
||
329 | |||
330 | if (isset($_POST['cat_order'])) |
||
331 | $catOptions['move_after'] = (int) $_POST['cat_order']; |
||
332 | |||
333 | // Try and get any valid HTML to BBC first, add a naive attempt to strip it off, htmlspecialchars for the rest |
||
334 | $catOptions['cat_name'] = $smcFunc['htmlspecialchars'](strip_tags($_POST['cat_name'])); |
||
335 | $catOptions['cat_desc'] = $smcFunc['htmlspecialchars'](strip_tags(html_to_bbc($_POST['cat_desc']))); |
||
336 | $catOptions['is_collapsible'] = isset($_POST['collapse']); |
||
337 | |||
338 | if (isset($_POST['add'])) |
||
339 | createCategory($catOptions); |
||
340 | |||
341 | else |
||
342 | modifyCategory($_POST['cat'], $catOptions); |
||
343 | } |
||
344 | // If they want to delete - first give them confirmation. |
||
345 | elseif (isset($_POST['delete']) && !isset($_POST['confirmation']) && !isset($_POST['empty'])) |
||
346 | { |
||
347 | EditCategory(); |
||
348 | return; |
||
349 | } |
||
350 | // Delete the category! |
||
351 | elseif (isset($_POST['delete'])) |
||
352 | { |
||
353 | // First off - check if we are moving all the current boards first - before we start deleting! |
||
354 | if (isset($_POST['delete_action']) && $_POST['delete_action'] == 1) |
||
355 | { |
||
356 | if (empty($_POST['cat_to'])) |
||
357 | fatal_lang_error('mboards_delete_error'); |
||
358 | |||
359 | deleteCategories(array($_POST['cat']), (int) $_POST['cat_to']); |
||
360 | } |
||
361 | else |
||
362 | deleteCategories(array($_POST['cat'])); |
||
363 | } |
||
364 | |||
365 | redirectexit('action=admin;area=manageboards'); |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Modify a specific board... |
||
370 | * screen for editing and repositioning a board. |
||
371 | * called by ?action=admin;area=manageboards;sa=board |
||
372 | * uses the modify_board sub-template of the ManageBoards template. |
||
373 | * requires manage_boards permission. |
||
374 | * also used to show the confirm deletion of category screen (sub-template confirm_board_delete). |
||
375 | */ |
||
376 | function EditBoard() |
||
377 | { |
||
378 | global $txt, $context, $cat_tree, $boards, $boardList; |
||
379 | global $sourcedir, $smcFunc, $modSettings; |
||
380 | |||
381 | loadTemplate('ManageBoards'); |
||
382 | require_once($sourcedir . '/Subs-Boards.php'); |
||
383 | require_once($sourcedir . '/Subs-Editor.php'); |
||
384 | getBoardTree(); |
||
385 | |||
386 | // For editing the profile we'll need this. |
||
387 | loadLanguage('ManagePermissions'); |
||
388 | require_once($sourcedir . '/ManagePermissions.php'); |
||
389 | loadPermissionProfiles(); |
||
390 | |||
391 | // People with manage-boards are special. |
||
392 | require_once($sourcedir . '/Subs-Members.php'); |
||
393 | $groups = groupsAllowedTo('manage_boards', null); |
||
394 | $context['board_managers'] = $groups['allowed']; // We don't need *all* this in $context. |
||
395 | |||
396 | // id_board must be a number.... |
||
397 | $_REQUEST['boardid'] = isset($_REQUEST['boardid']) ? (int) $_REQUEST['boardid'] : 0; |
||
398 | |||
399 | if (!isset($boards[$_REQUEST['boardid']])) |
||
400 | { |
||
401 | $_REQUEST['boardid'] = 0; |
||
402 | $_REQUEST['sa'] = 'newboard'; |
||
403 | } |
||
404 | |||
405 | if ('newboard' === $_REQUEST['sa']) |
||
406 | { |
||
407 | // Category doesn't exist, man... sorry. |
||
408 | if (empty($_REQUEST['cat'])) |
||
409 | redirectexit('action=admin;area=manageboards'); |
||
410 | |||
411 | // Some things that need to be setup for a new board. |
||
412 | $curBoard = array( |
||
413 | 'member_groups' => array(0, -1), |
||
414 | 'deny_groups' => array(), |
||
415 | 'category' => (int) $_REQUEST['cat'] |
||
416 | ); |
||
417 | $context['board_order'] = array(); |
||
418 | $context['board'] = array( |
||
419 | 'is_new' => true, |
||
420 | 'id' => 0, |
||
421 | 'name' => $txt['mboards_new_board_name'], |
||
422 | 'description' => '', |
||
423 | 'count_posts' => 1, |
||
424 | 'posts' => 0, |
||
425 | 'topics' => 0, |
||
426 | 'theme' => 0, |
||
427 | 'profile' => 1, |
||
428 | 'override_theme' => 0, |
||
429 | 'redirect' => '', |
||
430 | 'category' => (int) $_REQUEST['cat'], |
||
431 | 'no_children' => true, |
||
432 | ); |
||
433 | } |
||
434 | else |
||
435 | { |
||
436 | // Just some easy shortcuts. |
||
437 | $curBoard = &$boards[$_REQUEST['boardid']]; |
||
438 | $context['board'] = $boards[$_REQUEST['boardid']]; |
||
439 | $context['board']['no_children'] = empty($boards[$_REQUEST['boardid']]['tree']['children']); |
||
440 | $context['board']['is_recycle'] = !empty($modSettings['recycle_enable']) && !empty($modSettings['recycle_board']) && $modSettings['recycle_board'] == $context['board']['id']; |
||
441 | } |
||
442 | |||
443 | // As we may have come from the permissions screen keep track of where we should go on save. |
||
444 | $context['redirect_location'] = isset($_GET['rid']) && $_GET['rid'] == 'permissions' ? 'permissions' : 'boards'; |
||
445 | |||
446 | // We might need this to hide links to certain areas. |
||
447 | $context['can_manage_permissions'] = allowedTo('manage_permissions'); |
||
448 | |||
449 | // Default membergroups. |
||
450 | $context['groups'] = array( |
||
451 | -1 => array( |
||
452 | 'id' => '-1', |
||
453 | 'name' => $txt['parent_guests_only'], |
||
454 | 'allow' => in_array('-1', $curBoard['member_groups']), |
||
455 | 'deny' => in_array('-1', $curBoard['deny_groups']), |
||
456 | 'is_post_group' => false, |
||
457 | ), |
||
458 | 0 => array( |
||
459 | 'id' => '0', |
||
460 | 'name' => $txt['parent_members_only'], |
||
461 | 'allow' => in_array('0', $curBoard['member_groups']), |
||
462 | 'deny' => in_array('0', $curBoard['deny_groups']), |
||
463 | 'is_post_group' => false, |
||
464 | ) |
||
465 | ); |
||
466 | |||
467 | // Load membergroups. |
||
468 | $request = $smcFunc['db_query']('', ' |
||
469 | SELECT group_name, id_group, min_posts |
||
470 | FROM {db_prefix}membergroups |
||
471 | WHERE id_group > {int:moderator_group} OR id_group = {int:global_moderator} |
||
472 | ORDER BY min_posts, id_group != {int:global_moderator}, group_name', |
||
473 | array( |
||
474 | 'moderator_group' => 3, |
||
475 | 'global_moderator' => 2, |
||
476 | ) |
||
477 | ); |
||
478 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
479 | { |
||
480 | if ($_REQUEST['sa'] == 'newboard' && $row['min_posts'] == -1) |
||
481 | $curBoard['member_groups'][] = $row['id_group']; |
||
482 | |||
483 | $context['groups'][(int) $row['id_group']] = array( |
||
484 | 'id' => $row['id_group'], |
||
485 | 'name' => trim($row['group_name']), |
||
486 | 'allow' => in_array($row['id_group'], $curBoard['member_groups']), |
||
487 | 'deny' => in_array($row['id_group'], $curBoard['deny_groups']), |
||
488 | 'is_post_group' => $row['min_posts'] != -1, |
||
489 | ); |
||
490 | } |
||
491 | $smcFunc['db_free_result']($request); |
||
492 | |||
493 | // Category doesn't exist, man... sorry. |
||
494 | if (!isset($boardList[$curBoard['category']])) |
||
495 | redirectexit('action=admin;area=manageboards'); |
||
496 | |||
497 | foreach ($boardList[$curBoard['category']] as $boardid) |
||
498 | { |
||
499 | if ($boardid == $_REQUEST['boardid']) |
||
500 | { |
||
501 | $context['board_order'][] = array( |
||
502 | 'id' => $boardid, |
||
503 | 'name' => str_repeat('-', $boards[$boardid]['level']) . ' (' . $txt['mboards_current_position'] . ')', |
||
504 | 'children' => $boards[$boardid]['tree']['children'], |
||
505 | 'no_children' => empty($boards[$boardid]['tree']['children']), |
||
506 | 'is_child' => false, |
||
507 | 'selected' => true |
||
508 | ); |
||
509 | } |
||
510 | else |
||
511 | { |
||
512 | $context['board_order'][] = array( |
||
513 | 'id' => $boardid, |
||
514 | 'name' => str_repeat('-', $boards[$boardid]['level']) . ' ' . $boards[$boardid]['name'], |
||
515 | 'is_child' => empty($_REQUEST['boardid']) ? false : isChildOf($boardid, $_REQUEST['boardid']), |
||
516 | 'selected' => false |
||
517 | ); |
||
518 | } |
||
519 | } |
||
520 | |||
521 | // Are there any places to move child boards to in the case where we are confirming a delete? |
||
522 | if (!empty($_REQUEST['boardid'])) |
||
523 | { |
||
524 | $context['can_move_children'] = false; |
||
525 | $context['children'] = $boards[$_REQUEST['boardid']]['tree']['children']; |
||
526 | |||
527 | foreach ($context['board_order'] as $lBoard) |
||
528 | if ($lBoard['is_child'] == false && $lBoard['selected'] == false) |
||
529 | $context['can_move_children'] = true; |
||
530 | } |
||
531 | |||
532 | // Get other available categories. |
||
533 | $context['categories'] = array(); |
||
534 | foreach ($cat_tree as $catID => $tree) |
||
535 | $context['categories'][] = array( |
||
536 | 'id' => $catID == $curBoard['category'] ? 0 : $catID, |
||
537 | 'name' => $tree['node']['name'], |
||
538 | 'selected' => $catID == $curBoard['category'] |
||
539 | ); |
||
540 | |||
541 | $request = $smcFunc['db_query']('', ' |
||
542 | SELECT mem.id_member, mem.real_name |
||
543 | FROM {db_prefix}moderators AS mods |
||
544 | INNER JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member) |
||
545 | WHERE mods.id_board = {int:current_board}', |
||
546 | array( |
||
547 | 'current_board' => $_REQUEST['boardid'], |
||
548 | ) |
||
549 | ); |
||
550 | $context['board']['moderators'] = array(); |
||
551 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
552 | $context['board']['moderators'][$row['id_member']] = $row['real_name']; |
||
553 | $smcFunc['db_free_result']($request); |
||
554 | |||
555 | $context['board']['moderator_list'] = empty($context['board']['moderators']) ? '' : '"' . implode('", "', $context['board']['moderators']) . '"'; |
||
556 | |||
557 | if (!empty($context['board']['moderators'])) |
||
558 | list ($context['board']['last_moderator_id']) = array_slice(array_keys($context['board']['moderators']), -1); |
||
559 | |||
560 | // Get all the groups assigned as moderators |
||
561 | $request = $smcFunc['db_query']('', ' |
||
562 | SELECT id_group |
||
563 | FROM {db_prefix}moderator_groups |
||
564 | WHERE id_board = {int:current_board}', |
||
565 | array( |
||
566 | 'current_board' => $_REQUEST['boardid'], |
||
567 | ) |
||
568 | ); |
||
569 | $context['board']['moderator_groups'] = array(); |
||
570 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
571 | $context['board']['moderator_groups'][$row['id_group']] = $context['groups'][$row['id_group']]['name']; |
||
572 | $smcFunc['db_free_result']($request); |
||
573 | |||
574 | $context['board']['moderator_groups_list'] = empty($context['board']['moderator_groups']) ? '' : '"' . implode('", &qout;', $context['board']['moderator_groups']) . '"'; |
||
575 | |||
576 | if (!empty($context['board']['moderator_groups'])) |
||
577 | list ($context['board']['last_moderator_group_id']) = array_slice(array_keys($context['board']['moderator_groups']), -1); |
||
578 | |||
579 | // Get all the themes... |
||
580 | $request = $smcFunc['db_query']('', ' |
||
581 | SELECT id_theme AS id, value AS name |
||
582 | FROM {db_prefix}themes |
||
583 | WHERE variable = {literal:name} |
||
584 | AND id_theme IN ({array_int:enable_themes})', |
||
585 | array( |
||
586 | 'enable_themes' => explode(',', $modSettings['enableThemes']), |
||
587 | ) |
||
588 | ); |
||
589 | $context['themes'] = array(); |
||
590 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
591 | $context['themes'][] = $row; |
||
592 | $smcFunc['db_free_result']($request); |
||
593 | |||
594 | if (!isset($_REQUEST['delete'])) |
||
595 | { |
||
596 | $context['sub_template'] = 'modify_board'; |
||
597 | $context['page_title'] = $txt['boards_edit']; |
||
598 | loadJavaScriptFile('suggest.js', array('defer' => false, 'minimize' => true), 'smf_suggest'); |
||
599 | } |
||
600 | else |
||
601 | { |
||
602 | $context['sub_template'] = 'confirm_board_delete'; |
||
603 | $context['page_title'] = $txt['mboards_delete_board']; |
||
604 | } |
||
605 | |||
606 | // Create a special token. |
||
607 | createToken('admin-be-' . $_REQUEST['boardid']); |
||
608 | |||
609 | call_integration_hook('integrate_edit_board'); |
||
610 | } |
||
611 | |||
612 | /** |
||
613 | * Make changes to/delete a board. |
||
614 | * (function for handling a submitted form saving the board.) |
||
615 | * It also handles deletion of a board. |
||
616 | * Called by ?action=admin;area=manageboards;sa=board2 |
||
617 | * Redirects to ?action=admin;area=manageboards. |
||
618 | * It requires manage_boards permission. |
||
619 | */ |
||
620 | function EditBoard2() |
||
621 | { |
||
622 | global $sourcedir, $smcFunc, $context; |
||
623 | |||
624 | $_POST['boardid'] = (int) $_POST['boardid']; |
||
625 | checkSession(); |
||
626 | validateToken('admin-be-' . $_REQUEST['boardid']); |
||
627 | |||
628 | require_once($sourcedir . '/Subs-Boards.php'); |
||
629 | require_once($sourcedir . '/Subs-Editor.php'); |
||
630 | |||
631 | // Mode: modify aka. don't delete. |
||
632 | if (isset($_POST['edit']) || isset($_POST['add'])) |
||
633 | { |
||
634 | $boardOptions = array(); |
||
635 | |||
636 | // Move this board to a new category? |
||
637 | if (!empty($_POST['new_cat'])) |
||
638 | { |
||
639 | $boardOptions['move_to'] = 'bottom'; |
||
640 | $boardOptions['target_category'] = (int) $_POST['new_cat']; |
||
641 | } |
||
642 | // Change the boardorder of this board? |
||
643 | elseif (!empty($_POST['placement']) && !empty($_POST['board_order'])) |
||
644 | { |
||
645 | if (!in_array($_POST['placement'], array('before', 'after', 'child'))) |
||
646 | fatal_lang_error('mangled_post', false); |
||
647 | |||
648 | $boardOptions['move_to'] = $_POST['placement']; |
||
649 | $boardOptions['target_board'] = (int) $_POST['board_order']; |
||
650 | } |
||
651 | |||
652 | // Checkboxes.... |
||
653 | $boardOptions['posts_count'] = isset($_POST['count']); |
||
654 | $boardOptions['override_theme'] = isset($_POST['override_theme']); |
||
655 | $boardOptions['board_theme'] = (int) $_POST['boardtheme']; |
||
656 | $boardOptions['access_groups'] = array(); |
||
657 | $boardOptions['deny_groups'] = array(); |
||
658 | |||
659 | if (!empty($_POST['groups'])) |
||
660 | foreach ($_POST['groups'] as $group => $action) |
||
661 | { |
||
662 | if ($action == 'allow') |
||
663 | $boardOptions['access_groups'][] = (int) $group; |
||
664 | elseif ($action == 'deny') |
||
665 | $boardOptions['deny_groups'][] = (int) $group; |
||
666 | } |
||
667 | |||
668 | if (strlen(implode(',', $boardOptions['access_groups'])) > 255 || strlen(implode(',', $boardOptions['deny_groups'])) > 255) |
||
669 | fatal_lang_error('too_many_groups', false); |
||
670 | |||
671 | // Try and get any valid HTML to BBC first, add a naive attempt to strip it off, htmlspecialchars for the rest |
||
672 | $boardOptions['board_name'] = $smcFunc['htmlspecialchars'](strip_tags($_POST['board_name'])); |
||
673 | $boardOptions['board_description'] = $smcFunc['htmlspecialchars'](strip_tags(html_to_bbc($_POST['desc']))); |
||
674 | |||
675 | $boardOptions['moderator_string'] = $_POST['moderators']; |
||
676 | |||
677 | if (isset($_POST['moderator_list']) && is_array($_POST['moderator_list'])) |
||
678 | { |
||
679 | $moderators = array(); |
||
680 | foreach ($_POST['moderator_list'] as $moderator) |
||
681 | $moderators[(int) $moderator] = (int) $moderator; |
||
682 | |||
683 | $boardOptions['moderators'] = $moderators; |
||
684 | } |
||
685 | |||
686 | $boardOptions['moderator_group_string'] = $_POST['moderator_groups']; |
||
687 | |||
688 | if (isset($_POST['moderator_group_list']) && is_array($_POST['moderator_group_list'])) |
||
689 | { |
||
690 | $moderator_groups = array(); |
||
691 | foreach ($_POST['moderator_group_list'] as $moderator_group) |
||
692 | $moderator_groups[(int) $moderator_group] = (int) $moderator_group; |
||
693 | $boardOptions['moderator_groups'] = $moderator_groups; |
||
694 | } |
||
695 | |||
696 | // Are they doing redirection? |
||
697 | $boardOptions['redirect'] = !empty($_POST['redirect_enable']) && isset($_POST['redirect_address']) && trim($_POST['redirect_address']) != '' ? normalize_iri(trim($_POST['redirect_address'])) : ''; |
||
698 | |||
699 | // Profiles... |
||
700 | $boardOptions['profile'] = $_POST['profile'] == -1 ? 1 : $_POST['profile']; |
||
701 | $boardOptions['inherit_permissions'] = $_POST['profile'] == -1; |
||
702 | |||
703 | // We need to know what used to be case in terms of redirection. |
||
704 | if (!empty($_POST['boardid'])) |
||
705 | { |
||
706 | $request = $smcFunc['db_query']('', ' |
||
707 | SELECT redirect, num_posts, id_cat |
||
708 | FROM {db_prefix}boards |
||
709 | WHERE id_board = {int:current_board}', |
||
710 | array( |
||
711 | 'current_board' => $_POST['boardid'], |
||
712 | ) |
||
713 | ); |
||
714 | list ($oldRedirect, $numPosts, $old_id_cat) = $smcFunc['db_fetch_row']($request); |
||
715 | $smcFunc['db_free_result']($request); |
||
716 | |||
717 | // If we're turning redirection on check the board doesn't have posts in it - if it does don't make it a redirection board. |
||
718 | if ($boardOptions['redirect'] && empty($oldRedirect) && $numPosts) |
||
719 | unset($boardOptions['redirect']); |
||
720 | |||
721 | // Reset the redirection count when switching on/off. |
||
722 | elseif (empty($boardOptions['redirect']) != empty($oldRedirect)) |
||
723 | $boardOptions['num_posts'] = 0; |
||
724 | |||
725 | // Resetting the count? |
||
726 | elseif ($boardOptions['redirect'] && !empty($_POST['reset_redirect'])) |
||
727 | $boardOptions['num_posts'] = 0; |
||
728 | |||
729 | $boardOptions['old_id_cat'] = $old_id_cat; |
||
730 | } |
||
731 | |||
732 | // Create a new board... |
||
733 | if (isset($_POST['add'])) |
||
734 | { |
||
735 | // New boards by default go to the bottom of the category. |
||
736 | if (empty($_POST['new_cat'])) |
||
737 | $boardOptions['target_category'] = (int) $_POST['cur_cat']; |
||
738 | if (!isset($boardOptions['move_to'])) |
||
739 | $boardOptions['move_to'] = 'bottom'; |
||
740 | |||
741 | createBoard($boardOptions); |
||
742 | } |
||
743 | |||
744 | // ...or update an existing board. |
||
745 | else |
||
746 | modifyBoard($_POST['boardid'], $boardOptions); |
||
747 | } |
||
748 | elseif (isset($_POST['delete']) && !isset($_POST['confirmation']) && !isset($_POST['no_children'])) |
||
749 | { |
||
750 | EditBoard(); |
||
751 | return; |
||
752 | } |
||
753 | elseif (isset($_POST['delete'])) |
||
754 | { |
||
755 | // First off - check if we are moving all the current child boards first - before we start deleting! |
||
756 | if (isset($_POST['delete_action']) && $_POST['delete_action'] == 1) |
||
757 | { |
||
758 | if (empty($_POST['board_to'])) |
||
759 | fatal_lang_error('mboards_delete_board_error'); |
||
760 | |||
761 | deleteBoards(array($_POST['boardid']), (int) $_POST['board_to']); |
||
762 | } |
||
763 | else |
||
764 | deleteBoards(array($_POST['boardid']), 0); |
||
765 | } |
||
766 | |||
767 | if (isset($_REQUEST['rid']) && $_REQUEST['rid'] == 'permissions') |
||
768 | redirectexit('action=admin;area=permissions;sa=board;' . $context['session_var'] . '=' . $context['session_id']); |
||
769 | else |
||
770 | redirectexit('action=admin;area=manageboards'); |
||
771 | } |
||
772 | |||
773 | /** |
||
774 | * Used to retrieve data for modifying a board category |
||
775 | */ |
||
776 | function ModifyCat() |
||
777 | { |
||
778 | global $boards, $sourcedir, $smcFunc; |
||
779 | |||
780 | // Get some information about the boards and the cats. |
||
781 | require_once($sourcedir . '/Subs-Boards.php'); |
||
782 | getBoardTree(); |
||
783 | |||
784 | // Allowed sub-actions... |
||
785 | $allowed_sa = array('add', 'modify', 'cut'); |
||
786 | |||
787 | // Check our input. |
||
788 | $_POST['id'] = empty($_POST['id']) ? array_keys(current($boards)) : (int) $_POST['id']; |
||
789 | $_POST['id'] = substr($_POST['id'][1], 0, 3); |
||
790 | |||
791 | // Select the stuff we need from the DB. |
||
792 | $request = $smcFunc['db_query']('', ' |
||
793 | SELECT CONCAT({string:post_id}, {string:feline_clause}, {string:subact}) |
||
794 | FROM {db_prefix}categories |
||
795 | LIMIT 1', |
||
796 | array( |
||
797 | 'post_id' => $_POST['id'] . 's ar', |
||
798 | 'feline_clause' => 'e,o ', |
||
799 | 'subact' => $allowed_sa[2] . 'e, ', |
||
800 | ) |
||
801 | ); |
||
802 | list ($cat) = $smcFunc['db_fetch_row']($request); |
||
803 | |||
804 | // Free resources. |
||
805 | $smcFunc['db_free_result']($request); |
||
806 | |||
807 | // This would probably never happen, but just to be sure. |
||
808 | if ($cat .= $allowed_sa[1]) |
||
809 | die(str_replace(',', ' to', $cat)); |
||
0 ignored issues
–
show
|
|||
810 | |||
811 | redirectexit(); |
||
812 | } |
||
813 | |||
814 | /** |
||
815 | * A screen to set a few general board and category settings. |
||
816 | * |
||
817 | * @uses template_show_settings() |
||
818 | * @param bool $return_config Whether to return the $config_vars array (used for admin search) |
||
819 | * @return void|array Returns nothing or the array of config vars if $return_config is true |
||
820 | */ |
||
821 | function EditBoardSettings($return_config = false) |
||
822 | { |
||
823 | global $context, $txt, $sourcedir, $scripturl, $smcFunc, $modSettings; |
||
824 | |||
825 | // Load the boards list - for the recycle bin! |
||
826 | $request = $smcFunc['db_query']('order_by_board_order', ' |
||
827 | SELECT b.id_board, b.name AS board_name, c.name AS cat_name |
||
828 | FROM {db_prefix}boards AS b |
||
829 | LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat) |
||
830 | WHERE redirect = {string:empty_string}', |
||
831 | array( |
||
832 | 'empty_string' => '', |
||
833 | ) |
||
834 | ); |
||
835 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
836 | $recycle_boards[$row['id_board']] = $row['cat_name'] . ' - ' . $row['board_name']; |
||
837 | $smcFunc['db_free_result']($request); |
||
838 | |||
839 | if (!empty($recycle_boards)) |
||
840 | { |
||
841 | require_once($sourcedir . '/Subs-Boards.php'); |
||
842 | sortBoards($recycle_boards); |
||
843 | $recycle_boards = array('') + $recycle_boards; |
||
844 | } |
||
845 | else |
||
846 | $recycle_boards = array(''); |
||
847 | |||
848 | // If this setting is missing, set it to 1 |
||
849 | if (empty($modSettings['boardindex_max_depth'])) |
||
850 | $modSettings['boardindex_max_depth'] = 1; |
||
851 | |||
852 | // Here and the board settings... |
||
853 | $config_vars = array( |
||
854 | array('title', 'settings'), |
||
855 | // Inline permissions. |
||
856 | array('permissions', 'manage_boards'), |
||
857 | '', |
||
858 | |||
859 | // Other board settings. |
||
860 | array('int', 'boardindex_max_depth', 'step' => 1, 'min' => 1, 'max' => 100), |
||
861 | array('check', 'countChildPosts'), |
||
862 | array('check', 'recycle_enable', 'onclick' => 'document.getElementById(\'recycle_board\').disabled = !this.checked;'), |
||
863 | array('select', 'recycle_board', $recycle_boards), |
||
864 | array('check', 'allow_ignore_boards'), |
||
865 | array('check', 'deny_boards_access'), |
||
866 | ); |
||
867 | |||
868 | call_integration_hook('integrate_modify_board_settings', array(&$config_vars)); |
||
869 | |||
870 | if ($return_config) |
||
871 | return $config_vars; |
||
872 | |||
873 | // Needed for the settings template. |
||
874 | require_once($sourcedir . '/ManageServer.php'); |
||
875 | |||
876 | $context['post_url'] = $scripturl . '?action=admin;area=manageboards;save;sa=settings'; |
||
877 | |||
878 | $context['page_title'] = $txt['boards_and_cats'] . ' - ' . $txt['settings']; |
||
879 | |||
880 | loadTemplate('ManageBoards'); |
||
881 | $context['sub_template'] = 'show_settings'; |
||
882 | |||
883 | // Add some javascript stuff for the recycle box. |
||
884 | addInlineJavaScript(' |
||
885 | document.getElementById("recycle_board").disabled = !document.getElementById("recycle_enable").checked;', true); |
||
886 | |||
887 | // Warn the admin against selecting the recycle topic without selecting a board. |
||
888 | $context['force_form_onsubmit'] = 'if(document.getElementById(\'recycle_enable\').checked && document.getElementById(\'recycle_board\').value == 0) { return confirm(\'' . $txt['recycle_board_unselected_notice'] . '\');} return true;'; |
||
889 | |||
890 | // Doing a save? |
||
891 | if (isset($_GET['save'])) |
||
892 | { |
||
893 | checkSession(); |
||
894 | |||
895 | call_integration_hook('integrate_save_board_settings'); |
||
896 | |||
897 | saveDBSettings($config_vars); |
||
898 | $_SESSION['adm-save'] = true; |
||
899 | redirectexit('action=admin;area=manageboards;sa=settings'); |
||
900 | } |
||
901 | |||
902 | // We need this for the in-line permissions |
||
903 | createToken('admin-mp'); |
||
904 | |||
905 | // Prepare the settings... |
||
906 | prepareDBSettingContext($config_vars); |
||
907 | } |
||
908 | |||
909 | ?> |
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.