1<?php 2/** 3* 4* This file is part of the phpBB Forum Software package. 5* 6* @copyright (c) phpBB Limited <https://www.phpbb.com> 7* @license GNU General Public License, version 2 (GPL-2.0) 8* 9* For full copyright and license information, please see 10* the docs/CREDITS.txt file. 11* 12*/ 13 14/** 15* @ignore 16*/ 17if (!defined('IN_PHPBB')) 18{ 19 exit; 20} 21 22class acp_forums 23{ 24 var $u_action; 25 var $parent_id = 0; 26 27 function main($id, $mode) 28 { 29 global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher; 30 global $phpbb_admin_path, $phpbb_root_path, $phpEx, $phpbb_log; 31 32 $user->add_lang('acp/forums'); 33 $this->tpl_name = 'acp_forums'; 34 $this->page_title = 'ACP_MANAGE_FORUMS'; 35 36 $form_key = 'acp_forums'; 37 add_form_key($form_key); 38 39 $action = $request->variable('action', ''); 40 $update = (isset($_POST['update'])) ? true : false; 41 $forum_id = $request->variable('f', 0); 42 43 $this->parent_id = $request->variable('parent_id', 0); 44 $forum_data = $errors = array(); 45 if ($update && !check_form_key($form_key)) 46 { 47 $update = false; 48 $errors[] = $user->lang['FORM_INVALID']; 49 } 50 51 // Check additional permissions 52 switch ($action) 53 { 54 case 'progress_bar': 55 $start = $request->variable('start', 0); 56 $total = $request->variable('total', 0); 57 58 $this->display_progress_bar($start, $total); 59 break; 60 61 case 'delete': 62 63 if (!$auth->acl_get('a_forumdel')) 64 { 65 trigger_error($user->lang['NO_PERMISSION_FORUM_DELETE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); 66 } 67 68 break; 69 70 case 'add': 71 72 if (!$auth->acl_get('a_forumadd')) 73 { 74 trigger_error($user->lang['NO_PERMISSION_FORUM_ADD'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); 75 } 76 77 break; 78 } 79 80 // Major routines 81 if ($update) 82 { 83 switch ($action) 84 { 85 case 'delete': 86 $action_subforums = $request->variable('action_subforums', ''); 87 $subforums_to_id = $request->variable('subforums_to_id', 0); 88 $action_posts = $request->variable('action_posts', ''); 89 $posts_to_id = $request->variable('posts_to_id', 0); 90 91 $errors = $this->delete_forum($forum_id, $action_posts, $action_subforums, $posts_to_id, $subforums_to_id); 92 93 if (count($errors)) 94 { 95 break; 96 } 97 98 $auth->acl_clear_prefetch(); 99 $cache->destroy('sql', FORUMS_TABLE); 100 101 trigger_error($user->lang['FORUM_DELETED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); 102 103 break; 104 105 case 'edit': 106 $forum_data = array( 107 'forum_id' => $forum_id 108 ); 109 110 // No break here 111 112 case 'add': 113 114 $forum_data += array( 115 'parent_id' => $request->variable('forum_parent_id', $this->parent_id), 116 'forum_type' => $request->variable('forum_type', FORUM_POST), 117 'type_action' => $request->variable('type_action', ''), 118 'forum_status' => $request->variable('forum_status', ITEM_UNLOCKED), 119 'forum_parents' => '', 120 'forum_name' => $request->variable('forum_name', '', true), 121 'forum_link' => $request->variable('forum_link', ''), 122 'forum_link_track' => $request->variable('forum_link_track', false), 123 'forum_desc' => $request->variable('forum_desc', '', true), 124 'forum_desc_uid' => '', 125 'forum_desc_options' => 7, 126 'forum_desc_bitfield' => '', 127 'forum_rules' => $request->variable('forum_rules', '', true), 128 'forum_rules_uid' => '', 129 'forum_rules_options' => 7, 130 'forum_rules_bitfield' => '', 131 'forum_rules_link' => $request->variable('forum_rules_link', ''), 132 'forum_image' => $request->variable('forum_image', ''), 133 'forum_style' => $request->variable('forum_style', 0), 134 'display_subforum_list' => $request->variable('display_subforum_list', true), 135 'display_subforum_limit'=> $request->variable('display_subforum_limit', false), 136 'display_on_index' => $request->variable('display_on_index', true), 137 'forum_topics_per_page' => $request->variable('topics_per_page', 0), 138 'enable_indexing' => $request->variable('enable_indexing', true), 139 'enable_icons' => $request->variable('enable_icons', true), 140 'enable_prune' => $request->variable('enable_prune', false), 141 'enable_post_review' => $request->variable('enable_post_review', true), 142 'enable_quick_reply' => $request->variable('enable_quick_reply', false), 143 'enable_shadow_prune' => $request->variable('enable_shadow_prune', false), 144 'prune_days' => $request->variable('prune_days', 7), 145 'prune_viewed' => $request->variable('prune_viewed', 7), 146 'prune_freq' => $request->variable('prune_freq', 1), 147 'prune_old_polls' => $request->variable('prune_old_polls', false), 148 'prune_announce' => $request->variable('prune_announce', false), 149 'prune_sticky' => $request->variable('prune_sticky', false), 150 'prune_shadow_days' => $request->variable('prune_shadow_days', 7), 151 'prune_shadow_freq' => $request->variable('prune_shadow_freq', 1), 152 'forum_password' => $request->variable('forum_password', '', true), 153 'forum_password_confirm'=> $request->variable('forum_password_confirm', '', true), 154 'forum_password_unset' => $request->variable('forum_password_unset', false), 155 ); 156 157 /** 158 * Request forum data and operate on it (parse texts, etc.) 159 * 160 * @event core.acp_manage_forums_request_data 161 * @var string action Type of the action: add|edit 162 * @var array forum_data Array with new forum data 163 * @since 3.1.0-a1 164 */ 165 $vars = array('action', 'forum_data'); 166 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_request_data', compact($vars))); 167 168 // On add, add empty forum_options... else do not consider it (not updating it) 169 if ($action == 'add') 170 { 171 $forum_data['forum_options'] = 0; 172 } 173 174 // Use link_display_on_index setting if forum type is link 175 if ($forum_data['forum_type'] == FORUM_LINK) 176 { 177 $forum_data['display_on_index'] = $request->variable('link_display_on_index', false); 178 } 179 180 // Linked forums and categories are not able to be locked... 181 if ($forum_data['forum_type'] == FORUM_LINK || $forum_data['forum_type'] == FORUM_CAT) 182 { 183 $forum_data['forum_status'] = ITEM_UNLOCKED; 184 } 185 186 $forum_data['show_active'] = ($forum_data['forum_type'] == FORUM_POST) ? $request->variable('display_recent', true) : $request->variable('display_active', false); 187 188 // Get data for forum rules if specified... 189 if ($forum_data['forum_rules']) 190 { 191 generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], $request->variable('rules_parse_bbcode', false), $request->variable('rules_parse_urls', false), $request->variable('rules_parse_smilies', false)); 192 } 193 194 // Get data for forum description if specified 195 if ($forum_data['forum_desc']) 196 { 197 generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], $request->variable('desc_parse_bbcode', false), $request->variable('desc_parse_urls', false), $request->variable('desc_parse_smilies', false)); 198 } 199 200 $errors = $this->update_forum_data($forum_data); 201 202 if (!count($errors)) 203 { 204 $forum_perm_from = $request->variable('forum_perm_from', 0); 205 $cache->destroy('sql', FORUMS_TABLE); 206 207 $copied_permissions = false; 208 // Copy permissions? 209 if ($forum_perm_from && $forum_perm_from != $forum_data['forum_id'] && 210 ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth')))) 211 { 212 copy_forum_permissions($forum_perm_from, $forum_data['forum_id'], ($action == 'edit') ? true : false); 213 phpbb_cache_moderators($db, $cache, $auth); 214 $copied_permissions = true; 215 } 216/* Commented out because of questionable UI workflow - re-visit for 3.0.7 217 else if (!$this->parent_id && $action != 'edit' && $auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth')) 218 { 219 $this->copy_permission_page($forum_data); 220 return; 221 } 222*/ 223 $auth->acl_clear_prefetch(); 224 225 $acl_url = '&mode=setting_forum_local&forum_id[]=' . $forum_data['forum_id']; 226 227 $message = ($action == 'add') ? $user->lang['FORUM_CREATED'] : $user->lang['FORUM_UPDATED']; 228 229 // redirect directly to permission settings screen if authed 230 if ($action == 'add' && !$copied_permissions && $auth->acl_get('a_fauth')) 231 { 232 $message .= '<br /><br />' . sprintf($user->lang['REDIRECT_ACL'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url) . '">', '</a>'); 233 234 meta_refresh(4, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url)); 235 } 236 237 trigger_error($message . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); 238 } 239 240 break; 241 } 242 } 243 244 switch ($action) 245 { 246 case 'move_up': 247 case 'move_down': 248 249 if (!$forum_id) 250 { 251 trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); 252 } 253 254 $sql = 'SELECT * 255 FROM ' . FORUMS_TABLE . " 256 WHERE forum_id = $forum_id"; 257 $result = $db->sql_query($sql); 258 $row = $db->sql_fetchrow($result); 259 $db->sql_freeresult($result); 260 261 if (!$row) 262 { 263 trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); 264 } 265 266 $move_forum_name = $this->move_forum_by($row, $action, 1); 267 268 if ($move_forum_name !== false) 269 { 270 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_' . strtoupper($action), false, array($row['forum_name'], $move_forum_name)); 271 $cache->destroy('sql', FORUMS_TABLE); 272 } 273 274 if ($request->is_ajax()) 275 { 276 $json_response = new \phpbb\json_response; 277 $json_response->send(array('success' => ($move_forum_name !== false))); 278 } 279 280 break; 281 282 case 'sync': 283 if (!$forum_id) 284 { 285 trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); 286 } 287 288 @set_time_limit(0); 289 290 $sql = 'SELECT forum_name, (forum_topics_approved + forum_topics_unapproved + forum_topics_softdeleted) AS total_topics 291 FROM ' . FORUMS_TABLE . " 292 WHERE forum_id = $forum_id"; 293 $result = $db->sql_query($sql); 294 $row = $db->sql_fetchrow($result); 295 $db->sql_freeresult($result); 296 297 if (!$row) 298 { 299 trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); 300 } 301 302 if ($row['total_topics']) 303 { 304 $sql = 'SELECT MIN(topic_id) as min_topic_id, MAX(topic_id) as max_topic_id 305 FROM ' . TOPICS_TABLE . ' 306 WHERE forum_id = ' . $forum_id; 307 $result = $db->sql_query($sql); 308 $row2 = $db->sql_fetchrow($result); 309 $db->sql_freeresult($result); 310 311 // Typecast to int if there is no data available 312 $row2['min_topic_id'] = (int) $row2['min_topic_id']; 313 $row2['max_topic_id'] = (int) $row2['max_topic_id']; 314 315 $start = $request->variable('start', $row2['min_topic_id']); 316 317 $batch_size = 2000; 318 $end = $start + $batch_size; 319 320 // Sync all topics in batch mode... 321 sync('topic', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, true); 322 323 if ($end < $row2['max_topic_id']) 324 { 325 // We really need to find a way of showing statistics... no progress here 326 $sql = 'SELECT COUNT(topic_id) as num_topics 327 FROM ' . TOPICS_TABLE . ' 328 WHERE forum_id = ' . $forum_id . ' 329 AND topic_id BETWEEN ' . $start . ' AND ' . $end; 330 $result = $db->sql_query($sql); 331 $topics_done = $request->variable('topics_done', 0) + (int) $db->sql_fetchfield('num_topics'); 332 $db->sql_freeresult($result); 333 334 $start += $batch_size; 335 336 $url = $this->u_action . "&parent_id={$this->parent_id}&f=$forum_id&action=sync&start=$start&topics_done=$topics_done&total={$row['total_topics']}"; 337 338 meta_refresh(0, $url); 339 340 $template->assign_vars(array( 341 'U_PROGRESS_BAR' => $this->u_action . "&action=progress_bar&start=$topics_done&total={$row['total_topics']}", 342 'UA_PROGRESS_BAR' => addslashes($this->u_action . "&action=progress_bar&start=$topics_done&total={$row['total_topics']}"), 343 'S_CONTINUE_SYNC' => true, 344 'L_PROGRESS_EXPLAIN' => sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $topics_done, $row['total_topics'])) 345 ); 346 347 return; 348 } 349 } 350 351 $url = $this->u_action . "&parent_id={$this->parent_id}&f=$forum_id&action=sync_forum"; 352 meta_refresh(0, $url); 353 354 $template->assign_vars(array( 355 'U_PROGRESS_BAR' => $this->u_action . '&action=progress_bar', 356 'UA_PROGRESS_BAR' => addslashes($this->u_action . '&action=progress_bar'), 357 'S_CONTINUE_SYNC' => true, 358 'L_PROGRESS_EXPLAIN' => sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], 0, $row['total_topics'])) 359 ); 360 361 return; 362 363 break; 364 365 case 'sync_forum': 366 367 $sql = 'SELECT forum_name, forum_type 368 FROM ' . FORUMS_TABLE . " 369 WHERE forum_id = $forum_id"; 370 $result = $db->sql_query($sql); 371 $row = $db->sql_fetchrow($result); 372 $db->sql_freeresult($result); 373 374 if (!$row) 375 { 376 trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); 377 } 378 379 sync('forum', 'forum_id', $forum_id, false, true); 380 381 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_SYNC', false, array($row['forum_name'])); 382 383 $cache->destroy('sql', FORUMS_TABLE); 384 385 $template->assign_var('L_FORUM_RESYNCED', sprintf($user->lang['FORUM_RESYNCED'], $row['forum_name'])); 386 387 break; 388 389 case 'add': 390 case 'edit': 391 392 if ($update) 393 { 394 $forum_data['forum_flags'] = 0; 395 $forum_data['forum_flags'] += ($request->variable('forum_link_track', false)) ? FORUM_FLAG_LINK_TRACK : 0; 396 $forum_data['forum_flags'] += ($request->variable('prune_old_polls', false)) ? FORUM_FLAG_PRUNE_POLL : 0; 397 $forum_data['forum_flags'] += ($request->variable('prune_announce', false)) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0; 398 $forum_data['forum_flags'] += ($request->variable('prune_sticky', false)) ? FORUM_FLAG_PRUNE_STICKY : 0; 399 $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0; 400 $forum_data['forum_flags'] += ($request->variable('enable_post_review', true)) ? FORUM_FLAG_POST_REVIEW : 0; 401 $forum_data['forum_flags'] += ($request->variable('enable_quick_reply', false)) ? FORUM_FLAG_QUICK_REPLY : 0; 402 } 403 404 // Initialise $row, so we always have it in the event 405 $row = array(); 406 407 // Show form to create/modify a forum 408 if ($action == 'edit') 409 { 410 $this->page_title = 'EDIT_FORUM'; 411 $row = $this->get_forum_info($forum_id); 412 $old_forum_type = $row['forum_type']; 413 414 if (!$update) 415 { 416 $forum_data = $row; 417 } 418 else 419 { 420 $forum_data['left_id'] = $row['left_id']; 421 $forum_data['right_id'] = $row['right_id']; 422 } 423 424 // Make sure no direct child forums are able to be selected as parents. 425 $exclude_forums = array(); 426 foreach (get_forum_branch($forum_id, 'children') as $row) 427 { 428 $exclude_forums[] = $row['forum_id']; 429 } 430 431 $parents_list = make_forum_select($forum_data['parent_id'], $exclude_forums, false, false, false); 432 433 $forum_data['forum_password_confirm'] = $forum_data['forum_password']; 434 } 435 else 436 { 437 $this->page_title = 'CREATE_FORUM'; 438 439 $forum_id = $this->parent_id; 440 $parents_list = make_forum_select($this->parent_id, false, false, false, false); 441 442 // Fill forum data with default values 443 if (!$update) 444 { 445 $forum_data = array( 446 'parent_id' => $this->parent_id, 447 'forum_type' => FORUM_POST, 448 'forum_status' => ITEM_UNLOCKED, 449 'forum_name' => $request->variable('forum_name', '', true), 450 'forum_link' => '', 451 'forum_link_track' => false, 452 'forum_desc' => '', 453 'forum_rules' => '', 454 'forum_rules_link' => '', 455 'forum_image' => '', 456 'forum_style' => 0, 457 'display_subforum_list' => true, 458 'display_subforum_limit' => false, 459 'display_on_index' => true, 460 'forum_topics_per_page' => 0, 461 'enable_indexing' => true, 462 'enable_icons' => true, 463 'enable_prune' => false, 464 'prune_days' => 7, 465 'prune_viewed' => 7, 466 'prune_freq' => 1, 467 'enable_shadow_prune' => false, 468 'prune_shadow_days' => 7, 469 'prune_shadow_freq' => 1, 470 'forum_flags' => FORUM_FLAG_POST_REVIEW + FORUM_FLAG_ACTIVE_TOPICS, 471 'forum_options' => 0, 472 'forum_password' => '', 473 'forum_password_confirm'=> '', 474 ); 475 } 476 } 477 478 /** 479 * Initialise data before we display the add/edit form 480 * 481 * @event core.acp_manage_forums_initialise_data 482 * @var string action Type of the action: add|edit 483 * @var bool update Do we display the form only 484 * or did the user press submit 485 * @var int forum_id When editing: the forum id, 486 * when creating: the parent forum id 487 * @var array row Array with current forum data 488 * empty when creating new forum 489 * @var array forum_data Array with new forum data 490 * @var string parents_list List of parent options 491 * @since 3.1.0-a1 492 */ 493 $vars = array('action', 'update', 'forum_id', 'row', 'forum_data', 'parents_list'); 494 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_initialise_data', compact($vars))); 495 496 $forum_rules_data = array( 497 'text' => $forum_data['forum_rules'], 498 'allow_bbcode' => true, 499 'allow_smilies' => true, 500 'allow_urls' => true 501 ); 502 503 $forum_desc_data = array( 504 'text' => $forum_data['forum_desc'], 505 'allow_bbcode' => true, 506 'allow_smilies' => true, 507 'allow_urls' => true 508 ); 509 510 $forum_rules_preview = ''; 511 512 // Parse rules if specified 513 if ($forum_data['forum_rules']) 514 { 515 if (!isset($forum_data['forum_rules_uid'])) 516 { 517 // Before we are able to display the preview and plane text, we need to parse our $request->variable()'d value... 518 $forum_data['forum_rules_uid'] = ''; 519 $forum_data['forum_rules_bitfield'] = ''; 520 $forum_data['forum_rules_options'] = 0; 521 522 generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], $request->variable('rules_allow_bbcode', false), $request->variable('rules_allow_urls', false), $request->variable('rules_allow_smilies', false)); 523 } 524 525 // Generate preview content 526 $forum_rules_preview = generate_text_for_display($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options']); 527 528 // decode... 529 $forum_rules_data = generate_text_for_edit($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_options']); 530 } 531 532 // Parse desciption if specified 533 if ($forum_data['forum_desc']) 534 { 535 if (!isset($forum_data['forum_desc_uid'])) 536 { 537 // Before we are able to display the preview and plane text, we need to parse our $request->variable()'d value... 538 $forum_data['forum_desc_uid'] = ''; 539 $forum_data['forum_desc_bitfield'] = ''; 540 $forum_data['forum_desc_options'] = 0; 541 542 generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], $request->variable('desc_allow_bbcode', false), $request->variable('desc_allow_urls', false), $request->variable('desc_allow_smilies', false)); 543 } 544 545 // decode... 546 $forum_desc_data = generate_text_for_edit($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_options']); 547 } 548 549 $forum_type_options = ''; 550 $forum_type_ary = array(FORUM_CAT => 'CAT', FORUM_POST => 'FORUM', FORUM_LINK => 'LINK'); 551 552 foreach ($forum_type_ary as $value => $lang) 553 { 554 $forum_type_options .= '<option value="' . $value . '"' . (($value == $forum_data['forum_type']) ? ' selected="selected"' : '') . '>' . $user->lang['TYPE_' . $lang] . '</option>'; 555 } 556 557 $styles_list = style_select($forum_data['forum_style'], true); 558 559 $statuslist = '<option value="' . ITEM_UNLOCKED . '"' . (($forum_data['forum_status'] == ITEM_UNLOCKED) ? ' selected="selected"' : '') . '>' . $user->lang['UNLOCKED'] . '</option><option value="' . ITEM_LOCKED . '"' . (($forum_data['forum_status'] == ITEM_LOCKED) ? ' selected="selected"' : '') . '>' . $user->lang['LOCKED'] . '</option>'; 560 561 $sql = 'SELECT forum_id 562 FROM ' . FORUMS_TABLE . ' 563 WHERE forum_type = ' . FORUM_POST . " 564 AND forum_id <> $forum_id"; 565 $result = $db->sql_query_limit($sql, 1); 566 567 $postable_forum_exists = false; 568 if ($db->sql_fetchrow($result)) 569 { 570 $postable_forum_exists = true; 571 } 572 $db->sql_freeresult($result); 573 574 // Subforum move options 575 if ($action == 'edit' && $forum_data['forum_type'] == FORUM_CAT) 576 { 577 $subforums_id = array(); 578 $subforums = get_forum_branch($forum_id, 'children'); 579 580 foreach ($subforums as $row) 581 { 582 $subforums_id[] = $row['forum_id']; 583 } 584 585 $forums_list = make_forum_select($forum_data['parent_id'], $subforums_id); 586 587 if ($postable_forum_exists) 588 { 589 $template->assign_vars(array( 590 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $subforums_id)) // , false, true, false??? 591 ); 592 } 593 594 $template->assign_vars(array( 595 'S_HAS_SUBFORUMS' => ($forum_data['right_id'] - $forum_data['left_id'] > 1) ? true : false, 596 'S_FORUMS_LIST' => $forums_list) 597 ); 598 } 599 else if ($postable_forum_exists) 600 { 601 $template->assign_vars(array( 602 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $forum_id, false, true, false)) 603 ); 604 } 605 606 $s_show_display_on_index = false; 607 608 if ($forum_data['parent_id'] > 0) 609 { 610 // if this forum is a subforum put the "display on index" checkbox 611 if ($parent_info = $this->get_forum_info($forum_data['parent_id'])) 612 { 613 if ($parent_info['parent_id'] > 0 || $parent_info['forum_type'] == FORUM_CAT) 614 { 615 $s_show_display_on_index = true; 616 } 617 } 618 } 619 620 if (strlen($forum_data['forum_password']) == 32) 621 { 622 $errors[] = $user->lang['FORUM_PASSWORD_OLD']; 623 } 624 625 $template_data = array( 626 'S_EDIT_FORUM' => true, 627 'S_ERROR' => (count($errors)) ? true : false, 628 'S_PARENT_ID' => $this->parent_id, 629 'S_FORUM_PARENT_ID' => $forum_data['parent_id'], 630 'S_ADD_ACTION' => ($action == 'add') ? true : false, 631 632 'U_BACK' => $this->u_action . '&parent_id=' . $this->parent_id, 633 'U_EDIT_ACTION' => $this->u_action . "&parent_id={$this->parent_id}&action=$action&f=$forum_id", 634 635 'L_COPY_PERMISSIONS_EXPLAIN' => $user->lang['COPY_PERMISSIONS_' . strtoupper($action) . '_EXPLAIN'], 636 'L_TITLE' => $user->lang[$this->page_title], 637 'ERROR_MSG' => (count($errors)) ? implode('<br />', $errors) : '', 638 639 'FORUM_NAME' => $forum_data['forum_name'], 640 'FORUM_DATA_LINK' => $forum_data['forum_link'], 641 'FORUM_IMAGE' => $forum_data['forum_image'], 642 'FORUM_IMAGE_SRC' => ($forum_data['forum_image']) ? $phpbb_root_path . $forum_data['forum_image'] : '', 643 'FORUM_POST' => FORUM_POST, 644 'FORUM_LINK' => FORUM_LINK, 645 'FORUM_CAT' => FORUM_CAT, 646 'PRUNE_FREQ' => $forum_data['prune_freq'], 647 'PRUNE_DAYS' => $forum_data['prune_days'], 648 'PRUNE_VIEWED' => $forum_data['prune_viewed'], 649 'PRUNE_SHADOW_FREQ' => $forum_data['prune_shadow_freq'], 650 'PRUNE_SHADOW_DAYS' => $forum_data['prune_shadow_days'], 651 'TOPICS_PER_PAGE' => $forum_data['forum_topics_per_page'], 652 'FORUM_RULES_LINK' => $forum_data['forum_rules_link'], 653 'FORUM_RULES' => $forum_data['forum_rules'], 654 'FORUM_RULES_PREVIEW' => $forum_rules_preview, 655 'FORUM_RULES_PLAIN' => $forum_rules_data['text'], 656 'S_BBCODE_CHECKED' => ($forum_rules_data['allow_bbcode']) ? true : false, 657 'S_SMILIES_CHECKED' => ($forum_rules_data['allow_smilies']) ? true : false, 658 'S_URLS_CHECKED' => ($forum_rules_data['allow_urls']) ? true : false, 659 'S_FORUM_PASSWORD_SET' => (empty($forum_data['forum_password'])) ? false : true, 660 661 'FORUM_DESC' => $forum_desc_data['text'], 662 'S_DESC_BBCODE_CHECKED' => ($forum_desc_data['allow_bbcode']) ? true : false, 663 'S_DESC_SMILIES_CHECKED' => ($forum_desc_data['allow_smilies']) ? true : false, 664 'S_DESC_URLS_CHECKED' => ($forum_desc_data['allow_urls']) ? true : false, 665 666 'S_FORUM_TYPE_OPTIONS' => $forum_type_options, 667 'S_STATUS_OPTIONS' => $statuslist, 668 'S_PARENT_OPTIONS' => $parents_list, 669 'S_STYLES_OPTIONS' => $styles_list, 670 'S_FORUM_OPTIONS' => make_forum_select(($action == 'add') ? $forum_data['parent_id'] : false, ($action == 'edit') ? $forum_data['forum_id'] : false, false, false, false), 671 'S_SHOW_DISPLAY_ON_INDEX' => $s_show_display_on_index, 672 'S_FORUM_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false, 673 'S_FORUM_ORIG_POST' => (isset($old_forum_type) && $old_forum_type == FORUM_POST) ? true : false, 674 'S_FORUM_ORIG_CAT' => (isset($old_forum_type) && $old_forum_type == FORUM_CAT) ? true : false, 675 'S_FORUM_ORIG_LINK' => (isset($old_forum_type) && $old_forum_type == FORUM_LINK) ? true : false, 676 'S_FORUM_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, 677 'S_FORUM_CAT' => ($forum_data['forum_type'] == FORUM_CAT) ? true : false, 678 'S_ENABLE_INDEXING' => ($forum_data['enable_indexing']) ? true : false, 679 'S_TOPIC_ICONS' => ($forum_data['enable_icons']) ? true : false, 680 'S_DISPLAY_SUBFORUM_LIST' => ($forum_data['display_subforum_list']) ? true : false, 681 'S_DISPLAY_SUBFORUM_LIMIT' => ($forum_data['display_subforum_limit']) ? true : false, 682 'S_DISPLAY_ON_INDEX' => ($forum_data['display_on_index']) ? true : false, 683 'S_PRUNE_ENABLE' => ($forum_data['enable_prune']) ? true : false, 684 'S_PRUNE_SHADOW_ENABLE' => ($forum_data['enable_shadow_prune']) ? true : false, 685 'S_FORUM_LINK_TRACK' => ($forum_data['forum_flags'] & FORUM_FLAG_LINK_TRACK) ? true : false, 686 'S_PRUNE_OLD_POLLS' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_POLL) ? true : false, 687 'S_PRUNE_ANNOUNCE' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_ANNOUNCE) ? true : false, 688 'S_PRUNE_STICKY' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_STICKY) ? true : false, 689 'S_DISPLAY_ACTIVE_TOPICS' => ($forum_data['forum_type'] == FORUM_POST) ? ($forum_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) : true, 690 'S_ENABLE_ACTIVE_TOPICS' => ($forum_data['forum_type'] == FORUM_CAT) ? ($forum_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) : false, 691 'S_ENABLE_POST_REVIEW' => ($forum_data['forum_flags'] & FORUM_FLAG_POST_REVIEW) ? true : false, 692 'S_ENABLE_QUICK_REPLY' => ($forum_data['forum_flags'] & FORUM_FLAG_QUICK_REPLY) ? true : false, 693 'S_CAN_COPY_PERMISSIONS' => ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))) ? true : false, 694 ); 695 696 /** 697 * Modify forum template data before we display the form 698 * 699 * @event core.acp_manage_forums_display_form 700 * @var string action Type of the action: add|edit 701 * @var bool update Do we display the form only 702 * or did the user press submit 703 * @var int forum_id When editing: the forum id, 704 * when creating: the parent forum id 705 * @var array row Array with current forum data 706 * empty when creating new forum 707 * @var array forum_data Array with new forum data 708 * @var string parents_list List of parent options 709 * @var array errors Array of errors, if you add errors 710 * ensure to update the template variables 711 * S_ERROR and ERROR_MSG to display it 712 * @var array template_data Array with new forum data 713 * @since 3.1.0-a1 714 */ 715 $vars = array( 716 'action', 717 'update', 718 'forum_id', 719 'row', 720 'forum_data', 721 'parents_list', 722 'errors', 723 'template_data', 724 ); 725 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_display_form', compact($vars))); 726 727 $template->assign_vars($template_data); 728 729 return; 730 731 break; 732 733 case 'delete': 734 735 if (!$forum_id) 736 { 737 trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); 738 } 739 740 $forum_data = $this->get_forum_info($forum_id); 741 742 $subforums_id = array(); 743 $subforums = get_forum_branch($forum_id, 'children'); 744 745 foreach ($subforums as $row) 746 { 747 $subforums_id[] = $row['forum_id']; 748 } 749 750 $forums_list = make_forum_select($forum_data['parent_id'], $subforums_id); 751 752 $sql = 'SELECT forum_id 753 FROM ' . FORUMS_TABLE . ' 754 WHERE forum_type = ' . FORUM_POST . " 755 AND forum_id <> $forum_id"; 756 $result = $db->sql_query_limit($sql, 1); 757 758 if ($db->sql_fetchrow($result)) 759 { 760 $template->assign_vars(array( 761 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $subforums_id, false, true)) // , false, true, false??? 762 ); 763 } 764 $db->sql_freeresult($result); 765 766 $parent_id = ($this->parent_id == $forum_id) ? 0 : $this->parent_id; 767 768 $template->assign_vars(array( 769 'S_DELETE_FORUM' => true, 770 'U_ACTION' => $this->u_action . "&parent_id={$parent_id}&action=delete&f=$forum_id", 771 'U_BACK' => $this->u_action . '&parent_id=' . $this->parent_id, 772 773 'FORUM_NAME' => $forum_data['forum_name'], 774 'S_FORUM_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false, 775 'S_FORUM_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, 776 'S_HAS_SUBFORUMS' => ($forum_data['right_id'] - $forum_data['left_id'] > 1) ? true : false, 777 'S_FORUMS_LIST' => $forums_list, 778 'S_ERROR' => (count($errors)) ? true : false, 779 'ERROR_MSG' => (count($errors)) ? implode('<br />', $errors) : '') 780 ); 781 782 return; 783 break; 784 785 case 'copy_perm': 786 $forum_perm_from = $request->variable('forum_perm_from', 0); 787 788 // Copy permissions? 789 if (!empty($forum_perm_from) && $forum_perm_from != $forum_id) 790 { 791 copy_forum_permissions($forum_perm_from, $forum_id, true); 792 phpbb_cache_moderators($db, $cache, $auth); 793 $auth->acl_clear_prefetch(); 794 $cache->destroy('sql', FORUMS_TABLE); 795 796 $acl_url = '&mode=setting_forum_local&forum_id[]=' . $forum_id; 797 798 $message = $user->lang['FORUM_UPDATED']; 799 800 // Redirect to permissions 801 if ($auth->acl_get('a_fauth')) 802 { 803 $message .= '<br /><br />' . sprintf($user->lang['REDIRECT_ACL'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url) . '">', '</a>'); 804 } 805 806 trigger_error($message . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); 807 } 808 809 break; 810 } 811 812 // Default management page 813 if (!$this->parent_id) 814 { 815 $navigation = $user->lang['FORUM_INDEX']; 816 } 817 else 818 { 819 $navigation = '<a href="' . $this->u_action . '">' . $user->lang['FORUM_INDEX'] . '</a>'; 820 821 $forums_nav = get_forum_branch($this->parent_id, 'parents', 'descending'); 822 foreach ($forums_nav as $row) 823 { 824 if ($row['forum_id'] == $this->parent_id) 825 { 826 $navigation .= ' -> ' . $row['forum_name']; 827 } 828 else 829 { 830 $navigation .= ' -> <a href="' . $this->u_action . '&parent_id=' . $row['forum_id'] . '">' . $row['forum_name'] . '</a>'; 831 } 832 } 833 } 834 835 // Jumpbox 836 $forum_box = make_forum_select($this->parent_id, false, false, false, false); //make_forum_select($this->parent_id); 837 838 if ($action == 'sync' || $action == 'sync_forum') 839 { 840 $template->assign_var('S_RESYNCED', true); 841 } 842 843 $sql = 'SELECT * 844 FROM ' . FORUMS_TABLE . " 845 WHERE parent_id = $this->parent_id 846 ORDER BY left_id"; 847 $result = $db->sql_query($sql); 848 849 $rowset = array(); 850 while ($row = $db->sql_fetchrow($result)) 851 { 852 $rowset[(int) $row['forum_id']] = $row; 853 } 854 $db->sql_freeresult($result); 855 856 /** 857 * Modify the forum list data 858 * 859 * @event core.acp_manage_forums_modify_forum_list 860 * @var array rowset Array with the forums list data 861 * @since 3.1.10-RC1 862 */ 863 $vars = array('rowset'); 864 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_modify_forum_list', compact($vars))); 865 866 if (!empty($rowset)) 867 { 868 foreach ($rowset as $row) 869 { 870 $forum_type = $row['forum_type']; 871 872 if ($row['forum_status'] == ITEM_LOCKED) 873 { 874 $folder_image = '<img src="images/icon_folder_lock.gif" alt="' . $user->lang['LOCKED'] . '" />'; 875 } 876 else 877 { 878 switch ($forum_type) 879 { 880 case FORUM_LINK: 881 $folder_image = '<img src="images/icon_folder_link.gif" alt="' . $user->lang['LINK'] . '" />'; 882 break; 883 884 default: 885 $folder_image = ($row['left_id'] + 1 != $row['right_id']) ? '<img src="images/icon_subfolder.gif" alt="' . $user->lang['SUBFORUM'] . '" />' : '<img src="images/icon_folder.gif" alt="' . $user->lang['FOLDER'] . '" />'; 886 break; 887 } 888 } 889 890 $url = $this->u_action . "&parent_id=$this->parent_id&f={$row['forum_id']}"; 891 892 $template->assign_block_vars('forums', array( 893 'FOLDER_IMAGE' => $folder_image, 894 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="" />' : '', 895 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '', 896 'FORUM_NAME' => $row['forum_name'], 897 'FORUM_DESCRIPTION' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']), 898 'FORUM_TOPICS' => $row['forum_topics_approved'], 899 'FORUM_POSTS' => $row['forum_posts_approved'], 900 901 'S_FORUM_LINK' => ($forum_type == FORUM_LINK) ? true : false, 902 'S_FORUM_POST' => ($forum_type == FORUM_POST) ? true : false, 903 904 'U_FORUM' => $this->u_action . '&parent_id=' . $row['forum_id'], 905 'U_MOVE_UP' => $url . '&action=move_up', 906 'U_MOVE_DOWN' => $url . '&action=move_down', 907 'U_EDIT' => $url . '&action=edit', 908 'U_DELETE' => $url . '&action=delete', 909 'U_SYNC' => $url . '&action=sync') 910 ); 911 } 912 } 913 else if ($this->parent_id) 914 { 915 $row = $this->get_forum_info($this->parent_id); 916 917 $url = $this->u_action . '&parent_id=' . $this->parent_id . '&f=' . $row['forum_id']; 918 919 $template->assign_vars(array( 920 'S_NO_FORUMS' => true, 921 922 'U_EDIT' => $url . '&action=edit', 923 'U_DELETE' => $url . '&action=delete', 924 'U_SYNC' => $url . '&action=sync') 925 ); 926 } 927 unset($rowset); 928 929 $template->assign_vars(array( 930 'ERROR_MSG' => (count($errors)) ? implode('<br />', $errors) : '', 931 'NAVIGATION' => $navigation, 932 'FORUM_BOX' => $forum_box, 933 'U_SEL_ACTION' => $this->u_action, 934 'U_ACTION' => $this->u_action . '&parent_id=' . $this->parent_id, 935 936 'U_PROGRESS_BAR' => $this->u_action . '&action=progress_bar', 937 'UA_PROGRESS_BAR' => addslashes($this->u_action . '&action=progress_bar'), 938 )); 939 } 940 941 /** 942 * Get forum details 943 */ 944 function get_forum_info($forum_id) 945 { 946 global $db; 947 948 $sql = 'SELECT * 949 FROM ' . FORUMS_TABLE . " 950 WHERE forum_id = $forum_id"; 951 $result = $db->sql_query($sql); 952 $row = $db->sql_fetchrow($result); 953 $db->sql_freeresult($result); 954 955 if (!$row) 956 { 957 trigger_error("Forum #$forum_id does not exist", E_USER_ERROR); 958 } 959 960 return $row; 961 } 962 963 /** 964 * Update forum data 965 */ 966 function update_forum_data(&$forum_data_ary) 967 { 968 global $db, $user, $cache, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log, $request; 969 970 $errors = array(); 971 972 $forum_data = $forum_data_ary; 973 /** 974 * Validate the forum data before we create/update the forum 975 * 976 * @event core.acp_manage_forums_validate_data 977 * @var array forum_data Array with new forum data 978 * @var array errors Array of errors, should be strings and not 979 * language key. 980 * @since 3.1.0-a1 981 */ 982 $vars = array('forum_data', 'errors'); 983 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_validate_data', compact($vars))); 984 $forum_data_ary = $forum_data; 985 unset($forum_data); 986 987 if ($forum_data_ary['forum_name'] == '') 988 { 989 $errors[] = $user->lang['FORUM_NAME_EMPTY']; 990 } 991 992 /** 993 * Replace Emojis and other 4bit UTF-8 chars not allowed by MySql to UCR / NCR. 994 * Using their Numeric Character Reference's Hexadecimal notation. 995 */ 996 $forum_data_ary['forum_name'] = utf8_encode_ucr($forum_data_ary['forum_name']); 997 998 /** 999 * This should never happen again. 1000 * Leaving the fallback here just in case there will be the need of it. 1001 */ 1002 if (preg_match_all('/[\x{10000}-\x{10FFFF}]/u', $forum_data_ary['forum_name'], $matches)) 1003 { 1004 $character_list = implode('<br>', $matches[0]); 1005 1006 $errors[] = $user->lang('FORUM_NAME_EMOJI', $character_list); 1007 } 1008 1009 if (utf8_strlen($forum_data_ary['forum_desc']) > 4000) 1010 { 1011 $errors[] = $user->lang['FORUM_DESC_TOO_LONG']; 1012 } 1013 1014 if (utf8_strlen($forum_data_ary['forum_rules']) > 4000) 1015 { 1016 $errors[] = $user->lang['FORUM_RULES_TOO_LONG']; 1017 } 1018 1019 if ($forum_data_ary['forum_password'] || $forum_data_ary['forum_password_confirm']) 1020 { 1021 if ($forum_data_ary['forum_password'] != $forum_data_ary['forum_password_confirm']) 1022 { 1023 $forum_data_ary['forum_password'] = $forum_data_ary['forum_password_confirm'] = ''; 1024 $errors[] = $user->lang['FORUM_PASSWORD_MISMATCH']; 1025 } 1026 } 1027 1028 if ($forum_data_ary['prune_days'] < 0 || $forum_data_ary['prune_viewed'] < 0 || $forum_data_ary['prune_freq'] < 0) 1029 { 1030 $forum_data_ary['prune_days'] = $forum_data_ary['prune_viewed'] = $forum_data_ary['prune_freq'] = 0; 1031 $errors[] = $user->lang['FORUM_DATA_NEGATIVE']; 1032 } 1033 1034 $range_test_ary = array( 1035 array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data_ary['forum_topics_per_page'], 'column_type' => 'USINT:0'), 1036 ); 1037 1038 if (!empty($forum_data_ary['forum_image']) && !file_exists($phpbb_root_path . $forum_data_ary['forum_image'])) 1039 { 1040 $errors[] = $user->lang['FORUM_IMAGE_NO_EXIST']; 1041 } 1042 1043 validate_range($range_test_ary, $errors); 1044 1045 // Set forum flags 1046 // 1 = link tracking 1047 // 2 = prune old polls 1048 // 4 = prune announcements 1049 // 8 = prune stickies 1050 // 16 = show active topics 1051 // 32 = enable post review 1052 $forum_data_ary['forum_flags'] = 0; 1053 $forum_data_ary['forum_flags'] += ($forum_data_ary['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0; 1054 $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0; 1055 $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0; 1056 $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0; 1057 $forum_data_ary['forum_flags'] += ($forum_data_ary['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0; 1058 $forum_data_ary['forum_flags'] += ($forum_data_ary['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0; 1059 $forum_data_ary['forum_flags'] += ($forum_data_ary['enable_quick_reply']) ? FORUM_FLAG_QUICK_REPLY : 0; 1060 1061 // Unset data that are not database fields 1062 $forum_data_sql = $forum_data_ary; 1063 1064 unset($forum_data_sql['forum_link_track']); 1065 unset($forum_data_sql['prune_old_polls']); 1066 unset($forum_data_sql['prune_announce']); 1067 unset($forum_data_sql['prune_sticky']); 1068 unset($forum_data_sql['show_active']); 1069 unset($forum_data_sql['enable_post_review']); 1070 unset($forum_data_sql['enable_quick_reply']); 1071 unset($forum_data_sql['forum_password_confirm']); 1072 1073 // What are we going to do tonight Brain? The same thing we do everynight, 1074 // try to take over the world ... or decide whether to continue update 1075 // and if so, whether it's a new forum/cat/link or an existing one 1076 if (count($errors)) 1077 { 1078 return $errors; 1079 } 1080 1081 // As we don't know the old password, it's kinda tricky to detect changes 1082 if ($forum_data_sql['forum_password_unset']) 1083 { 1084 $forum_data_sql['forum_password'] = ''; 1085 } 1086 else if (empty($forum_data_sql['forum_password'])) 1087 { 1088 unset($forum_data_sql['forum_password']); 1089 } 1090 else 1091 { 1092 // Instantiate passwords manager 1093 /* @var $passwords_manager \phpbb\passwords\manager */ 1094 $passwords_manager = $phpbb_container->get('passwords.manager'); 1095 1096 $forum_data_sql['forum_password'] = $passwords_manager->hash($forum_data_sql['forum_password']); 1097 } 1098 unset($forum_data_sql['forum_password_unset']); 1099 1100 $forum_data = $forum_data_ary; 1101 /** 1102 * Remove invalid values from forum_data_sql that should not be updated 1103 * 1104 * @event core.acp_manage_forums_update_data_before 1105 * @var array forum_data Array with forum data 1106 * @var array forum_data_sql Array with data we are going to update 1107 * If forum_data_sql[forum_id] is set, we update 1108 * that forum, otherwise a new one is created. 1109 * @since 3.1.0-a1 1110 */ 1111 $vars = array('forum_data', 'forum_data_sql'); 1112 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_before', compact($vars))); 1113 $forum_data_ary = $forum_data; 1114 unset($forum_data); 1115 1116 $is_new_forum = !isset($forum_data_sql['forum_id']); 1117 1118 if ($is_new_forum) 1119 { 1120 // no forum_id means we're creating a new forum 1121 unset($forum_data_sql['type_action']); 1122 1123 if ($forum_data_sql['parent_id']) 1124 { 1125 $sql = 'SELECT left_id, right_id, forum_type 1126 FROM ' . FORUMS_TABLE . ' 1127 WHERE forum_id = ' . $forum_data_sql['parent_id']; 1128 $result = $db->sql_query($sql); 1129 $row = $db->sql_fetchrow($result); 1130 $db->sql_freeresult($result); 1131 1132 if (!$row) 1133 { 1134 trigger_error($user->lang['PARENT_NOT_EXIST'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); 1135 } 1136 1137 if ($row['forum_type'] == FORUM_LINK) 1138 { 1139 $errors[] = $user->lang['PARENT_IS_LINK_FORUM']; 1140 return $errors; 1141 } 1142 1143 $sql = 'UPDATE ' . FORUMS_TABLE . ' 1144 SET left_id = left_id + 2, right_id = right_id + 2 1145 WHERE left_id > ' . $row['right_id']; 1146 $db->sql_query($sql); 1147 1148 $sql = 'UPDATE ' . FORUMS_TABLE . ' 1149 SET right_id = right_id + 2 1150 WHERE ' . $row['left_id'] . ' BETWEEN left_id AND right_id'; 1151 $db->sql_query($sql); 1152 1153 $forum_data_sql['left_id'] = $row['right_id']; 1154 $forum_data_sql['right_id'] = $row['right_id'] + 1; 1155 } 1156 else 1157 { 1158 $sql = 'SELECT MAX(right_id) AS right_id 1159 FROM ' . FORUMS_TABLE; 1160 $result = $db->sql_query($sql); 1161 $row = $db->sql_fetchrow($result); 1162 $db->sql_freeresult($result); 1163 1164 $forum_data_sql['left_id'] = $row['right_id'] + 1; 1165 $forum_data_sql['right_id'] = $row['right_id'] + 2; 1166 } 1167 1168 $sql = 'INSERT INTO ' . FORUMS_TABLE . ' ' . $db->sql_build_array('INSERT', $forum_data_sql); 1169 $db->sql_query($sql); 1170 1171 $forum_data_ary['forum_id'] = $db->sql_nextid(); 1172 1173 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_ADD', false, array($forum_data_ary['forum_name'])); 1174 } 1175 else 1176 { 1177 $row = $this->get_forum_info($forum_data_sql['forum_id']); 1178 1179 if ($row['forum_type'] == FORUM_POST && $row['forum_type'] != $forum_data_sql['forum_type']) 1180 { 1181 // Has subforums and want to change into a link? 1182 if ($row['right_id'] - $row['left_id'] > 1 && $forum_data_sql['forum_type'] == FORUM_LINK) 1183 { 1184 $errors[] = $user->lang['FORUM_WITH_SUBFORUMS_NOT_TO_LINK']; 1185 return $errors; 1186 } 1187 1188 // we're turning a postable forum into a non-postable forum 1189 if ($forum_data_sql['type_action'] == 'move') 1190 { 1191 $to_forum_id = $request->variable('to_forum_id', 0); 1192 1193 if ($to_forum_id) 1194 { 1195 $errors = $this->move_forum_content($forum_data_sql['forum_id'], $to_forum_id); 1196 } 1197 else 1198 { 1199 return array($user->lang['NO_DESTINATION_FORUM']); 1200 } 1201 } 1202 else if ($forum_data_sql['type_action'] == 'delete') 1203 { 1204 $errors = $this->delete_forum_content($forum_data_sql['forum_id']); 1205 } 1206 else 1207 { 1208 return array($user->lang['NO_FORUM_ACTION']); 1209 } 1210 1211 $forum_data_sql['forum_posts_approved'] = $forum_data_sql['forum_posts_unapproved'] = $forum_data_sql['forum_posts_softdeleted'] = $forum_data_sql['forum_topics_approved'] = $forum_data_sql['forum_topics_unapproved'] = $forum_data_sql['forum_topics_softdeleted'] = 0; 1212 $forum_data_sql['forum_last_post_id'] = $forum_data_sql['forum_last_poster_id'] = $forum_data_sql['forum_last_post_time'] = 0; 1213 $forum_data_sql['forum_last_poster_name'] = $forum_data_sql['forum_last_poster_colour'] = ''; 1214 } 1215 else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_LINK) 1216 { 1217 // Has subforums? 1218 if ($row['right_id'] - $row['left_id'] > 1) 1219 { 1220 // We are turning a category into a link - but need to decide what to do with the subforums. 1221 $action_subforums = $request->variable('action_subforums', ''); 1222 $subforums_to_id = $request->variable('subforums_to_id', 0); 1223 1224 if ($action_subforums == 'delete') 1225 { 1226 $rows = get_forum_branch($row['forum_id'], 'children', 'descending', false); 1227 1228 foreach ($rows as $_row) 1229 { 1230 // Do not remove the forum id we are about to change. ;) 1231 if ($_row['forum_id'] == $row['forum_id']) 1232 { 1233 continue; 1234 } 1235 1236 $forum_ids[] = $_row['forum_id']; 1237 $errors = array_merge($errors, $this->delete_forum_content($_row['forum_id'])); 1238 } 1239 1240 if (count($errors)) 1241 { 1242 return $errors; 1243 } 1244 1245 if (count($forum_ids)) 1246 { 1247 $sql = 'DELETE FROM ' . FORUMS_TABLE . ' 1248 WHERE ' . $db->sql_in_set('forum_id', $forum_ids); 1249 $db->sql_query($sql); 1250 1251 $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' 1252 WHERE ' . $db->sql_in_set('forum_id', $forum_ids); 1253 $db->sql_query($sql); 1254 1255 $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' 1256 WHERE ' . $db->sql_in_set('forum_id', $forum_ids); 1257 $db->sql_query($sql); 1258 1259 // Delete forum ids from extension groups table 1260 $sql = 'SELECT group_id, allowed_forums 1261 FROM ' . EXTENSION_GROUPS_TABLE; 1262 $result = $db->sql_query($sql); 1263 1264 while ($_row = $db->sql_fetchrow($result)) 1265 { 1266 if (!$_row['allowed_forums']) 1267 { 1268 continue; 1269 } 1270 1271 $allowed_forums = unserialize(trim($_row['allowed_forums'])); 1272 $allowed_forums = array_diff($allowed_forums, $forum_ids); 1273 1274 $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . " 1275 SET allowed_forums = '" . ((count($allowed_forums)) ? serialize($allowed_forums) : '') . "' 1276 WHERE group_id = {$_row['group_id']}"; 1277 $db->sql_query($sql); 1278 } 1279 $db->sql_freeresult($result); 1280 1281 $cache->destroy('_extensions'); 1282 } 1283 } 1284 else if ($action_subforums == 'move') 1285 { 1286 if (!$subforums_to_id) 1287 { 1288 return array($user->lang['NO_DESTINATION_FORUM']); 1289 } 1290 1291 $sql = 'SELECT forum_name 1292 FROM ' . FORUMS_TABLE . ' 1293 WHERE forum_id = ' . $subforums_to_id; 1294 $result = $db->sql_query($sql); 1295 $_row = $db->sql_fetchrow($result); 1296 $db->sql_freeresult($result); 1297 1298 if (!$_row) 1299 { 1300 return array($user->lang['NO_FORUM']); 1301 } 1302 1303 $sql = 'SELECT forum_id 1304 FROM ' . FORUMS_TABLE . " 1305 WHERE parent_id = {$row['forum_id']}"; 1306 $result = $db->sql_query($sql); 1307 1308 while ($_row = $db->sql_fetchrow($result)) 1309 { 1310 $this->move_forum($_row['forum_id'], $subforums_to_id); 1311 } 1312 $db->sql_freeresult($result); 1313 1314 $sql = 'UPDATE ' . FORUMS_TABLE . " 1315 SET parent_id = $subforums_to_id 1316 WHERE parent_id = {$row['forum_id']}"; 1317 $db->sql_query($sql); 1318 } 1319 1320 // Adjust the left/right id 1321 $sql = 'UPDATE ' . FORUMS_TABLE . ' 1322 SET right_id = left_id + 1 1323 WHERE forum_id = ' . $row['forum_id']; 1324 $db->sql_query($sql); 1325 } 1326 } 1327 else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_POST) 1328 { 1329 // Changing a category to a forum? Reset the data (you can't post directly in a cat, you must use a forum) 1330 $forum_data_sql['forum_posts_approved'] = 0; 1331 $forum_data_sql['forum_posts_unapproved'] = 0; 1332 $forum_data_sql['forum_posts_softdeleted'] = 0; 1333 $forum_data_sql['forum_topics_approved'] = 0; 1334 $forum_data_sql['forum_topics_unapproved'] = 0; 1335 $forum_data_sql['forum_topics_softdeleted'] = 0; 1336 $forum_data_sql['forum_last_post_id'] = 0; 1337 $forum_data_sql['forum_last_post_subject'] = ''; 1338 $forum_data_sql['forum_last_post_time'] = 0; 1339 $forum_data_sql['forum_last_poster_id'] = 0; 1340 $forum_data_sql['forum_last_poster_name'] = ''; 1341 $forum_data_sql['forum_last_poster_colour'] = ''; 1342 } 1343 1344 if (count($errors)) 1345 { 1346 return $errors; 1347 } 1348 1349 if ($row['parent_id'] != $forum_data_sql['parent_id']) 1350 { 1351 if ($row['forum_id'] != $forum_data_sql['parent_id']) 1352 { 1353 $errors = $this->move_forum($forum_data_sql['forum_id'], $forum_data_sql['parent_id']); 1354 } 1355 else 1356 { 1357 $forum_data_sql['parent_id'] = $row['parent_id']; 1358 } 1359 } 1360 1361 if (count($errors)) 1362 { 1363 return $errors; 1364 } 1365 1366 unset($forum_data_sql['type_action']); 1367 1368 if ($row['forum_name'] != $forum_data_sql['forum_name']) 1369 { 1370 // the forum name has changed, clear the parents list of all forums (for safety) 1371 $sql = 'UPDATE ' . FORUMS_TABLE . " 1372 SET forum_parents = ''"; 1373 $db->sql_query($sql); 1374 } 1375 1376 // Setting the forum id to the forum id is not really received well by some dbs. ;) 1377 $forum_id = $forum_data_sql['forum_id']; 1378 unset($forum_data_sql['forum_id']); 1379 1380 $sql = 'UPDATE ' . FORUMS_TABLE . ' 1381 SET ' . $db->sql_build_array('UPDATE', $forum_data_sql) . ' 1382 WHERE forum_id = ' . $forum_id; 1383 $db->sql_query($sql); 1384 1385 // Add it back 1386 $forum_data_ary['forum_id'] = $forum_id; 1387 1388 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_EDIT', false, array($forum_data_ary['forum_name'])); 1389 } 1390 1391 $forum_data = $forum_data_ary; 1392 /** 1393 * Event after a forum was updated or created 1394 * 1395 * @event core.acp_manage_forums_update_data_after 1396 * @var array forum_data Array with forum data 1397 * @var array forum_data_sql Array with data we updated 1398 * @var bool is_new_forum Did we create a forum or update one 1399 * If you want to overwrite this value, 1400 * ensure to set forum_data_sql[forum_id] 1401 * @var array errors Array of errors, should be strings and not 1402 * language key. 1403 * @since 3.1.0-a1 1404 */ 1405 $vars = array('forum_data', 'forum_data_sql', 'is_new_forum', 'errors'); 1406 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_after', compact($vars))); 1407 $forum_data_ary = $forum_data; 1408 unset($forum_data); 1409 1410 return $errors; 1411 } 1412 1413 /** 1414 * Move forum 1415 */ 1416 function move_forum($from_id, $to_id) 1417 { 1418 global $db, $user, $phpbb_dispatcher; 1419 1420 $errors = array(); 1421 1422 // Check if we want to move to a parent with link type 1423 if ($to_id > 0) 1424 { 1425 $to_data = $this->get_forum_info($to_id); 1426 1427 if ($to_data['forum_type'] == FORUM_LINK) 1428 { 1429 $errors[] = $user->lang['PARENT_IS_LINK_FORUM']; 1430 } 1431 } 1432 1433 /** 1434 * Event when we move all children of one forum to another 1435 * 1436 * This event may be triggered, when a forum is deleted 1437 * 1438 * @event core.acp_manage_forums_move_children 1439 * @var int from_id Id of the current parent forum 1440 * @var int to_id Id of the new parent forum 1441 * @var array errors Array of errors, should be strings and not 1442 * language key. 1443 * @since 3.1.0-a1 1444 */ 1445 $vars = array('from_id', 'to_id', 'errors'); 1446 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_children', compact($vars))); 1447 1448 // Return if there were errors 1449 if (!empty($errors)) 1450 { 1451 return $errors; 1452 } 1453 1454 $db->sql_transaction('begin'); 1455 1456 $moved_forums = get_forum_branch($from_id, 'children', 'descending'); 1457 $from_data = $moved_forums[0]; 1458 $diff = count($moved_forums) * 2; 1459 1460 $moved_ids = array(); 1461 for ($i = 0, $size = count($moved_forums); $i < $size; ++$i) 1462 { 1463 $moved_ids[] = $moved_forums[$i]['forum_id']; 1464 } 1465 1466 // Resync parents 1467 $sql = 'UPDATE ' . FORUMS_TABLE . " 1468 SET right_id = right_id - $diff, forum_parents = '' 1469 WHERE left_id < " . $from_data['right_id'] . " 1470 AND right_id > " . $from_data['right_id']; 1471 $db->sql_query($sql); 1472 1473 // Resync righthand side of tree 1474 $sql = 'UPDATE ' . FORUMS_TABLE . " 1475 SET left_id = left_id - $diff, right_id = right_id - $diff, forum_parents = '' 1476 WHERE left_id > " . $from_data['right_id']; 1477 $db->sql_query($sql); 1478 1479 if ($to_id > 0) 1480 { 1481 // Retrieve $to_data again, it may have been changed... 1482 $to_data = $this->get_forum_info($to_id); 1483 1484 // Resync new parents 1485 $sql = 'UPDATE ' . FORUMS_TABLE . " 1486 SET right_id = right_id + $diff, forum_parents = '' 1487 WHERE " . $to_data['right_id'] . ' BETWEEN left_id AND right_id 1488 AND ' . $db->sql_in_set('forum_id', $moved_ids, true); 1489 $db->sql_query($sql); 1490 1491 // Resync the righthand side of the tree 1492 $sql = 'UPDATE ' . FORUMS_TABLE . " 1493 SET left_id = left_id + $diff, right_id = right_id + $diff, forum_parents = '' 1494 WHERE left_id > " . $to_data['right_id'] . ' 1495 AND ' . $db->sql_in_set('forum_id', $moved_ids, true); 1496 $db->sql_query($sql); 1497 1498 // Resync moved branch 1499 $to_data['right_id'] += $diff; 1500 1501 if ($to_data['right_id'] > $from_data['right_id']) 1502 { 1503 $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1); 1504 } 1505 else 1506 { 1507 $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1); 1508 } 1509 } 1510 else 1511 { 1512 $sql = 'SELECT MAX(right_id) AS right_id 1513 FROM ' . FORUMS_TABLE . ' 1514 WHERE ' . $db->sql_in_set('forum_id', $moved_ids, true); 1515 $result = $db->sql_query($sql); 1516 $row = $db->sql_fetchrow($result); 1517 $db->sql_freeresult($result); 1518 1519 $diff = '+ ' . ($row['right_id'] - $from_data['left_id'] + 1); 1520 } 1521 1522 $sql = 'UPDATE ' . FORUMS_TABLE . " 1523 SET left_id = left_id $diff, right_id = right_id $diff, forum_parents = '' 1524 WHERE " . $db->sql_in_set('forum_id', $moved_ids); 1525 $db->sql_query($sql); 1526 1527 $db->sql_transaction('commit'); 1528 1529 return $errors; 1530 } 1531 1532 /** 1533 * Move forum content from one to another forum 1534 */ 1535 function move_forum_content($from_id, $to_id, $sync = true) 1536 { 1537 global $db, $phpbb_dispatcher; 1538 1539 $errors = array(); 1540 1541 /** 1542 * Event when we move content from one forum to another 1543 * 1544 * @event core.acp_manage_forums_move_content 1545 * @var int from_id Id of the current parent forum 1546 * @var int to_id Id of the new parent forum 1547 * @var bool sync Shall we sync the "to"-forum's data 1548 * @var array errors Array of errors, should be strings and not 1549 * language key. If this array is not empty, 1550 * The content will not be moved. 1551 * @since 3.1.0-a1 1552 */ 1553 $vars = array('from_id', 'to_id', 'sync', 'errors'); 1554 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_content', compact($vars))); 1555 1556 // Return if there were errors 1557 if (!empty($errors)) 1558 { 1559 return $errors; 1560 } 1561 1562 $table_ary = array(LOG_TABLE, POSTS_TABLE, TOPICS_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); 1563 1564 /** 1565 * Perform additional actions before move forum content 1566 * 1567 * @event core.acp_manage_forums_move_content_sql_before 1568 * @var array table_ary Array of tables from which forum_id will be updated 1569 * @since 3.2.4-RC1 1570 */ 1571 $vars = array('table_ary'); 1572 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_content_sql_before', compact($vars))); 1573 1574 foreach ($table_ary as $table) 1575 { 1576 $sql = "UPDATE $table 1577 SET forum_id = $to_id 1578 WHERE forum_id = $from_id"; 1579 $db->sql_query($sql); 1580 } 1581 unset($table_ary); 1582 1583 $table_ary = array(FORUMS_ACCESS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, MODERATOR_CACHE_TABLE); 1584 1585 foreach ($table_ary as $table) 1586 { 1587 $sql = "DELETE FROM $table 1588 WHERE forum_id = $from_id"; 1589 $db->sql_query($sql); 1590 } 1591 1592 /** 1593 * Event when content has been moved from one forum to another 1594 * 1595 * @event core.acp_manage_forums_move_content_after 1596 * @var int from_id Id of the current parent forum 1597 * @var int to_id Id of the new parent forum 1598 * @var bool sync Shall we sync the "to"-forum's data 1599 * 1600 * @since 3.2.9-RC1 1601 */ 1602 $vars = array('from_id', 'to_id', 'sync'); 1603 extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_content_after', compact($vars))); 1604 1605 if ($sync) 1606 { 1607 // Delete ghost topics that link back to the same forum then resync counters 1608 sync('topic_moved'); 1609 sync('forum', 'forum_id', $to_id, false, true); 1610 } 1611 1612 return array(); 1613 } 1614 1615 /** 1616 * Remove complete forum 1617 */ 1618 function delete_forum($forum_id, $action_posts = 'delete', $action_subforums = 'delete', $posts_to_id = 0, $subforums_to_id = 0) 1619 { 1620 global $db, $user, $cache, $phpbb_log; 1621 1622 $forum_data = $this->get_forum_info($forum_id); 1623 1624 $errors = array(); 1625 $log_action_posts = $log_action_forums = $posts_to_name = $subforums_to_name = ''; 1626 $forum_ids = array($forum_id); 1627 1628 if ($action_posts == 'delete') 1629 { 1630 $log_action_posts = 'POSTS'; 1631 $errors = array_merge($errors, $this->delete_forum_content($forum_id)); 1632 } 1633 else if ($action_posts == 'move') 1634 { 1635 if (!$posts_to_id) 1636 { 1637 $errors[] = $user->lang['NO_DESTINATION_FORUM']; 1638 } 1639 else 1640 { 1641 $log_action_posts = 'MOVE_POSTS'; 1642 1643 $sql = 'SELECT forum_name 1644 FROM ' . FORUMS_TABLE . ' 1645 WHERE forum_id = ' . $posts_to_id; 1646 $result = $db->sql_query($sql); 1647 $row = $db->sql_fetchrow($result); 1648 $db->sql_freeresult($result); 1649 1650 if (!$row) 1651 { 1652 $errors[] = $user->lang['NO_FORUM']; 1653 } 1654 else 1655 { 1656 $posts_to_name = $row['forum_name']; 1657 $errors = array_merge($errors, $this->move_forum_content($forum_id, $posts_to_id)); 1658 } 1659 } 1660 } 1661 1662 if (count($errors)) 1663 { 1664 return $errors; 1665 } 1666 1667 if ($action_subforums == 'delete') 1668 { 1669 $log_action_forums = 'FORUMS'; 1670 $rows = get_forum_branch($forum_id, 'children', 'descending', false); 1671 1672 foreach ($rows as $row) 1673 { 1674 $forum_ids[] = $row['forum_id']; 1675 $errors = array_merge($errors, $this->delete_forum_content($row['forum_id'])); 1676 } 1677 1678 if (count($errors)) 1679 { 1680 return $errors; 1681 } 1682 1683 $diff = count($forum_ids) * 2; 1684 1685 $sql = 'DELETE FROM ' . FORUMS_TABLE . ' 1686 WHERE ' . $db->sql_in_set('forum_id', $forum_ids); 1687 $db->sql_query($sql); 1688 1689 $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' 1690 WHERE ' . $db->sql_in_set('forum_id', $forum_ids); 1691 $db->sql_query($sql); 1692 1693 $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' 1694 WHERE ' . $db->sql_in_set('forum_id', $forum_ids); 1695 $db->sql_query($sql); 1696 } 1697 else if ($action_subforums == 'move') 1698 { 1699 if (!$subforums_to_id) 1700 { 1701 $errors[] = $user->lang['NO_DESTINATION_FORUM']; 1702 } 1703 else 1704 { 1705 $log_action_forums = 'MOVE_FORUMS'; 1706 1707 $sql = 'SELECT forum_name 1708 FROM ' . FORUMS_TABLE . ' 1709 WHERE forum_id = ' . $subforums_to_id; 1710 $result = $db->sql_query($sql); 1711 $row = $db->sql_fetchrow($result); 1712 $db->sql_freeresult($result); 1713 1714 if (!$row) 1715 { 1716 $errors[] = $user->lang['NO_FORUM']; 1717 } 1718 else 1719 { 1720 $subforums_to_name = $row['forum_name']; 1721 1722 $sql = 'SELECT forum_id 1723 FROM ' . FORUMS_TABLE . " 1724 WHERE parent_id = $forum_id"; 1725 $result = $db->sql_query($sql); 1726 1727 while ($row = $db->sql_fetchrow($result)) 1728 { 1729 $this->move_forum($row['forum_id'], $subforums_to_id); 1730 } 1731 $db->sql_freeresult($result); 1732 1733 // Grab new forum data for correct tree updating later 1734 $forum_data = $this->get_forum_info($forum_id); 1735 1736 $sql = 'UPDATE ' . FORUMS_TABLE . " 1737 SET parent_id = $subforums_to_id 1738 WHERE parent_id = $forum_id"; 1739 $db->sql_query($sql); 1740 1741 $diff = 2; 1742 $sql = 'DELETE FROM ' . FORUMS_TABLE . " 1743 WHERE forum_id = $forum_id"; 1744 $db->sql_query($sql); 1745 1746 $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . " 1747 WHERE forum_id = $forum_id"; 1748 $db->sql_query($sql); 1749 1750 $sql = 'DELETE FROM ' . ACL_USERS_TABLE . " 1751 WHERE forum_id = $forum_id"; 1752 $db->sql_query($sql); 1753 } 1754 } 1755 1756 if (count($errors)) 1757 { 1758 return $errors; 1759 } 1760 } 1761 else 1762 { 1763 $diff = 2; 1764 $sql = 'DELETE FROM ' . FORUMS_TABLE . " 1765 WHERE forum_id = $forum_id"; 1766 $db->sql_query($sql); 1767 1768 $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . " 1769 WHERE forum_id = $forum_id"; 1770 $db->sql_query($sql); 1771 1772 $sql = 'DELETE FROM ' . ACL_USERS_TABLE . " 1773 WHERE forum_id = $forum_id"; 1774 $db->sql_query($sql); 1775 } 1776 1777 // Resync tree 1778 $sql = 'UPDATE ' . FORUMS_TABLE . " 1779 SET right_id = right_id - $diff 1780 WHERE left_id < {$forum_data['right_id']} AND right_id > {$forum_data['right_id']}"; 1781 $db->sql_query($sql); 1782 1783 $sql = 'UPDATE ' . FORUMS_TABLE . " 1784 SET left_id = left_id - $diff, right_id = right_id - $diff 1785 WHERE left_id > {$forum_data['right_id']}"; 1786 $db->sql_query($sql); 1787 1788 // Delete forum ids from extension groups table 1789 $sql = 'SELECT group_id, allowed_forums 1790 FROM ' . EXTENSION_GROUPS_TABLE; 1791 $result = $db->sql_query($sql); 1792 1793 while ($row = $db->sql_fetchrow($result)) 1794 { 1795 if (!$row['allowed_forums']) 1796 { 1797 continue; 1798 } 1799 1800 $allowed_forums = unserialize(trim($row['allowed_forums'])); 1801 $allowed_forums = array_diff($allowed_forums, $forum_ids); 1802 1803 $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . " 1804 SET allowed_forums = '" . ((count($allowed_forums)) ? serialize($allowed_forums) : '') . "' 1805 WHERE group_id = {$row['group_id']}"; 1806 $db->sql_query($sql); 1807 } 1808 $db->sql_freeresult($result); 1809 1810 $cache->destroy('_extensions'); 1811 1812 $log_action = implode('_', array($log_action_posts, $log_action_forums)); 1813 1814 switch ($log_action) 1815 { 1816 case 'MOVE_POSTS_MOVE_FORUMS': 1817 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS_MOVE_FORUMS', false, array($posts_to_name, $subforums_to_name, $forum_data['forum_name'])); 1818 break; 1819 1820 case 'MOVE_POSTS_FORUMS': 1821 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS', false, array($posts_to_name, $forum_data['forum_name'])); 1822 break; 1823 1824 case 'POSTS_MOVE_FORUMS': 1825 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS', false, array($subforums_to_name, $forum_data['forum_name'])); 1826 break; 1827 1828 case '_MOVE_FORUMS': 1829 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_FORUMS', false, array($subforums_to_name, $forum_data['forum_name'])); 1830 break; 1831 1832 case 'MOVE_POSTS_': 1833 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_MOVE_POSTS', false, array($posts_to_name, $forum_data['forum_name'])); 1834 break; 1835 1836 case 'POSTS_FORUMS': 1837 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS_FORUMS', false, array($forum_data['forum_name'])); 1838 break; 1839 1840 case '_FORUMS': 1841 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_FORUMS', false, array($forum_data['forum_name'])); 1842 break; 1843 1844 case 'POSTS_': 1845 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_POSTS', false, array($forum_data['forum_name'])); 1846 break; 1847 1848 default: 1849 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_DEL_FORUM', false, array($forum_data['forum_name'])); 1850 break; 1851 } 1852 1853 return $errors; 1854 } 1855 1856 /** 1857 * Delete forum content 1858 */ 1859 function delete_forum_content($forum_id) 1860 { 1861 global $db, $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher; 1862 1863 include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); 1864 1865 $db->sql_transaction('begin'); 1866 1867 // Select then delete all attachments 1868 $sql = 'SELECT a.topic_id 1869 FROM ' . POSTS_TABLE . ' p, ' . ATTACHMENTS_TABLE . " a 1870 WHERE p.forum_id = $forum_id 1871 AND a.in_message = 0 1872 AND a.topic_id = p.topic_id"; 1873 $result = $db->sql_query($sql); 1874 1875 $topic_ids = array(); 1876 while ($row = $db->sql_fetchrow($result)) 1877 { 1878 $topic_ids[] = $row['topic_id']; 1879 } 1880 $db->sql_freeresult($result); 1881 1882 /** @var \phpbb\attachment\manager $attachment_manager */ 1883 $attachment_manager = $phpbb_container->get('attachment.manager'); 1884 $attachment_manager->delete('topic', $topic_ids, false); 1885 unset($attachment_manager); 1886 1887 // Delete shadow topics pointing to topics in this forum 1888 delete_topic_shadows($forum_id); 1889 1890 // Before we remove anything we make sure we are able to adjust the post counts later. ;) 1891 $sql = 'SELECT poster_id 1892 FROM ' . POSTS_TABLE . ' 1893 WHERE forum_id = ' . $forum_id . ' 1894 AND post_postcount = 1 1895 AND post_visibility = ' . ITEM_APPROVED; 1896 $result = $db->sql_query($sql); 1897 1898 $post_counts = array(); 1899 while ($row = $db->sql_fetchrow($result)) 1900 { 1901 $post_counts[$row['poster_id']] = (!empty($post_counts[$row['poster_id']])) ? $post_counts[$row['poster_id']] + 1 : 1; 1902 } 1903 $db->sql_freeresult($result); 1904 1905 switch ($db->get_sql_layer()) 1906 { 1907 case 'mysqli': 1908 1909 // Delete everything else and thank MySQL for offering multi-table deletion 1910 $tables_ary = array( 1911 SEARCH_WORDMATCH_TABLE => 'post_id', 1912 REPORTS_TABLE => 'post_id', 1913 WARNINGS_TABLE => 'post_id', 1914 BOOKMARKS_TABLE => 'topic_id', 1915 TOPICS_WATCH_TABLE => 'topic_id', 1916 TOPICS_POSTED_TABLE => 'topic_id', 1917 POLL_OPTIONS_TABLE => 'topic_id', 1918 POLL_VOTES_TABLE => 'topic_id', 1919 ); 1920 1921 $sql = 'DELETE ' . POSTS_TABLE; 1922 $sql_using = "\nFROM " . POSTS_TABLE; 1923 $sql_where = "\nWHERE " . POSTS_TABLE . ".forum_id = $forum_id\n"; 1924 1925 foreach ($tables_ary as $table => $field) 1926 { 1927 $sql .= ", $table "; 1928 $sql_using .= ", $table "; 1929 $sql_where .= "\nAND $table.$field = " . POSTS_TABLE . ".$field"; 1930 } 1931 1932 $db->sql_query($sql . $sql_using . $sql_where); 1933 1934 break; 1935 1936 default: 1937 1938 // Delete everything else and curse your DB for not offering multi-table deletion 1939 $tables_ary = array( 1940 'post_id' => array( 1941 SEARCH_WORDMATCH_TABLE, 1942 REPORTS_TABLE, 1943 WARNINGS_TABLE, 1944 ), 1945 1946 'topic_id' => array( 1947 BOOKMARKS_TABLE, 1948 TOPICS_WATCH_TABLE, 1949 TOPICS_POSTED_TABLE, 1950 POLL_OPTIONS_TABLE, 1951 POLL_VOTES_TABLE, 1952 ) 1953 ); 1954 1955 // Amount of rows we select and delete in one iteration. 1956 $batch_size = 500; 1957 1958 foreach ($tables_ary as $field => $tables) 1959 { 1960 $start = 0; 1961 1962 do 1963 { 1964 $sql = "SELECT $field 1965 FROM " . POSTS_TABLE . ' 1966 WHERE forum_id = ' . $forum_id; 1967 $result = $db->sql_query_limit($sql, $batch_size, $start); 1968 1969 $ids = array(); 1970 while ($row = $db->sql_fetchrow($result)) 1971 { 1972 $ids[] = $row[$field]; 1973 } 1974 $db->sql_freeresult($result); 1975 1976 if (count($ids)) 1977 { 1978 $start += count($ids); 1979 1980 foreach ($tables as $table) 1981 { 1982 $db->sql_query("DELETE FROM $table WHERE " . $db->sql_in_set($field, $ids)); 1983 } 1984 } 1985 } 1986 while (count($ids) == $batch_size); 1987 } 1988 unset($ids); 1989 1990 break; 1991 } 1992 1993 $table_ary = array(FORUMS_ACCESS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, LOG_TABLE, MODERATOR_CACHE_TABLE, POSTS_TABLE, TOPICS_TABLE, TOPICS_TRACK_TABLE); 1994 1995 /** 1996 * Perform additional actions before forum content deletion 1997 * 1998 * @event core.delete_forum_content_before_query 1999 * @var array table_ary Array of tables from which all rows will be deleted that hold the forum_id 2000 * @var int forum_id the forum id 2001 * @var array topic_ids Array of the topic ids from the forum to be deleted 2002 * @var array post_counts Array of counts of posts in the forum, by poster_id 2003 * @since 3.1.6-RC1 2004 */ 2005 $vars = array( 2006 'table_ary', 2007 'forum_id', 2008 'topic_ids', 2009 'post_counts', 2010 ); 2011 extract($phpbb_dispatcher->trigger_event('core.delete_forum_content_before_query', compact($vars))); 2012 2013 foreach ($table_ary as $table) 2014 { 2015 $db->sql_query("DELETE FROM $table WHERE forum_id = $forum_id"); 2016 } 2017 2018 // Set forum ids to 0 2019 $table_ary = array(DRAFTS_TABLE); 2020 2021 foreach ($table_ary as $table) 2022 { 2023 $db->sql_query("UPDATE $table SET forum_id = 0 WHERE forum_id = $forum_id"); 2024 } 2025 2026 // Adjust users post counts 2027 if (count($post_counts)) 2028 { 2029 foreach ($post_counts as $poster_id => $substract) 2030 { 2031 $sql = 'UPDATE ' . USERS_TABLE . ' 2032 SET user_posts = 0 2033 WHERE user_id = ' . $poster_id . ' 2034 AND user_posts < ' . $substract; 2035 $db->sql_query($sql); 2036 2037 $sql = 'UPDATE ' . USERS_TABLE . ' 2038 SET user_posts = user_posts - ' . $substract . ' 2039 WHERE user_id = ' . $poster_id . ' 2040 AND user_posts >= ' . $substract; 2041 $db->sql_query($sql); 2042 } 2043 } 2044 2045 $db->sql_transaction('commit'); 2046 2047 // Make sure the overall post/topic count is correct... 2048 $sql = 'SELECT COUNT(post_id) AS stat 2049 FROM ' . POSTS_TABLE . ' 2050 WHERE post_visibility = ' . ITEM_APPROVED; 2051 $result = $db->sql_query($sql); 2052 $row = $db->sql_fetchrow($result); 2053 $db->sql_freeresult($result); 2054 2055 $config->set('num_posts', (int) $row['stat'], false); 2056 2057 $sql = 'SELECT COUNT(topic_id) AS stat 2058 FROM ' . TOPICS_TABLE . ' 2059 WHERE topic_visibility = ' . ITEM_APPROVED; 2060 $result = $db->sql_query($sql); 2061 $row = $db->sql_fetchrow($result); 2062 $db->sql_freeresult($result); 2063 2064 $config->set('num_topics', (int) $row['stat'], false); 2065 2066 $sql = 'SELECT COUNT(attach_id) as stat 2067 FROM ' . ATTACHMENTS_TABLE; 2068 $result = $db->sql_query($sql); 2069 $row = $db->sql_fetchrow($result); 2070 $db->sql_freeresult($result); 2071 2072 $config->set('num_files', (int) $row['stat'], false); 2073 2074 $sql = 'SELECT SUM(filesize) as stat 2075 FROM ' . ATTACHMENTS_TABLE; 2076 $result = $db->sql_query($sql); 2077 $row = $db->sql_fetchrow($result); 2078 $db->sql_freeresult($result); 2079 2080 $config->set('upload_dir_size', (float) $row['stat'], false); 2081 2082 return array(); 2083 } 2084 2085 /** 2086 * Move forum position by $steps up/down 2087 */ 2088 function move_forum_by($forum_row, $action = 'move_up', $steps = 1) 2089 { 2090 global $db; 2091 2092 /** 2093 * Fetch all the siblings between the module's current spot 2094 * and where we want to move it to. If there are less than $steps 2095 * siblings between the current spot and the target then the 2096 * module will move as far as possible 2097 */ 2098 $sql = 'SELECT forum_id, forum_name, left_id, right_id 2099 FROM ' . FORUMS_TABLE . " 2100 WHERE parent_id = {$forum_row['parent_id']} 2101 AND " . (($action == 'move_up') ? "right_id < {$forum_row['right_id']} ORDER BY right_id DESC" : "left_id > {$forum_row['left_id']} ORDER BY left_id ASC"); 2102 $result = $db->sql_query_limit($sql, $steps); 2103 2104 $target = array(); 2105 while ($row = $db->sql_fetchrow($result)) 2106 { 2107 $target = $row; 2108 } 2109 $db->sql_freeresult($result); 2110 2111 if (!count($target)) 2112 { 2113 // The forum is already on top or bottom 2114 return false; 2115 } 2116 2117 /** 2118 * $left_id and $right_id define the scope of the nodes that are affected by the move. 2119 * $diff_up and $diff_down are the values to substract or add to each node's left_id 2120 * and right_id in order to move them up or down. 2121 * $move_up_left and $move_up_right define the scope of the nodes that are moving 2122 * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down. 2123 */ 2124 if ($action == 'move_up') 2125 { 2126 $left_id = $target['left_id']; 2127 $right_id = $forum_row['right_id']; 2128 2129 $diff_up = $forum_row['left_id'] - $target['left_id']; 2130 $diff_down = $forum_row['right_id'] + 1 - $forum_row['left_id']; 2131 2132 $move_up_left = $forum_row['left_id']; 2133 $move_up_right = $forum_row['right_id']; 2134 } 2135 else 2136 { 2137 $left_id = $forum_row['left_id']; 2138 $right_id = $target['right_id']; 2139 2140 $diff_up = $forum_row['right_id'] + 1 - $forum_row['left_id']; 2141 $diff_down = $target['right_id'] - $forum_row['right_id']; 2142 2143 $move_up_left = $forum_row['right_id'] + 1; 2144 $move_up_right = $target['right_id']; 2145 } 2146 2147 // Now do the dirty job 2148 $sql = 'UPDATE ' . FORUMS_TABLE . " 2149 SET left_id = left_id + CASE 2150 WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} 2151 ELSE {$diff_down} 2152 END, 2153 right_id = right_id + CASE 2154 WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} 2155 ELSE {$diff_down} 2156 END, 2157 forum_parents = '' 2158 WHERE 2159 left_id BETWEEN {$left_id} AND {$right_id} 2160 AND right_id BETWEEN {$left_id} AND {$right_id}"; 2161 $db->sql_query($sql); 2162 2163 return $target['forum_name']; 2164 } 2165 2166 /** 2167 * Display progress bar for syncinc forums 2168 */ 2169 function display_progress_bar($start, $total) 2170 { 2171 global $template, $user; 2172 2173 adm_page_header($user->lang['SYNC_IN_PROGRESS']); 2174 2175 $template->set_filenames(array( 2176 'body' => 'progress_bar.html') 2177 ); 2178 2179 $template->assign_vars(array( 2180 'L_PROGRESS' => $user->lang['SYNC_IN_PROGRESS'], 2181 'L_PROGRESS_EXPLAIN' => ($start && $total) ? sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $start, $total) : $user->lang['SYNC_IN_PROGRESS']) 2182 ); 2183 2184 adm_page_footer(); 2185 } 2186 2187 /** 2188 * Display copy permission page 2189 * Not used at the moment - we will have a look at it for 3.0.7 2190 */ 2191 function copy_permission_page($forum_data) 2192 { 2193 global $phpEx, $phpbb_admin_path, $template, $user; 2194 2195 $acl_url = '&mode=setting_forum_local&forum_id[]=' . $forum_data['forum_id']; 2196 $action = append_sid($this->u_action . "&parent_id={$this->parent_id}&f={$forum_data['forum_id']}&action=copy_perm"); 2197 2198 $l_acl = sprintf($user->lang['COPY_TO_ACL'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url) . '">', '</a>'); 2199 2200 $this->tpl_name = 'acp_forums_copy_perm'; 2201 2202 $template->assign_vars(array( 2203 'U_ACL' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url), 2204 'L_ACL_LINK' => $l_acl, 2205 'L_BACK_LINK' => adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), 2206 'S_COPY_ACTION' => $action, 2207 'S_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $forum_data['forum_id'], false, false, false), 2208 )); 2209 } 2210 2211} 2212