/** * Allows for moderation from the message index. * @todo refactor this... */ function QuickModeration() { global $sourcedir, $board, $user_info, $modSettings, $smcFunc, $context; // Check the session = get or post. checkSession('request'); // Lets go straight to the restore area. if (isset($_REQUEST['qaction']) && $_REQUEST['qaction'] == 'restore' && !empty($_REQUEST['topics'])) { redirectexit('action=restoretopic;topics=' . implode(',', $_REQUEST['topics']) . ';' . $context['session_var'] . '=' . $context['session_id']); } if (isset($_SESSION['topicseen_cache'])) { $_SESSION['topicseen_cache'] = array(); } // This is going to be needed to send off the notifications and for updateLastMessages(). require_once $sourcedir . '/Subs-Post.php'; // Remember the last board they moved things to. if (isset($_REQUEST['move_to'])) { $_SESSION['move_to_topic'] = $_REQUEST['move_to']; } // Only a few possible actions. $possibleActions = array(); if (!empty($board)) { $boards_can = array('make_sticky' => allowedTo('make_sticky') ? array($board) : array(), 'move_any' => allowedTo('move_any') ? array($board) : array(), 'move_own' => allowedTo('move_own') ? array($board) : array(), 'remove_any' => allowedTo('remove_any') ? array($board) : array(), 'remove_own' => allowedTo('remove_own') ? array($board) : array(), 'lock_any' => allowedTo('lock_any') ? array($board) : array(), 'lock_own' => allowedTo('lock_own') ? array($board) : array(), 'merge_any' => allowedTo('merge_any') ? array($board) : array(), 'approve_posts' => allowedTo('approve_posts') ? array($board) : array()); $redirect_url = 'board=' . $board . '.' . $_REQUEST['start']; } else { /** * @todo Ugly. There's no getting around this, is there? * @todo Maybe just do this on the actions people want to use? */ $boards_can = boardsAllowedTo(array('make_sticky', 'move_any', 'move_own', 'remove_any', 'remove_own', 'lock_any', 'lock_own', 'merge_any', 'approve_posts'), true, false); $redirect_url = isset($_POST['redirect_url']) ? $_POST['redirect_url'] : (isset($_SESSION['old_url']) ? $_SESSION['old_url'] : ''); } if (!$user_info['is_guest']) { $possibleActions[] = 'markread'; } if (!empty($boards_can['make_sticky']) && !empty($modSettings['enableStickyTopics'])) { $possibleActions[] = 'sticky'; } if (!empty($boards_can['move_any']) || !empty($boards_can['move_own'])) { $possibleActions[] = 'move'; } if (!empty($boards_can['remove_any']) || !empty($boards_can['remove_own'])) { $possibleActions[] = 'remove'; } if (!empty($boards_can['lock_any']) || !empty($boards_can['lock_own'])) { $possibleActions[] = 'lock'; } if (!empty($boards_can['merge_any'])) { $possibleActions[] = 'merge'; } if (!empty($boards_can['approve_posts'])) { $possibleActions[] = 'approve'; } // Two methods: $_REQUEST['actions'] (id_topic => action), and $_REQUEST['topics'] and $_REQUEST['qaction']. // (if action is 'move', $_REQUEST['move_to'] or $_REQUEST['move_tos'][$topic] is used.) if (!empty($_REQUEST['topics'])) { // If the action isn't valid, just quit now. if (empty($_REQUEST['qaction']) || !in_array($_REQUEST['qaction'], $possibleActions)) { redirectexit($redirect_url); } // Merge requires all topics as one parameter and can be done at once. if ($_REQUEST['qaction'] == 'merge') { // Merge requires at least two topics. if (empty($_REQUEST['topics']) || count($_REQUEST['topics']) < 2) { redirectexit($redirect_url); } require_once $sourcedir . '/SplitTopics.php'; return MergeExecute($_REQUEST['topics']); } // Just convert to the other method, to make it easier. foreach ($_REQUEST['topics'] as $topic) { $_REQUEST['actions'][(int) $topic] = $_REQUEST['qaction']; } } // Weird... how'd you get here? if (empty($_REQUEST['actions'])) { redirectexit($redirect_url); } // Validate each action. $temp = array(); foreach ($_REQUEST['actions'] as $topic => $action) { if (in_array($action, $possibleActions)) { $temp[(int) $topic] = $action; } } $_REQUEST['actions'] = $temp; if (!empty($_REQUEST['actions'])) { // Find all topics... $request = $smcFunc['db_query']('', ' SELECT id_topic, id_member_started, id_board, locked, approved, unapproved_posts FROM {db_prefix}topics WHERE id_topic IN ({array_int:action_topic_ids}) LIMIT ' . count($_REQUEST['actions']), array('action_topic_ids' => array_keys($_REQUEST['actions']))); while ($row = $smcFunc['db_fetch_assoc']($request)) { if (!empty($board)) { if ($row['id_board'] != $board || $modSettings['postmod_active'] && !$row['approved'] && !allowedTo('approve_posts')) { unset($_REQUEST['actions'][$row['id_topic']]); } } else { // Don't allow them to act on unapproved posts they can't see... if ($modSettings['postmod_active'] && !$row['approved'] && !in_array(0, $boards_can['approve_posts']) && !in_array($row['id_board'], $boards_can['approve_posts'])) { unset($_REQUEST['actions'][$row['id_topic']]); } elseif ($_REQUEST['actions'][$row['id_topic']] == 'sticky' && !in_array(0, $boards_can['make_sticky']) && !in_array($row['id_board'], $boards_can['make_sticky'])) { unset($_REQUEST['actions'][$row['id_topic']]); } elseif ($_REQUEST['actions'][$row['id_topic']] == 'move' && !in_array(0, $boards_can['move_any']) && !in_array($row['id_board'], $boards_can['move_any']) && ($row['id_member_started'] != $user_info['id'] || !in_array(0, $boards_can['move_own']) && !in_array($row['id_board'], $boards_can['move_own']))) { unset($_REQUEST['actions'][$row['id_topic']]); } elseif ($_REQUEST['actions'][$row['id_topic']] == 'remove' && !in_array(0, $boards_can['remove_any']) && !in_array($row['id_board'], $boards_can['remove_any']) && ($row['id_member_started'] != $user_info['id'] || !in_array(0, $boards_can['remove_own']) && !in_array($row['id_board'], $boards_can['remove_own']))) { unset($_REQUEST['actions'][$row['id_topic']]); } elseif ($_REQUEST['actions'][$row['id_topic']] == 'lock' && !in_array(0, $boards_can['lock_any']) && !in_array($row['id_board'], $boards_can['lock_any']) && ($row['id_member_started'] != $user_info['id'] || $row['locked'] == 1 || !in_array(0, $boards_can['lock_own']) && !in_array($row['id_board'], $boards_can['lock_own']))) { unset($_REQUEST['actions'][$row['id_topic']]); } elseif ($_REQUEST['actions'][$row['id_topic']] == 'approve' && (!$row['unapproved_posts'] || !in_array(0, $boards_can['approve_posts']) && !in_array($row['id_board'], $boards_can['approve_posts']))) { unset($_REQUEST['actions'][$row['id_topic']]); } } } $smcFunc['db_free_result']($request); } $stickyCache = array(); $moveCache = array(0 => array(), 1 => array()); $removeCache = array(); $lockCache = array(); $markCache = array(); $approveCache = array(); // Separate the actions. foreach ($_REQUEST['actions'] as $topic => $action) { $topic = (int) $topic; if ($action == 'markread') { $markCache[] = $topic; } elseif ($action == 'sticky') { $stickyCache[] = $topic; } elseif ($action == 'move') { require_once $sourcedir . '/MoveTopic.php'; moveTopicConcurrence(); // $moveCache[0] is the topic, $moveCache[1] is the board to move to. $moveCache[1][$topic] = (int) (isset($_REQUEST['move_tos'][$topic]) ? $_REQUEST['move_tos'][$topic] : $_REQUEST['move_to']); if (empty($moveCache[1][$topic])) { continue; } $moveCache[0][] = $topic; } elseif ($action == 'remove') { $removeCache[] = $topic; } elseif ($action == 'lock') { $lockCache[] = $topic; } elseif ($action == 'approve') { $approveCache[] = $topic; } } if (empty($board)) { $affectedBoards = array(); } else { $affectedBoards = array($board => array(0, 0)); } // Do all the stickies... if (!empty($stickyCache)) { $smcFunc['db_query']('', ' UPDATE {db_prefix}topics SET is_sticky = CASE WHEN is_sticky = {int:is_sticky} THEN 0 ELSE 1 END WHERE id_topic IN ({array_int:sticky_topic_ids})', array('sticky_topic_ids' => $stickyCache, 'is_sticky' => 1)); // Get the board IDs and Sticky status $request = $smcFunc['db_query']('', ' SELECT id_topic, id_board, is_sticky FROM {db_prefix}topics WHERE id_topic IN ({array_int:sticky_topic_ids}) LIMIT ' . count($stickyCache), array('sticky_topic_ids' => $stickyCache)); $stickyCacheBoards = array(); $stickyCacheStatus = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $stickyCacheBoards[$row['id_topic']] = $row['id_board']; $stickyCacheStatus[$row['id_topic']] = empty($row['is_sticky']); } $smcFunc['db_free_result']($request); } // Move sucka! (this is, by the by, probably the most complicated part....) if (!empty($moveCache[0])) { // I know - I just KNOW you're trying to beat the system. Too bad for you... we CHECK :P. $request = $smcFunc['db_query']('', ' SELECT t.id_topic, t.id_board, b.count_posts FROM {db_prefix}topics AS t LEFT JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board) WHERE t.id_topic IN ({array_int:move_topic_ids})' . (!empty($board) && !allowedTo('move_any') ? ' AND t.id_member_started = {int:current_member}' : '') . ' LIMIT ' . count($moveCache[0]), array('current_member' => $user_info['id'], 'move_topic_ids' => $moveCache[0])); $moveTos = array(); $moveCache2 = array(); $countPosts = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $to = $moveCache[1][$row['id_topic']]; if (empty($to)) { continue; } // Does this topic's board count the posts or not? $countPosts[$row['id_topic']] = empty($row['count_posts']); if (!isset($moveTos[$to])) { $moveTos[$to] = array(); } $moveTos[$to][] = $row['id_topic']; // For reporting... $moveCache2[] = array($row['id_topic'], $row['id_board'], $to); } $smcFunc['db_free_result']($request); $moveCache = $moveCache2; require_once $sourcedir . '/MoveTopic.php'; // Do the actual moves... foreach ($moveTos as $to => $topics) { moveTopics($topics, $to); } // Does the post counts need to be updated? if (!empty($moveTos)) { $topicRecounts = array(); $request = $smcFunc['db_query']('', ' SELECT id_board, count_posts FROM {db_prefix}boards WHERE id_board IN ({array_int:move_boards})', array('move_boards' => array_keys($moveTos))); while ($row = $smcFunc['db_fetch_assoc']($request)) { $cp = empty($row['count_posts']); // Go through all the topics that are being moved to this board. foreach ($moveTos[$row['id_board']] as $topic) { // If both boards have the same value for post counting then no adjustment needs to be made. if ($countPosts[$topic] != $cp) { // If the board being moved to does count the posts then the other one doesn't so add to their post count. $topicRecounts[$topic] = $cp ? '+' : '-'; } } } $smcFunc['db_free_result']($request); if (!empty($topicRecounts)) { $members = array(); // Get all the members who have posted in the moved topics. $request = $smcFunc['db_query']('', ' SELECT id_member, id_topic FROM {db_prefix}messages WHERE id_topic IN ({array_int:moved_topic_ids})', array('moved_topic_ids' => array_keys($topicRecounts))); while ($row = $smcFunc['db_fetch_assoc']($request)) { if (!isset($members[$row['id_member']])) { $members[$row['id_member']] = 0; } if ($topicRecounts[$row['id_topic']] === '+') { $members[$row['id_member']] += 1; } else { $members[$row['id_member']] -= 1; } } $smcFunc['db_free_result']($request); // And now update them member's post counts foreach ($members as $id_member => $post_adj) { updateMemberData($id_member, array('posts' => 'posts + ' . $post_adj)); } } } } // Now delete the topics... if (!empty($removeCache)) { // They can only delete their own topics. (we wouldn't be here if they couldn't do that..) $result = $smcFunc['db_query']('', ' SELECT id_topic, id_board FROM {db_prefix}topics WHERE id_topic IN ({array_int:removed_topic_ids})' . (!empty($board) && !allowedTo('remove_any') ? ' AND id_member_started = {int:current_member}' : '') . ' LIMIT ' . count($removeCache), array('current_member' => $user_info['id'], 'removed_topic_ids' => $removeCache)); $removeCache = array(); $removeCacheBoards = array(); while ($row = $smcFunc['db_fetch_assoc']($result)) { $removeCache[] = $row['id_topic']; $removeCacheBoards[$row['id_topic']] = $row['id_board']; } $smcFunc['db_free_result']($result); // Maybe *none* were their own topics. if (!empty($removeCache)) { // Gotta send the notifications *first*! foreach ($removeCache as $topic) { // Only log the topic ID if it's not in the recycle board. logAction('remove', array(empty($modSettings['recycle_enable']) || $modSettings['recycle_board'] != $removeCacheBoards[$topic] ? 'topic' : 'old_topic_id' => $topic, 'board' => $removeCacheBoards[$topic])); sendNotifications($topic, 'remove'); } require_once $sourcedir . '/RemoveTopic.php'; removeTopics($removeCache); } } // Approve the topics... if (!empty($approveCache)) { // We need unapproved topic ids and their authors! $request = $smcFunc['db_query']('', ' SELECT id_topic, id_member_started FROM {db_prefix}topics WHERE id_topic IN ({array_int:approve_topic_ids}) AND approved = {int:not_approved} LIMIT ' . count($approveCache), array('approve_topic_ids' => $approveCache, 'not_approved' => 0)); $approveCache = array(); $approveCacheMembers = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $approveCache[] = $row['id_topic']; $approveCacheMembers[$row['id_topic']] = $row['id_member_started']; } $smcFunc['db_free_result']($request); // Any topics to approve? if (!empty($approveCache)) { // Handle the approval part... approveTopics($approveCache); // Time for some logging! foreach ($approveCache as $topic) { logAction('approve_topic', array('topic' => $topic, 'member' => $approveCacheMembers[$topic])); } } } // And (almost) lastly, lock the topics... if (!empty($lockCache)) { $lockStatus = array(); // Gotta make sure they CAN lock/unlock these topics... if (!empty($board) && !allowedTo('lock_any')) { // Make sure they started the topic AND it isn't already locked by someone with higher priv's. $result = $smcFunc['db_query']('', ' SELECT id_topic, locked, id_board FROM {db_prefix}topics WHERE id_topic IN ({array_int:locked_topic_ids}) AND id_member_started = {int:current_member} AND locked IN (2, 0) LIMIT ' . count($lockCache), array('current_member' => $user_info['id'], 'locked_topic_ids' => $lockCache)); $lockCache = array(); $lockCacheBoards = array(); while ($row = $smcFunc['db_fetch_assoc']($result)) { $lockCache[] = $row['id_topic']; $lockCacheBoards[$row['id_topic']] = $row['id_board']; $lockStatus[$row['id_topic']] = empty($row['locked']); } $smcFunc['db_free_result']($result); } else { $result = $smcFunc['db_query']('', ' SELECT id_topic, locked, id_board FROM {db_prefix}topics WHERE id_topic IN ({array_int:locked_topic_ids}) LIMIT ' . count($lockCache), array('locked_topic_ids' => $lockCache)); $lockCacheBoards = array(); while ($row = $smcFunc['db_fetch_assoc']($result)) { $lockStatus[$row['id_topic']] = empty($row['locked']); $lockCacheBoards[$row['id_topic']] = $row['id_board']; } $smcFunc['db_free_result']($result); } // It could just be that *none* were their own topics... if (!empty($lockCache)) { // Alternate the locked value. $smcFunc['db_query']('', ' UPDATE {db_prefix}topics SET locked = CASE WHEN locked = {int:is_locked} THEN ' . (allowedTo('lock_any') ? '1' : '2') . ' ELSE 0 END WHERE id_topic IN ({array_int:locked_topic_ids})', array('locked_topic_ids' => $lockCache, 'is_locked' => 0)); } } if (!empty($markCache)) { $markArray = array(); foreach ($markCache as $topic) { $markArray[] = array($modSettings['maxMsgID'], $user_info['id'], $topic); } $smcFunc['db_insert']('replace', '{db_prefix}log_topics', array('id_msg' => 'int', 'id_member' => 'int', 'id_topic' => 'int'), $markArray, array('id_member', 'id_topic')); } foreach ($moveCache as $topic) { // Didn't actually move anything! if (!isset($topic[0])) { break; } logAction('move', array('topic' => $topic[0], 'board_from' => $topic[1], 'board_to' => $topic[2])); sendNotifications($topic[0], 'move'); } foreach ($lockCache as $topic) { logAction($lockStatus[$topic] ? 'lock' : 'unlock', array('topic' => $topic, 'board' => $lockCacheBoards[$topic])); sendNotifications($topic, $lockStatus[$topic] ? 'lock' : 'unlock'); } foreach ($stickyCache as $topic) { logAction($stickyCacheStatus[$topic] ? 'unsticky' : 'sticky', array('topic' => $topic, 'board' => $stickyCacheBoards[$topic])); sendNotifications($topic, 'sticky'); } updateStats('topic'); updateStats('message'); updateSettings(array('calendar_updated' => time())); if (!empty($affectedBoards)) { updateLastMessages(array_keys($affectedBoards)); } redirectexit($redirect_url); }
function QuickModeration() { global $db_prefix, $sourcedir, $board, $ID_MEMBER, $modSettings, $sourcedir; // Check the session = get or post. checkSession('request'); if (isset($_SESSION['topicseen_cache'])) { $_SESSION['topicseen_cache'] = array(); } // This is going to be needed to send off the notifications and for updateLastMessages(). require_once $sourcedir . '/Subs-Post.php'; // Remember the last board they moved things to. if (isset($_REQUEST['move_to'])) { $_SESSION['move_to_topic'] = $_REQUEST['move_to']; } // Only a few possible actions. $possibleActions = array('markread'); if (!empty($board)) { $boards_can = array('make_sticky' => allowedTo('make_sticky') ? array($board) : array(), 'move_any' => allowedTo('move_any') ? array($board) : array(), 'move_own' => allowedTo('move_own') ? array($board) : array(), 'remove_any' => allowedTo('remove_any') ? array($board) : array(), 'remove_own' => allowedTo('remove_own') ? array($board) : array(), 'lock_any' => allowedTo('lock_any') ? array($board) : array(), 'lock_own' => allowedTo('lock_own') ? array($board) : array(), 'merge_any' => allowedTo('merge_any') ? array($board) : array()); $redirect_url = 'board=' . $board . '.' . $_REQUEST['start']; } else { // !!! Ugly. There's no getting around this, is there? $boards_can = array('make_sticky' => boardsAllowedTo('make_sticky'), 'move_any' => boardsAllowedTo('move_any'), 'move_own' => boardsAllowedTo('move_own'), 'remove_any' => boardsAllowedTo('remove_any'), 'remove_own' => boardsAllowedTo('remove_own'), 'lock_any' => boardsAllowedTo('lock_any'), 'lock_own' => boardsAllowedTo('lock_own'), 'merge_any' => boardsAllowedTo('merge_any')); $redirect_url = isset($_POST['redirect_url']) ? $_POST['redirect_url'] : (isset($_SESSION['old_url']) ? $_SESSION['old_url'] : ''); } if (!empty($boards_can['make_sticky']) && !empty($modSettings['enableStickyTopics'])) { $possibleActions[] = 'sticky'; } if (!empty($boards_can['move_any']) || !empty($boards_can['move_own'])) { $possibleActions[] = 'move'; } if (!empty($boards_can['remove_any']) || !empty($boards_can['remove_own'])) { $possibleActions[] = 'remove'; } if (!empty($boards_can['lock_any']) || !empty($boards_can['lock_own'])) { $possibleActions[] = 'lock'; } if (!empty($boards_can['merge_any'])) { $possibleActions[] = 'merge'; } // Two methods: $_REQUEST['actions'] (ID_TOPIC => action), and $_REQUEST['topics'] and $_REQUEST['qaction']. // (if action is 'move', $_REQUEST['move_to'] or $_REQUEST['move_tos'][$topic] is used.) if (!empty($_REQUEST['topics'])) { // If the action isn't valid, just quit now. if (empty($_REQUEST['qaction']) || !in_array($_REQUEST['qaction'], $possibleActions)) { redirectexit($redirect_url); } // Merge requires all topics as one parameter and can be done at once. if ($_REQUEST['qaction'] == 'merge') { // Merge requires at least two topics. if (empty($_REQUEST['topics']) || count($_REQUEST['topics']) < 2) { redirectexit($redirect_url); } require_once $sourcedir . '/SplitTopics.php'; return MergeExecute($_REQUEST['topics']); } // Just convert to the other method, to make it easier. foreach ($_REQUEST['topics'] as $topic) { $_REQUEST['actions'][(int) $topic] = $_REQUEST['qaction']; } } // Weird... how'd you get here? if (empty($_REQUEST['actions'])) { redirectexit($redirect_url); } // Validate each action. $temp = array(); foreach ($_REQUEST['actions'] as $topic => $action) { if (in_array($action, $possibleActions)) { $temp[(int) $topic] = $action; } } $_REQUEST['actions'] = $temp; if (!empty($_REQUEST['actions'])) { // Find all topics that *aren't* on this board. $request = db_query("\n\t\t\tSELECT ID_TOPIC, ID_MEMBER_STARTED, ID_BOARD, locked\n\t\t\tFROM {$db_prefix}topics\n\t\t\tWHERE ID_TOPIC IN (" . implode(', ', array_keys($_REQUEST['actions'])) . ")" . (!empty($board) ? "\n\t\t\t\tAND ID_BOARD != {$board}" : '') . "\n\t\t\tLIMIT " . count($_REQUEST['actions']), __FILE__, __LINE__); while ($row = mysql_fetch_assoc($request)) { if (!empty($board)) { unset($_REQUEST['actions'][$row['ID_TOPIC']]); } else { // Goodness, this is fun. We need to validate the action. if ($_REQUEST['actions'][$row['ID_TOPIC']] == 'sticky' && !in_array(0, $boards_can['make_sticky']) && !in_array($row['ID_BOARD'], $boards_can['make_sticky'])) { unset($_REQUEST['actions'][$row['ID_TOPIC']]); } elseif ($_REQUEST['actions'][$row['ID_TOPIC']] == 'move' && !in_array(0, $boards_can['move_any']) && !in_array($row['ID_BOARD'], $boards_can['move_any']) && ($row['ID_MEMBER_STARTED'] != $ID_MEMBER || !in_array(0, $boards_can['move_own']) && !in_array($row['ID_BOARD'], $boards_can['move_own']))) { unset($_REQUEST['actions'][$row['ID_TOPIC']]); } elseif ($_REQUEST['actions'][$row['ID_TOPIC']] == 'remove' && !in_array(0, $boards_can['remove_any']) && !in_array($row['ID_BOARD'], $boards_can['remove_any']) && ($row['ID_MEMBER_STARTED'] != $ID_MEMBER || !in_array(0, $boards_can['remove_own']) && !in_array($row['ID_BOARD'], $boards_can['remove_own']))) { unset($_REQUEST['actions'][$row['ID_TOPIC']]); } elseif ($_REQUEST['actions'][$row['ID_TOPIC']] == 'lock' && !in_array(0, $boards_can['lock_any']) && !in_array($row['ID_BOARD'], $boards_can['lock_any']) && ($row['ID_MEMBER_STARTED'] != $ID_MEMBER || $locked == 1 || !in_array(0, $boards_can['lock_own']) && !in_array($row['ID_BOARD'], $boards_can['lock_own']))) { unset($_REQUEST['actions'][$row['ID_TOPIC']]); } } } mysql_free_result($request); } $stickyCache = array(); $moveCache = array(0 => array(), 1 => array()); $removeCache = array(); $lockCache = array(); $markCache = array(); // Separate the actions. foreach ($_REQUEST['actions'] as $topic => $action) { $topic = (int) $topic; if ($action == 'markread') { $markCache[] = $topic; } elseif ($action == 'sticky') { $stickyCache[] = $topic; } elseif ($action == 'move') { // $moveCache[0] is the topic, $moveCache[1] is the board to move to. $moveCache[1][$topic] = (int) (isset($_REQUEST['move_tos'][$topic]) ? $_REQUEST['move_tos'][$topic] : $_REQUEST['move_to']); if (empty($moveCache[1][$topic])) { continue; } $moveCache[0][] = $topic; } elseif ($action == 'remove') { $removeCache[] = $topic; } elseif ($action == 'lock') { $lockCache[] = $topic; } } if (empty($board)) { $affectedBoards = array(); } else { $affectedBoards = array($board => array(0, 0)); } // Do all the stickies... if (!empty($stickyCache)) { db_query("\n\t\t\tUPDATE {$db_prefix}topics\n\t\t\tSET isSticky = IF(isSticky = 1, 0, 1)\n\t\t\tWHERE ID_TOPIC IN (" . implode(', ', $stickyCache) . ")\n\t\t\tLIMIT " . count($stickyCache), __FILE__, __LINE__); } // Move sucka! (this is, by the by, probably the most complicated part....) if (!empty($moveCache[0])) { // I know - I just KNOW you're trying to beat the system. Too bad for you... we CHECK :P. $request = db_query("\n\t\t\tSELECT numReplies, ID_TOPIC, ID_BOARD\n\t\t\tFROM {$db_prefix}topics\n\t\t\tWHERE ID_TOPIC IN (" . implode(', ', $moveCache[0]) . ")" . (!empty($board) && !allowedTo('move_any') ? "\n\t\t\t\tAND ID_MEMBER_STARTED = {$ID_MEMBER}" : '') . "\n\t\t\tLIMIT " . count($moveCache[0]), __FILE__, __LINE__); $moveCache2 = array(); while ($row = mysql_fetch_assoc($request)) { $to = $moveCache[1][$row['ID_TOPIC']]; $row['numReplies']++; if (empty($to)) { continue; } if (!isset($affectedBoards[$to])) { $affectedBoards[$to] = array(0, 0); } if (!isset($affectedBoards[$row['ID_BOARD']])) { $affectedBoards[$row['ID_BOARD']] = array(0, 0); } $affectedBoards[$row['ID_BOARD']][0]--; $affectedBoards[$row['ID_BOARD']][1] -= $row['numReplies']; $affectedBoards[$to][0]++; $affectedBoards[$to][1] += $row['numReplies']; // Move the actual topic. db_query("\n\t\t\t\tUPDATE {$db_prefix}topics\n\t\t\t\tSET ID_BOARD = {$to}\n\t\t\t\tWHERE ID_TOPIC = {$row['ID_TOPIC']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__); db_query("\n\t\t\t\tUPDATE {$db_prefix}messages\n\t\t\t\tSET ID_BOARD = {$to}\n\t\t\t\tWHERE ID_TOPIC = {$row['ID_TOPIC']}", __FILE__, __LINE__); db_query("\n\t\t\t\tUPDATE {$db_prefix}calendar\n\t\t\t\tSET ID_BOARD = {$to}\n\t\t\t\tWHERE ID_TOPIC = {$row['ID_TOPIC']}", __FILE__, __LINE__); $moveCache2[] = array($row['ID_TOPIC'], $row['ID_BOARD'], $to); } mysql_free_result($request); $moveCache = $moveCache2; foreach ($affectedBoards as $ID_BOARD => $topicsPosts) { db_query("\n\t\t\t\tUPDATE {$db_prefix}boards\n\t\t\t\tSET numPosts = numPosts + {$topicsPosts['1']}, numTopics = numTopics + {$topicsPosts['0']}\n\t\t\t\tWHERE ID_BOARD = {$ID_BOARD}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__); } } // Now delete the topics... if (!empty($removeCache)) { // They can only delete their own topics. (we wouldn't be here if they couldn't do that..) if (!empty($board) && !allowedTo('remove_any')) { $result = db_query("\n\t\t\t\tSELECT ID_TOPIC\n\t\t\t\tFROM {$db_prefix}topics\n\t\t\t\tWHERE ID_TOPIC IN (" . implode(', ', $removeCache) . ")\n\t\t\t\t\tAND ID_MEMBER_STARTED = {$ID_MEMBER}\n\t\t\t\tLIMIT " . count($removeCache), __FILE__, __LINE__); $removeCache = array(); while ($row = mysql_fetch_assoc($result)) { $removeCache[] = $row['ID_TOPIC']; } mysql_free_result($result); } // Maybe *none* were their own topics. if (!empty($removeCache)) { // Gotta send the notifications *first*! foreach ($removeCache as $topic) { logAction('remove', array('topic' => $topic)); sendNotifications($topic, 'remove'); } require_once $sourcedir . '/RemoveTopic.php'; removeTopics($removeCache); } } // And lastly, lock the topics... if (!empty($lockCache)) { $lockStatus = array(); // Gotta make sure they CAN lock/unlock these topics... if (!empty($board) && !allowedTo('lock_any')) { // Make sure they started the topic AND it isn't already locked by someone with higher priv's. $result = db_query("\n\t\t\t\tSELECT ID_TOPIC, locked\n\t\t\t\tFROM {$db_prefix}topics\n\t\t\t\tWHERE ID_TOPIC IN (" . implode(', ', $lockCache) . ")\n\t\t\t\t\tAND ID_MEMBER_STARTED = {$ID_MEMBER}\n\t\t\t\t\tAND locked IN (2, 0)\n\t\t\t\tLIMIT " . count($lockCache), __FILE__, __LINE__); $lockCache = array(); while ($row = mysql_fetch_assoc($result)) { $lockCache[] = $row['ID_TOPIC']; $lockStatus[$row['ID_TOPIC']] = empty($row['locked']); } mysql_free_result($result); } else { $result = db_query("\n\t\t\t\tSELECT ID_TOPIC, locked\n\t\t\t\tFROM {$db_prefix}topics\n\t\t\t\tWHERE ID_TOPIC IN (" . implode(', ', $lockCache) . ")\n\t\t\t\tLIMIT " . count($lockCache), __FILE__, __LINE__); while ($row = mysql_fetch_assoc($result)) { $lockStatus[$row['ID_TOPIC']] = empty($row['locked']); } mysql_free_result($result); } // It could just be that *none* were their own topics... if (!empty($lockCache)) { // Alternate the locked value. db_query("\n\t\t\t\tUPDATE {$db_prefix}topics\n\t\t\t\tSET locked = IF(locked = 0, " . (allowedTo('lock_any') ? '1' : '2') . ", 0)\n\t\t\t\tWHERE ID_TOPIC IN (" . implode(', ', $lockCache) . ")\n\t\t\t\tLIMIT " . count($lockCache), __FILE__, __LINE__); } } if (!empty($markCache)) { $setString = ''; foreach ($markCache as $topic) { $setString .= "\n\t\t\t\t({$modSettings['maxMsgID']}, {$ID_MEMBER}, {$topic}),"; } db_query("\n\t\t\tREPLACE INTO {$db_prefix}log_topics\n\t\t\t\t(ID_MSG, ID_MEMBER, ID_TOPIC)\n\t\t\tVALUES" . substr($setString, 0, -1), __FILE__, __LINE__); } foreach ($moveCache as $topic) { // Didn't actually move anything! if (!isset($topic[0])) { break; } logAction('move', array('topic' => $topic[0], 'board_from' => $topic[1], 'board_to' => $topic[2])); sendNotifications($topic[0], 'move'); } foreach ($lockCache as $topic) { logAction('lock', array('topic' => $topic)); sendNotifications($topic, $lockStatus ? 'lock' : 'unlock'); } foreach ($stickyCache as $topic) { logAction('sticky', array('topic' => $topic)); sendNotifications($topic, 'sticky'); } updateStats('topic'); updateStats('message'); updateStats('calendar'); if (!empty($affectedBoards)) { updateLastMessages(array_keys($affectedBoards)); } redirectexit($redirect_url); }