Chris@76: $topic, Chris@76: ) Chris@76: ); Chris@76: list ($starter, $subject, $approved) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if ($starter == $user_info['id'] && !allowedTo('remove_any')) Chris@76: isAllowedTo('remove_own'); Chris@76: else Chris@76: isAllowedTo('remove_any'); Chris@76: Chris@76: // Can they see the topic? Chris@76: if ($modSettings['postmod_active'] && !$approved && $starter != $user_info['id']) Chris@76: isAllowedTo('approve_posts'); Chris@76: Chris@76: // Notify people that this topic has been removed. Chris@76: sendNotifications($topic, 'remove'); Chris@76: Chris@76: removeTopics($topic); Chris@76: Chris@76: // Note, only log topic ID in native form if it's not gone forever. Chris@76: if (allowedTo('remove_any') || (allowedTo('remove_own') && $starter == $user_info['id'])) Chris@76: logAction('remove', array((empty($modSettings['recycle_enable']) || $modSettings['recycle_board'] != $board ? 'topic' : 'old_topic_id') => $topic, 'subject' => $subject, 'member' => $starter, 'board' => $board)); Chris@76: Chris@76: redirectexit('board=' . $board . '.0'); Chris@76: } Chris@76: Chris@76: // Remove just a single post. Chris@76: function DeleteMessage() Chris@76: { Chris@76: global $user_info, $topic, $board, $modSettings, $smcFunc; Chris@76: Chris@76: checkSession('get'); Chris@76: Chris@76: $_REQUEST['msg'] = (int) $_REQUEST['msg']; Chris@76: Chris@76: // Is $topic set? Chris@76: if (empty($topic) && isset($_REQUEST['topic'])) Chris@76: $topic = (int) $_REQUEST['topic']; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT t.id_member_started, m.id_member, m.subject, m.poster_time, m.approved Chris@76: FROM {db_prefix}topics AS t Chris@76: INNER JOIN {db_prefix}messages AS m ON (m.id_msg = {int:id_msg} AND m.id_topic = {int:current_topic}) Chris@76: WHERE t.id_topic = {int:current_topic} Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'current_topic' => $topic, Chris@76: 'id_msg' => $_REQUEST['msg'], Chris@76: ) Chris@76: ); Chris@76: list ($starter, $poster, $subject, $post_time, $approved) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Verify they can see this! Chris@76: if ($modSettings['postmod_active'] && !$approved && !empty($poster) && $poster != $user_info['id']) Chris@76: isAllowedTo('approve_posts'); Chris@76: Chris@76: if ($poster == $user_info['id']) Chris@76: { Chris@76: if (!allowedTo('delete_own')) Chris@76: { Chris@76: if ($starter == $user_info['id'] && !allowedTo('delete_any')) Chris@76: isAllowedTo('delete_replies'); Chris@76: elseif (!allowedTo('delete_any')) Chris@76: isAllowedTo('delete_own'); Chris@76: } Chris@76: elseif (!allowedTo('delete_any') && ($starter != $user_info['id'] || !allowedTo('delete_replies')) && !empty($modSettings['edit_disable_time']) && $post_time + $modSettings['edit_disable_time'] * 60 < time()) Chris@76: fatal_lang_error('modify_post_time_passed', false); Chris@76: } Chris@76: elseif ($starter == $user_info['id'] && !allowedTo('delete_any')) Chris@76: isAllowedTo('delete_replies'); Chris@76: else Chris@76: isAllowedTo('delete_any'); Chris@76: Chris@76: // If the full topic was removed go back to the board. Chris@76: $full_topic = removeMessage($_REQUEST['msg']); Chris@76: Chris@76: if (allowedTo('delete_any') && (!allowedTo('delete_own') || $poster != $user_info['id'])) Chris@76: logAction('delete', array('topic' => $topic, 'subject' => $subject, 'member' => $poster, 'board' => $board)); Chris@76: Chris@76: // We want to redirect back to recent action. Chris@76: if (isset($_REQUEST['recent'])) Chris@76: redirectexit('action=recent'); Chris@76: elseif (isset($_REQUEST['profile'], $_REQUEST['start'], $_REQUEST['u'])) Chris@76: redirectexit('action=profile;u=' . $_REQUEST['u'] . ';area=showposts;start=' . $_REQUEST['start']); Chris@76: elseif ($full_topic) Chris@76: redirectexit('board=' . $board . '.0'); Chris@76: else Chris@76: redirectexit('topic=' . $topic . '.' . $_REQUEST['start']); Chris@76: } Chris@76: Chris@76: // So long as you are sure... all old posts will be gone. Chris@76: function RemoveOldTopics2() Chris@76: { Chris@76: global $modSettings, $smcFunc; Chris@76: Chris@76: isAllowedTo('admin_forum'); Chris@76: checkSession('post', 'admin'); Chris@76: Chris@76: // No boards at all? Forget it then :/. Chris@76: if (empty($_POST['boards'])) Chris@76: redirectexit('action=admin;area=maintain;sa=topics'); Chris@76: Chris@76: // This should exist, but we can make sure. Chris@76: $_POST['delete_type'] = isset($_POST['delete_type']) ? $_POST['delete_type'] : 'nothing'; Chris@76: Chris@76: // Custom conditions. Chris@76: $condition = ''; Chris@76: $condition_params = array( Chris@76: 'boards' => array_keys($_POST['boards']), Chris@76: 'poster_time' => time() - 3600 * 24 * $_POST['maxdays'], Chris@76: ); Chris@76: Chris@76: // Just moved notice topics? Chris@76: if ($_POST['delete_type'] == 'moved') Chris@76: { Chris@76: $condition .= ' Chris@76: AND m.icon = {string:icon} Chris@76: AND t.locked = {int:locked}'; Chris@76: $condition_params['icon'] = 'moved'; Chris@76: $condition_params['locked'] = 1; Chris@76: } Chris@76: // Otherwise, maybe locked topics only? Chris@76: elseif ($_POST['delete_type'] == 'locked') Chris@76: { Chris@76: $condition .= ' Chris@76: AND t.locked = {int:locked}'; Chris@76: $condition_params['locked'] = 1; Chris@76: } Chris@76: Chris@76: // Exclude stickies? Chris@76: if (isset($_POST['delete_old_not_sticky'])) Chris@76: { Chris@76: $condition .= ' Chris@76: AND t.is_sticky = {int:is_sticky}'; Chris@76: $condition_params['is_sticky'] = 0; Chris@76: } Chris@76: Chris@76: // All we're gonna do here is grab the id_topic's and send them to removeTopics(). Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT t.id_topic Chris@76: FROM {db_prefix}topics AS t Chris@76: INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_last_msg) Chris@76: WHERE Chris@76: m.poster_time < {int:poster_time}' . $condition . ' Chris@76: AND t.id_board IN ({array_int:boards})', Chris@76: $condition_params Chris@76: ); Chris@76: $topics = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $topics[] = $row['id_topic']; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: removeTopics($topics, false, true); Chris@76: Chris@76: // Log an action into the moderation log. Chris@76: logAction('pruned', array('days' => $_POST['maxdays'])); Chris@76: Chris@76: redirectexit('action=admin;area=maintain;sa=topics;done=purgeold'); Chris@76: } Chris@76: Chris@76: // Removes the passed id_topic's. (permissions are NOT checked here!) Chris@76: function removeTopics($topics, $decreasePostCount = true, $ignoreRecycling = false) Chris@76: { Chris@76: global $sourcedir, $modSettings, $smcFunc; Chris@76: Chris@76: // Nothing to do? Chris@76: if (empty($topics)) Chris@76: return; Chris@76: // Only a single topic. Chris@76: elseif (is_numeric($topics)) Chris@76: $topics = array($topics); Chris@76: Chris@76: // Decrease the post counts. Chris@76: if ($decreasePostCount) Chris@76: { Chris@76: $requestMembers = $smcFunc['db_query']('', ' Chris@76: SELECT m.id_member, COUNT(*) AS posts Chris@76: FROM {db_prefix}messages AS m Chris@76: INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) Chris@76: WHERE m.id_topic IN ({array_int:topics}) Chris@76: AND m.icon != {string:recycled} Chris@76: AND b.count_posts = {int:do_count_posts} Chris@76: AND m.approved = {int:is_approved} Chris@76: GROUP BY m.id_member', Chris@76: array( Chris@76: 'do_count_posts' => 0, Chris@76: 'recycled' => 'recycled', Chris@76: 'topics' => $topics, Chris@76: 'is_approved' => 1, Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($requestMembers) > 0) Chris@76: { Chris@76: while ($rowMembers = $smcFunc['db_fetch_assoc']($requestMembers)) Chris@76: updateMemberData($rowMembers['id_member'], array('posts' => 'posts - ' . $rowMembers['posts'])); Chris@76: } Chris@76: $smcFunc['db_free_result']($requestMembers); Chris@76: } Chris@76: Chris@76: // Recycle topics that aren't in the recycle board... Chris@76: if (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 && !$ignoreRecycling) Chris@76: { Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_topic, id_board, unapproved_posts, approved Chris@76: FROM {db_prefix}topics Chris@76: WHERE id_topic IN ({array_int:topics}) Chris@76: AND id_board != {int:recycle_board} Chris@76: LIMIT ' . count($topics), Chris@76: array( Chris@76: 'recycle_board' => $modSettings['recycle_board'], Chris@76: 'topics' => $topics, Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) > 0) Chris@76: { Chris@76: // Get topics that will be recycled. Chris@76: $recycleTopics = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: if (function_exists('apache_reset_timeout')) Chris@76: @apache_reset_timeout(); Chris@76: Chris@76: $recycleTopics[] = $row['id_topic']; Chris@76: Chris@76: // Set the id_previous_board for this topic - and make it not sticky. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}topics Chris@76: SET id_previous_board = {int:id_previous_board}, is_sticky = {int:not_sticky} Chris@76: WHERE id_topic = {int:id_topic}', Chris@76: array( Chris@76: 'id_previous_board' => $row['id_board'], Chris@76: 'id_topic' => $row['id_topic'], Chris@76: 'not_sticky' => 0, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Mark recycled topics as recycled. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}messages Chris@76: SET icon = {string:recycled} Chris@76: WHERE id_topic IN ({array_int:recycle_topics})', Chris@76: array( Chris@76: 'recycle_topics' => $recycleTopics, Chris@76: 'recycled' => 'recycled', Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Move the topics to the recycle board. Chris@76: require_once($sourcedir . '/MoveTopic.php'); Chris@76: moveTopics($recycleTopics, $modSettings['recycle_board']); Chris@76: Chris@76: // Close reports that are being recycled. Chris@76: require_once($sourcedir . '/ModerationCenter.php'); Chris@76: Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}log_reported Chris@76: SET closed = {int:is_closed} Chris@76: WHERE id_topic IN ({array_int:recycle_topics})', Chris@76: array( Chris@76: 'recycle_topics' => $recycleTopics, Chris@76: 'is_closed' => 1, Chris@76: ) Chris@76: ); Chris@76: Chris@76: updateSettings(array('last_mod_report_action' => time())); Chris@76: recountOpenReports(); Chris@76: Chris@76: // Topics that were recycled don't need to be deleted, so subtract them. Chris@76: $topics = array_diff($topics, $recycleTopics); Chris@76: } Chris@76: else Chris@76: $smcFunc['db_free_result']($request); Chris@76: } Chris@76: Chris@76: // Still topics left to delete? Chris@76: if (empty($topics)) Chris@76: return; Chris@76: Chris@76: $adjustBoards = array(); Chris@76: Chris@76: // Find out how many posts we are deleting. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_board, approved, COUNT(*) AS num_topics, SUM(unapproved_posts) AS unapproved_posts, Chris@76: SUM(num_replies) AS num_replies Chris@76: FROM {db_prefix}topics Chris@76: WHERE id_topic IN ({array_int:topics}) Chris@76: GROUP BY id_board, approved', Chris@76: array( Chris@76: 'topics' => $topics, Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: if (!isset($adjustBoards[$row['id_board']]['num_posts'])) Chris@76: { Chris@76: $adjustBoards[$row['id_board']] = array( Chris@76: 'num_posts' => 0, Chris@76: 'num_topics' => 0, Chris@76: 'unapproved_posts' => 0, Chris@76: 'unapproved_topics' => 0, Chris@76: 'id_board' => $row['id_board'] Chris@76: ); Chris@76: } Chris@76: // Posts = (num_replies + 1) for each approved topic. Chris@76: $adjustBoards[$row['id_board']]['num_posts'] += $row['num_replies'] + ($row['approved'] ? $row['num_topics'] : 0); Chris@76: $adjustBoards[$row['id_board']]['unapproved_posts'] += $row['unapproved_posts']; Chris@76: Chris@76: // Add the topics to the right type. Chris@76: if ($row['approved']) Chris@76: $adjustBoards[$row['id_board']]['num_topics'] += $row['num_topics']; Chris@76: else Chris@76: $adjustBoards[$row['id_board']]['unapproved_topics'] += $row['num_topics']; Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Decrease the posts/topics... Chris@76: foreach ($adjustBoards as $stats) Chris@76: { Chris@76: if (function_exists('apache_reset_timeout')) Chris@76: @apache_reset_timeout(); Chris@76: Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}boards Chris@76: SET Chris@76: num_posts = CASE WHEN {int:num_posts} > num_posts THEN 0 ELSE num_posts - {int:num_posts} END, Chris@76: num_topics = CASE WHEN {int:num_topics} > num_topics THEN 0 ELSE num_topics - {int:num_topics} END, Chris@76: unapproved_posts = CASE WHEN {int:unapproved_posts} > unapproved_posts THEN 0 ELSE unapproved_posts - {int:unapproved_posts} END, Chris@76: unapproved_topics = CASE WHEN {int:unapproved_topics} > unapproved_topics THEN 0 ELSE unapproved_topics - {int:unapproved_topics} END Chris@76: WHERE id_board = {int:id_board}', Chris@76: array( Chris@76: 'id_board' => $stats['id_board'], Chris@76: 'num_posts' => $stats['num_posts'], Chris@76: 'num_topics' => $stats['num_topics'], Chris@76: 'unapproved_posts' => $stats['unapproved_posts'], Chris@76: 'unapproved_topics' => $stats['unapproved_topics'], Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: // Remove Polls. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_poll Chris@76: FROM {db_prefix}topics Chris@76: WHERE id_topic IN ({array_int:topics}) Chris@76: AND id_poll > {int:no_poll} Chris@76: LIMIT ' . count($topics), Chris@76: array( Chris@76: 'no_poll' => 0, Chris@76: 'topics' => $topics, Chris@76: ) Chris@76: ); Chris@76: $polls = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $polls[] = $row['id_poll']; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if (!empty($polls)) Chris@76: { Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}polls Chris@76: WHERE id_poll IN ({array_int:polls})', Chris@76: array( Chris@76: 'polls' => $polls, Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}poll_choices Chris@76: WHERE id_poll IN ({array_int:polls})', Chris@76: array( Chris@76: 'polls' => $polls, Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_polls Chris@76: WHERE id_poll IN ({array_int:polls})', Chris@76: array( Chris@76: 'polls' => $polls, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: // Get rid of the attachment, if it exists. Chris@76: require_once($sourcedir . '/ManageAttachments.php'); Chris@76: $attachmentQuery = array( Chris@76: 'attachment_type' => 0, Chris@76: 'id_topic' => $topics, Chris@76: ); Chris@76: removeAttachments($attachmentQuery, 'messages'); Chris@76: Chris@76: // Delete possible search index entries. Chris@76: if (!empty($modSettings['search_custom_index_config'])) Chris@76: { Chris@76: $customIndexSettings = unserialize($modSettings['search_custom_index_config']); Chris@76: Chris@76: $words = array(); Chris@76: $messages = array(); Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_msg, body Chris@76: FROM {db_prefix}messages Chris@76: WHERE id_topic IN ({array_int:topics})', Chris@76: array( Chris@76: 'topics' => $topics, Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: if (function_exists('apache_reset_timeout')) Chris@76: @apache_reset_timeout(); Chris@76: Chris@76: $words = array_merge($words, text2words($row['body'], $customIndexSettings['bytes_per_word'], true)); Chris@76: $messages[] = $row['id_msg']; Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: $words = array_unique($words); Chris@76: Chris@76: if (!empty($words) && !empty($messages)) Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_search_words Chris@76: WHERE id_word IN ({array_int:word_list}) Chris@76: AND id_msg IN ({array_int:message_list})', Chris@76: array( Chris@76: 'word_list' => $words, Chris@76: 'message_list' => $messages, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: // Delete anything related to the topic. Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}messages Chris@76: WHERE id_topic IN ({array_int:topics})', Chris@76: array( Chris@76: 'topics' => $topics, Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}calendar Chris@76: WHERE id_topic IN ({array_int:topics})', Chris@76: array( Chris@76: 'topics' => $topics, Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_topics Chris@76: WHERE id_topic IN ({array_int:topics})', Chris@76: array( Chris@76: 'topics' => $topics, Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_notify Chris@76: WHERE id_topic IN ({array_int:topics})', Chris@76: array( Chris@76: 'topics' => $topics, Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}topics Chris@76: WHERE id_topic IN ({array_int:topics})', Chris@76: array( Chris@76: 'topics' => $topics, Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_search_subjects Chris@76: WHERE id_topic IN ({array_int:topics})', Chris@76: array( Chris@76: 'topics' => $topics, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Update the totals... Chris@76: updateStats('message'); Chris@76: updateStats('topic'); Chris@76: updateSettings(array( Chris@76: 'calendar_updated' => time(), Chris@76: )); Chris@76: Chris@76: require_once($sourcedir . '/Subs-Post.php'); Chris@76: $updates = array(); Chris@76: foreach ($adjustBoards as $stats) Chris@76: $updates[] = $stats['id_board']; Chris@76: updateLastMessages($updates); Chris@76: } Chris@76: Chris@76: // Remove a specific message (including permission checks). Chris@76: function removeMessage($message, $decreasePostCount = true) Chris@76: { Chris@76: global $board, $sourcedir, $modSettings, $user_info, $smcFunc, $context; Chris@76: Chris@76: if (empty($message) || !is_numeric($message)) Chris@76: return false; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT Chris@76: m.id_member, m.icon, m.poster_time, m.subject,' . (empty($modSettings['search_custom_index_config']) ? '' : ' m.body,') . ' Chris@76: m.approved, t.id_topic, t.id_first_msg, t.id_last_msg, t.num_replies, t.id_board, Chris@76: t.id_member_started AS id_member_poster, Chris@76: b.count_posts Chris@76: FROM {db_prefix}messages AS m Chris@76: INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) Chris@76: INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) Chris@76: WHERE m.id_msg = {int:id_msg} Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'id_msg' => $message, Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) == 0) Chris@76: return false; Chris@76: $row = $smcFunc['db_fetch_assoc']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if (empty($board) || $row['id_board'] != $board) Chris@76: { Chris@76: $delete_any = boardsAllowedTo('delete_any'); Chris@76: Chris@76: if (!in_array(0, $delete_any) && !in_array($row['id_board'], $delete_any)) Chris@76: { Chris@76: $delete_own = boardsAllowedTo('delete_own'); Chris@76: $delete_own = in_array(0, $delete_own) || in_array($row['id_board'], $delete_own); Chris@76: $delete_replies = boardsAllowedTo('delete_replies'); Chris@76: $delete_replies = in_array(0, $delete_replies) || in_array($row['id_board'], $delete_replies); Chris@76: Chris@76: if ($row['id_member'] == $user_info['id']) Chris@76: { Chris@76: if (!$delete_own) Chris@76: { Chris@76: if ($row['id_member_poster'] == $user_info['id']) Chris@76: { Chris@76: if (!$delete_replies) Chris@76: fatal_lang_error('cannot_delete_replies', 'permission'); Chris@76: } Chris@76: else Chris@76: fatal_lang_error('cannot_delete_own', 'permission'); Chris@76: } Chris@76: elseif (($row['id_member_poster'] != $user_info['id'] || !$delete_replies) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + $modSettings['edit_disable_time'] * 60 < time()) Chris@76: fatal_lang_error('modify_post_time_passed', false); Chris@76: } Chris@76: elseif ($row['id_member_poster'] == $user_info['id']) Chris@76: { Chris@76: if (!$delete_replies) Chris@76: fatal_lang_error('cannot_delete_replies', 'permission'); Chris@76: } Chris@76: else Chris@76: fatal_lang_error('cannot_delete_any', 'permission'); Chris@76: } Chris@76: Chris@76: // Can't delete an unapproved message, if you can't see it! Chris@76: if ($modSettings['postmod_active'] && !$row['approved'] && $row['id_member'] != $user_info['id'] && !(in_array(0, $delete_any) || in_array($row['id_board'], $delete_any))) Chris@76: { Chris@76: $approve_posts = boardsAllowedTo('approve_posts'); Chris@76: if (!in_array(0, $approve_posts) && !in_array($row['id_board'], $approve_posts)) Chris@76: return false; Chris@76: } Chris@76: } Chris@76: else Chris@76: { Chris@76: // Check permissions to delete this message. Chris@76: if ($row['id_member'] == $user_info['id']) Chris@76: { Chris@76: if (!allowedTo('delete_own')) Chris@76: { Chris@76: if ($row['id_member_poster'] == $user_info['id'] && !allowedTo('delete_any')) Chris@76: isAllowedTo('delete_replies'); Chris@76: elseif (!allowedTo('delete_any')) Chris@76: isAllowedTo('delete_own'); Chris@76: } Chris@76: elseif (!allowedTo('delete_any') && ($row['id_member_poster'] != $user_info['id'] || !allowedTo('delete_replies')) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + $modSettings['edit_disable_time'] * 60 < time()) Chris@76: fatal_lang_error('modify_post_time_passed', false); Chris@76: } Chris@76: elseif ($row['id_member_poster'] == $user_info['id'] && !allowedTo('delete_any')) Chris@76: isAllowedTo('delete_replies'); Chris@76: else Chris@76: isAllowedTo('delete_any'); Chris@76: Chris@76: if ($modSettings['postmod_active'] && !$row['approved'] && $row['id_member'] != $user_info['id'] && !allowedTo('delete_own')) Chris@76: isAllowedTo('approve_posts'); Chris@76: } Chris@76: Chris@76: // Close any moderation reports for this message. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}log_reported Chris@76: SET closed = {int:is_closed} Chris@76: WHERE id_msg = {int:id_msg}', Chris@76: array( Chris@76: 'is_closed' => 1, Chris@76: 'id_msg' => $message, Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_affected_rows']() != 0) Chris@76: { Chris@76: require_once($sourcedir . '/ModerationCenter.php'); Chris@76: updateSettings(array('last_mod_report_action' => time())); Chris@76: recountOpenReports(); Chris@76: } Chris@76: Chris@76: // Delete the *whole* topic, but only if the topic consists of one message. Chris@76: if ($row['id_first_msg'] == $message) Chris@76: { Chris@76: if (empty($board) || $row['id_board'] != $board) Chris@76: { Chris@76: $remove_any = boardsAllowedTo('remove_any'); Chris@76: $remove_any = in_array(0, $remove_any) || in_array($row['id_board'], $remove_any); Chris@76: if (!$remove_any) Chris@76: { Chris@76: $remove_own = boardsAllowedTo('remove_own'); Chris@76: $remove_own = in_array(0, $remove_own) || in_array($row['id_board'], $remove_own); Chris@76: } Chris@76: Chris@76: if ($row['id_member'] != $user_info['id'] && !$remove_any) Chris@76: fatal_lang_error('cannot_remove_any', 'permission'); Chris@76: elseif (!$remove_any && !$remove_own) Chris@76: fatal_lang_error('cannot_remove_own', 'permission'); Chris@76: } Chris@76: else Chris@76: { Chris@76: // Check permissions to delete a whole topic. Chris@76: if ($row['id_member'] != $user_info['id']) Chris@76: isAllowedTo('remove_any'); Chris@76: elseif (!allowedTo('remove_any')) Chris@76: isAllowedTo('remove_own'); Chris@76: } Chris@76: Chris@76: // ...if there is only one post. Chris@76: if (!empty($row['num_replies'])) Chris@76: fatal_lang_error('delFirstPost', false); Chris@76: Chris@76: removeTopics($row['id_topic']); Chris@76: return true; Chris@76: } Chris@76: Chris@76: // Deleting a recycled message can not lower anyone's post count. Chris@76: if ($row['icon'] == 'recycled') Chris@76: $decreasePostCount = false; Chris@76: Chris@76: // This is the last post, update the last post on the board. Chris@76: if ($row['id_last_msg'] == $message) Chris@76: { Chris@76: // Find the last message, set it, and decrease the post count. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_msg, id_member Chris@76: FROM {db_prefix}messages Chris@76: WHERE id_topic = {int:id_topic} Chris@76: AND id_msg != {int:id_msg} Chris@76: ORDER BY ' . ($modSettings['postmod_active'] ? 'approved DESC, ' : '') . 'id_msg DESC Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'id_topic' => $row['id_topic'], Chris@76: 'id_msg' => $message, Chris@76: ) Chris@76: ); Chris@76: $row2 = $smcFunc['db_fetch_assoc']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}topics Chris@76: SET Chris@76: id_last_msg = {int:id_last_msg}, Chris@76: id_member_updated = {int:id_member_updated}' . (!$modSettings['postmod_active'] || $row['approved'] ? ', Chris@76: num_replies = CASE WHEN num_replies = {int:no_replies} THEN 0 ELSE num_replies - 1 END' : ', Chris@76: unapproved_posts = CASE WHEN unapproved_posts = {int:no_unapproved} THEN 0 ELSE unapproved_posts - 1 END') . ' Chris@76: WHERE id_topic = {int:id_topic}', Chris@76: array( Chris@76: 'id_last_msg' => $row2['id_msg'], Chris@76: 'id_member_updated' => $row2['id_member'], Chris@76: 'no_replies' => 0, Chris@76: 'no_unapproved' => 0, Chris@76: 'id_topic' => $row['id_topic'], Chris@76: ) Chris@76: ); Chris@76: } Chris@76: // Only decrease post counts. Chris@76: else Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}topics Chris@76: SET ' . ($row['approved'] ? ' Chris@76: num_replies = CASE WHEN num_replies = {int:no_replies} THEN 0 ELSE num_replies - 1 END' : ' Chris@76: unapproved_posts = CASE WHEN unapproved_posts = {int:no_unapproved} THEN 0 ELSE unapproved_posts - 1 END') . ' Chris@76: WHERE id_topic = {int:id_topic}', Chris@76: array( Chris@76: 'no_replies' => 0, Chris@76: 'no_unapproved' => 0, Chris@76: 'id_topic' => $row['id_topic'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Default recycle to false. Chris@76: $recycle = false; Chris@76: Chris@76: // If recycle topics has been set, make a copy of this message in the recycle board. Chris@76: // Make sure we're not recycling messages that are already on the recycle board. Chris@76: if (!empty($modSettings['recycle_enable']) && $row['id_board'] != $modSettings['recycle_board'] && $row['icon'] != 'recycled') Chris@76: { Chris@76: // Check if the recycle board exists and if so get the read status. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT (IFNULL(lb.id_msg, 0) >= b.id_msg_updated) AS is_seen, id_last_msg Chris@76: FROM {db_prefix}boards AS b Chris@76: LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = b.id_board AND lb.id_member = {int:current_member}) Chris@76: WHERE b.id_board = {int:recycle_board}', Chris@76: array( Chris@76: 'current_member' => $user_info['id'], Chris@76: 'recycle_board' => $modSettings['recycle_board'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($request) == 0) Chris@76: fatal_lang_error('recycle_no_valid_board'); Chris@76: list ($isRead, $last_board_msg) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Is there an existing topic in the recycle board to group this post with? Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_topic, id_first_msg, id_last_msg Chris@76: FROM {db_prefix}topics Chris@76: WHERE id_previous_topic = {int:id_previous_topic} Chris@76: AND id_board = {int:recycle_board}', Chris@76: array( Chris@76: 'id_previous_topic' => $row['id_topic'], Chris@76: 'recycle_board' => $modSettings['recycle_board'], Chris@76: ) Chris@76: ); Chris@76: list ($id_recycle_topic, $first_topic_msg, $last_topic_msg) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Insert a new topic in the recycle board if $id_recycle_topic is empty. Chris@76: if (empty($id_recycle_topic)) Chris@76: $smcFunc['db_insert']('', Chris@76: '{db_prefix}topics', Chris@76: array( Chris@76: 'id_board' => 'int', 'id_member_started' => 'int', 'id_member_updated' => 'int', 'id_first_msg' => 'int', Chris@76: 'id_last_msg' => 'int', 'unapproved_posts' => 'int', 'approved' => 'int', 'id_previous_topic' => 'int', Chris@76: ), Chris@76: array( Chris@76: $modSettings['recycle_board'], $row['id_member'], $row['id_member'], $message, Chris@76: $message, 0, 1, $row['id_topic'], Chris@76: ), Chris@76: array('id_topic') Chris@76: ); Chris@76: Chris@76: // Capture the ID of the new topic... Chris@76: $topicID = empty($id_recycle_topic) ? $smcFunc['db_insert_id']('{db_prefix}topics', 'id_topic') : $id_recycle_topic; Chris@76: Chris@76: // If the topic creation went successful, move the message. Chris@76: if ($topicID > 0) Chris@76: { Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}messages Chris@76: SET Chris@76: id_topic = {int:id_topic}, Chris@76: id_board = {int:recycle_board}, Chris@76: icon = {string:recycled}, Chris@76: approved = {int:is_approved} Chris@76: WHERE id_msg = {int:id_msg}', Chris@76: array( Chris@76: 'id_topic' => $topicID, Chris@76: 'recycle_board' => $modSettings['recycle_board'], Chris@76: 'id_msg' => $message, Chris@76: 'recycled' => 'recycled', Chris@76: 'is_approved' => 1, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Take any reported posts with us... Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}log_reported Chris@76: SET Chris@76: id_topic = {int:id_topic}, Chris@76: id_board = {int:recycle_board} Chris@76: WHERE id_msg = {int:id_msg}', Chris@76: array( Chris@76: 'id_topic' => $topicID, Chris@76: 'recycle_board' => $modSettings['recycle_board'], Chris@76: 'id_msg' => $message, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Mark recycled topic as read. Chris@76: if (!$user_info['is_guest']) Chris@76: $smcFunc['db_insert']('replace', Chris@76: '{db_prefix}log_topics', Chris@76: array('id_topic' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), Chris@76: array($topicID, $user_info['id'], $modSettings['maxMsgID']), Chris@76: array('id_topic', 'id_member') Chris@76: ); Chris@76: Chris@76: // Mark recycle board as seen, if it was marked as seen before. Chris@76: if (!empty($isRead) && !$user_info['is_guest']) Chris@76: $smcFunc['db_insert']('replace', Chris@76: '{db_prefix}log_boards', Chris@76: array('id_board' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), Chris@76: array($modSettings['recycle_board'], $user_info['id'], $modSettings['maxMsgID']), Chris@76: array('id_board', 'id_member') Chris@76: ); Chris@76: Chris@76: // Add one topic and post to the recycle bin board. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}boards Chris@76: SET Chris@76: num_topics = num_topics + {int:num_topics_inc}, Chris@76: num_posts = num_posts + 1' . Chris@76: ($message > $last_board_msg ? ', id_last_msg = {int:id_merged_msg}' : '') . ' Chris@76: WHERE id_board = {int:recycle_board}', Chris@76: array( Chris@76: 'num_topics_inc' => empty($id_recycle_topic) ? 1 : 0, Chris@76: 'recycle_board' => $modSettings['recycle_board'], Chris@76: 'id_merged_msg' => $message, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Lets increase the num_replies, and the first/last message ID as appropriate. Chris@76: if (!empty($id_recycle_topic)) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}topics Chris@76: SET num_replies = num_replies + 1' . Chris@76: ($message > $last_topic_msg ? ', id_last_msg = {int:id_merged_msg}' : '') . Chris@76: ($message < $first_topic_msg ? ', id_first_msg = {int:id_merged_msg}' : '') . ' Chris@76: WHERE id_topic = {int:id_recycle_topic}', Chris@76: array( Chris@76: 'id_recycle_topic' => $id_recycle_topic, Chris@76: 'id_merged_msg' => $message, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Make sure this message isn't getting deleted later on. Chris@76: $recycle = true; Chris@76: Chris@76: // Make sure we update the search subject index. Chris@76: updateStats('subject', $topicID, $row['subject']); Chris@76: } Chris@76: Chris@76: // If it wasn't approved don't keep it in the queue. Chris@76: if (!$row['approved']) Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}approval_queue Chris@76: WHERE id_msg = {int:id_msg} Chris@76: AND id_attach = {int:id_attach}', Chris@76: array( Chris@76: 'id_msg' => $message, Chris@76: 'id_attach' => 0, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}boards Chris@76: SET ' . ($row['approved'] ? ' Chris@76: num_posts = CASE WHEN num_posts = {int:no_posts} THEN 0 ELSE num_posts - 1 END' : ' Chris@76: unapproved_posts = CASE WHEN unapproved_posts = {int:no_unapproved} THEN 0 ELSE unapproved_posts - 1 END') . ' Chris@76: WHERE id_board = {int:id_board}', Chris@76: array( Chris@76: 'no_posts' => 0, Chris@76: 'no_unapproved' => 0, Chris@76: 'id_board' => $row['id_board'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: // If the poster was registered and the board this message was on incremented Chris@76: // the member's posts when it was posted, decrease his or her post count. Chris@76: if (!empty($row['id_member']) && $decreasePostCount && empty($row['count_posts']) && $row['approved']) Chris@76: updateMemberData($row['id_member'], array('posts' => '-')); Chris@76: Chris@76: // Only remove posts if they're not recycled. Chris@76: if (!$recycle) Chris@76: { Chris@76: // Remove the message! Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}messages Chris@76: WHERE id_msg = {int:id_msg}', Chris@76: array( Chris@76: 'id_msg' => $message, Chris@76: ) Chris@76: ); Chris@76: Chris@76: if (!empty($modSettings['search_custom_index_config'])) Chris@76: { Chris@76: $customIndexSettings = unserialize($modSettings['search_custom_index_config']); Chris@76: $words = text2words($row['body'], $customIndexSettings['bytes_per_word'], true); Chris@76: if (!empty($words)) Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_search_words Chris@76: WHERE id_word IN ({array_int:word_list}) Chris@76: AND id_msg = {int:id_msg}', Chris@76: array( Chris@76: 'word_list' => $words, Chris@76: 'id_msg' => $message, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: // Delete attachment(s) if they exist. Chris@76: require_once($sourcedir . '/ManageAttachments.php'); Chris@76: $attachmentQuery = array( Chris@76: 'attachment_type' => 0, Chris@76: 'id_msg' => $message, Chris@76: ); Chris@76: removeAttachments($attachmentQuery); Chris@76: } Chris@76: Chris@76: // Update the pesky statistics. Chris@76: updateStats('message'); Chris@76: updateStats('topic'); Chris@76: updateSettings(array( Chris@76: 'calendar_updated' => time(), Chris@76: )); Chris@76: Chris@76: // And now to update the last message of each board we messed with. Chris@76: require_once($sourcedir . '/Subs-Post.php'); Chris@76: if ($recycle) Chris@76: updateLastMessages(array($row['id_board'], $modSettings['recycle_board'])); Chris@76: else Chris@76: updateLastMessages($row['id_board']); Chris@76: Chris@76: return false; Chris@76: } Chris@76: Chris@76: function RestoreTopic() Chris@76: { Chris@76: global $context, $smcFunc, $modSettings, $sourcedir; Chris@76: Chris@76: // Check session. Chris@76: checkSession('get'); Chris@76: Chris@76: // Is recycled board enabled? Chris@76: if (empty($modSettings['recycle_enable'])) Chris@76: fatal_lang_error('restored_disabled', 'critical'); Chris@76: Chris@76: // Can we be in here? Chris@76: isAllowedTo('move_any', $modSettings['recycle_board']); Chris@76: Chris@76: // We need this file. Chris@76: require_once($sourcedir . '/MoveTopic.php'); Chris@76: Chris@76: $unfound_messages = array(); Chris@76: $topics_to_restore = array(); Chris@76: Chris@76: // Restoring messages? Chris@76: if (!empty($_REQUEST['msgs'])) Chris@76: { Chris@76: $msgs = explode(',', $_REQUEST['msgs']); Chris@76: foreach ($msgs as $k => $msg) Chris@76: $msgs[$k] = (int) $msg; Chris@76: Chris@76: // Get the id_previous_board and id_previous_topic. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT m.id_topic, m.id_msg, m.id_board, m.subject, m.id_member, t.id_previous_board, t.id_previous_topic, Chris@76: t.id_first_msg, b.count_posts, IFNULL(pt.id_board, 0) AS possible_prev_board Chris@76: FROM {db_prefix}messages AS m Chris@76: INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) Chris@76: INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) Chris@76: LEFT JOIN {db_prefix}topics AS pt ON (pt.id_topic = t.id_previous_topic) Chris@76: WHERE m.id_msg IN ({array_int:messages})', Chris@76: array( Chris@76: 'messages' => $msgs, Chris@76: ) Chris@76: ); Chris@76: Chris@76: $actioned_messages = array(); Chris@76: $previous_topics = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: // Restoring the first post means topic. Chris@76: if ($row['id_msg'] == $row['id_first_msg'] && $row['id_previous_topic'] == $row['id_topic']) Chris@76: { Chris@76: $topics_to_restore[] = $row['id_topic']; Chris@76: continue; Chris@76: } Chris@76: // Don't know where it's going? Chris@76: if (empty($row['id_previous_topic'])) Chris@76: { Chris@76: $unfound_messages[$row['id_msg']] = $row['subject']; Chris@76: continue; Chris@76: } Chris@76: Chris@76: $previous_topics[] = $row['id_previous_topic']; Chris@76: if (empty($actioned_messages[$row['id_previous_topic']])) Chris@76: $actioned_messages[$row['id_previous_topic']] = array( Chris@76: 'msgs' => array(), Chris@76: 'count_posts' => $row['count_posts'], Chris@76: 'subject' => $row['subject'], Chris@76: 'previous_board' => $row['id_previous_board'], Chris@76: 'possible_prev_board' => $row['possible_prev_board'], Chris@76: 'current_topic' => $row['id_topic'], Chris@76: 'current_board' => $row['id_board'], Chris@76: 'members' => array(), Chris@76: ); Chris@76: Chris@76: $actioned_messages[$row['id_previous_topic']]['msgs'][$row['id_msg']] = $row['subject']; Chris@76: if ($row['id_member']) Chris@76: $actioned_messages[$row['id_previous_topic']]['members'][] = $row['id_member']; Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Check for topics we are going to fully restore. Chris@76: foreach ($actioned_messages as $topic => $data) Chris@76: if (in_array($topic, $topics_to_restore)) Chris@76: unset($actioned_messages[$topic]); Chris@76: Chris@76: // Load any previous topics to check they exist. Chris@76: if (!empty($previous_topics)) Chris@76: { Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT t.id_topic, t.id_board, m.subject Chris@76: FROM {db_prefix}topics AS t Chris@76: INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) Chris@76: WHERE t.id_topic IN ({array_int:previous_topics})', Chris@76: array( Chris@76: 'previous_topics' => $previous_topics, Chris@76: ) Chris@76: ); Chris@76: $previous_topics = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $previous_topics[$row['id_topic']] = array( Chris@76: 'board' => $row['id_board'], Chris@76: 'subject' => $row['subject'], Chris@76: ); Chris@76: $smcFunc['db_free_result']($request); Chris@76: } Chris@76: Chris@76: // Restore each topic. Chris@76: $messages = array(); Chris@76: foreach ($actioned_messages as $topic => $data) Chris@76: { Chris@76: // If we have topics we are going to restore the whole lot ignore them. Chris@76: if (in_array($topic, $topics_to_restore)) Chris@76: { Chris@76: unset($actioned_messages[$topic]); Chris@76: continue; Chris@76: } Chris@76: Chris@76: // Move the posts back then! Chris@76: if (isset($previous_topics[$topic])) Chris@76: { Chris@76: mergePosts(array_keys($data['msgs']), $data['current_topic'], $topic); Chris@76: // Log em. Chris@76: logAction('restore_posts', array('topic' => $topic, 'subject' => $previous_topics[$topic]['subject'], 'board' => empty($data['previous_board']) ? $data['possible_prev_board'] : $data['previous_board'])); Chris@76: $messages = array_merge(array_keys($data['msgs']), $messages); Chris@76: } Chris@76: else Chris@76: { Chris@76: foreach ($data['msgs'] as $msg) Chris@76: $unfound_messages[$msg['id']] = $msg['subject']; Chris@76: } Chris@76: } Chris@76: Chris@76: // Put the icons back. Chris@76: if (!empty($messages)) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}messages Chris@76: SET icon = {string:icon} Chris@76: WHERE id_msg IN ({array_int:messages})', Chris@76: array( Chris@76: 'icon' => 'xx', Chris@76: 'messages' => $messages, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: // Now any topics? Chris@76: if (!empty($_REQUEST['topics'])) Chris@76: { Chris@76: $topics = explode(',', $_REQUEST['topics']); Chris@76: foreach ($topics as $key => $id) Chris@76: $topics_to_restore[] = (int) $id; Chris@76: } Chris@76: Chris@76: if (!empty($topics_to_restore)) Chris@76: { Chris@76: // Lets get the data for these topics. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT t.id_topic, t.id_previous_board, t.id_board, t.id_first_msg, m.subject Chris@76: FROM {db_prefix}topics AS t Chris@76: INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) Chris@76: WHERE t.id_topic IN ({array_int:topics})', Chris@76: array( Chris@76: 'topics' => $topics_to_restore, Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: // We can only restore if the previous board is set. Chris@76: if (empty($row['id_previous_board'])) Chris@76: { Chris@76: $unfound_messages[$row['id_first_msg']] = $row['subject']; Chris@76: continue; Chris@76: } Chris@76: Chris@76: // Ok we got here so me move them from here to there. Chris@76: moveTopics($row['id_topic'], $row['id_previous_board']); Chris@76: Chris@76: // Lets remove the recycled icon. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}messages Chris@76: SET icon = {string:icon} Chris@76: WHERE id_topic = {int:id_topic}', Chris@76: array( Chris@76: 'icon' => 'xx', Chris@76: 'id_topic' => $row['id_topic'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Lets see if the board that we are returning to has post count enabled. Chris@76: $request2 = $smcFunc['db_query']('', ' Chris@76: SELECT count_posts Chris@76: FROM {db_prefix}boards Chris@76: WHERE id_board = {int:board}', Chris@76: array( Chris@76: 'board' => $row['id_previous_board'], Chris@76: ) Chris@76: ); Chris@76: list ($count_posts) = $smcFunc['db_fetch_row']($request2); Chris@76: $smcFunc['db_free_result']($request2); Chris@76: Chris@76: if (empty($count_posts)) Chris@76: { Chris@76: // Lets get the members that need their post count restored. Chris@76: $request2 = $smcFunc['db_query']('', ' Chris@76: SELECT id_member, COUNT(id_msg) AS post_count Chris@76: FROM {db_prefix}messages Chris@76: WHERE id_topic = {int:topic} Chris@76: AND approved = {int:is_approved} Chris@76: GROUP BY id_member', Chris@76: array( Chris@76: 'topic' => $row['id_topic'], Chris@76: 'is_approved' => 1, Chris@76: ) Chris@76: ); Chris@76: Chris@76: while ($member = $smcFunc['db_fetch_assoc']($request2)) Chris@76: updateMemberData($member['id_member'], array('posts' => 'posts + ' . $member['post_count'])); Chris@76: $smcFunc['db_free_result']($request2); Chris@76: } Chris@76: Chris@76: // Log it. Chris@76: logAction('restore_topic', array('topic' => $row['id_topic'], 'board' => $row['id_board'], 'board_to' => $row['id_previous_board'])); Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: } Chris@76: Chris@76: // Didn't find some things? Chris@76: if (!empty($unfound_messages)) Chris@76: fatal_lang_error('restore_not_found', false, array(implode('
', $unfound_messages))); Chris@76: Chris@76: // Just send them to the index if they get here. Chris@76: redirectexit(); Chris@76: } Chris@76: Chris@76: // Take a load of messages from one place and stick them in a topic. Chris@76: function mergePosts($msgs = array(), $from_topic, $target_topic) Chris@76: { Chris@76: global $context, $smcFunc, $modSettings, $sourcedir; Chris@76: Chris@76: //!!! This really needs to be rewritten to take a load of messages from ANY topic, it's also inefficient. Chris@76: Chris@76: // Is it an array? Chris@76: if (!is_array($msgs)) Chris@76: $msgs = array($msgs); Chris@76: Chris@76: // Lets make sure they are int. Chris@76: foreach ($msgs as $key => $msg) Chris@76: $msgs[$key] = (int) $msg; Chris@76: Chris@76: // Get the source information. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT t.id_board, t.id_first_msg, t.num_replies, t.unapproved_posts Chris@76: FROM {db_prefix}topics AS t Chris@76: INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) Chris@76: WHERE t.id_topic = {int:from_topic}', Chris@76: array( Chris@76: 'from_topic' => $from_topic, Chris@76: ) Chris@76: ); Chris@76: list ($from_board, $from_first_msg, $from_replies, $from_unapproved_posts) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Get some target topic and board stats. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT t.id_board, t.id_first_msg, t.num_replies, t.unapproved_posts, b.count_posts Chris@76: FROM {db_prefix}topics AS t Chris@76: INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) Chris@76: WHERE t.id_topic = {int:target_topic}', Chris@76: array( Chris@76: 'target_topic' => $target_topic, Chris@76: ) Chris@76: ); Chris@76: list ($target_board, $target_first_msg, $target_replies, $target_unapproved_posts, $count_posts) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Lets see if the board that we are returning to has post count enabled. Chris@76: if (empty($count_posts)) Chris@76: { Chris@76: // Lets get the members that need their post count restored. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_member Chris@76: FROM {db_prefix}messages Chris@76: WHERE id_msg IN ({array_int:messages}) Chris@76: AND approved = {int:is_approved}', Chris@76: array( Chris@76: 'messages' => $msgs, Chris@76: 'is_approved' => 1, Chris@76: ) Chris@76: ); Chris@76: Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: updateMemberData($row['id_member'], array('posts' => '+')); Chris@76: } Chris@76: Chris@76: // Time to move the messages. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}messages Chris@76: SET Chris@76: id_topic = {int:target_topic}, Chris@76: id_board = {int:target_board}, Chris@76: icon = {string:icon} Chris@76: WHERE id_msg IN({array_int:msgs})', Chris@76: array( Chris@76: 'target_topic' => $target_topic, Chris@76: 'target_board' => $target_board, Chris@76: 'icon' => $target_board == $modSettings['recycle_board'] ? 'recycled' : 'xx', Chris@76: 'msgs' => $msgs, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Fix the id_first_msg and id_last_msg for the target topic. Chris@76: $target_topic_data = array( Chris@76: 'num_replies' => 0, Chris@76: 'unapproved_posts' => 0, Chris@76: 'id_first_msg' => 9999999999, Chris@76: ); Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT MIN(id_msg) AS id_first_msg, MAX(id_msg) AS id_last_msg, COUNT(*) AS message_count, approved Chris@76: FROM {db_prefix}messages Chris@76: WHERE id_topic = {int:target_topic} Chris@76: GROUP BY id_topic, approved Chris@76: ORDER BY approved ASC Chris@76: LIMIT 2', Chris@76: array( Chris@76: 'target_topic' => $target_topic, Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: if ($row['id_first_msg'] < $target_topic_data['id_first_msg']) Chris@76: $target_topic_data['id_first_msg'] = $row['id_first_msg']; Chris@76: $target_topic_data['id_last_msg'] = $row['id_last_msg']; Chris@76: if (!$row['approved']) Chris@76: $target_topic_data['unapproved_posts'] = $row['message_count']; Chris@76: else Chris@76: $target_topic_data['num_replies'] = max(0, $row['message_count'] - 1); Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // We have a new post count for the board. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}boards Chris@76: SET Chris@76: num_posts = num_posts + {int:diff_replies}, Chris@76: unapproved_posts = unapproved_posts + {int:diff_unapproved_posts} Chris@76: WHERE id_board = {int:target_board}', Chris@76: array( Chris@76: 'diff_replies' => $target_topic_data['num_replies'] - $target_replies, // Lets keep in mind that the first message in a topic counts towards num_replies in a board. Chris@76: 'diff_unapproved_posts' => $target_topic_data['unapproved_posts'] - $target_unapproved_posts, Chris@76: 'target_board' => $target_board, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // In some cases we merged the only post in a topic so the topic data is left behind in the topic table. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_topic Chris@76: FROM {db_prefix}messages Chris@76: WHERE id_topic = {int:from_topic}', Chris@76: array( Chris@76: 'from_topic' => $from_topic, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Remove the topic if it doesn't have any messages. Chris@76: $topic_exists = true; Chris@76: if ($smcFunc['db_num_rows']($request) == 0) Chris@76: { Chris@76: removeTopics($from_topic, false, true); Chris@76: $topic_exists = false; Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Recycled topic. Chris@76: if ($topic_exists == true) Chris@76: { Chris@76: // Fix the id_first_msg and id_last_msg for the source topic. Chris@76: $source_topic_data = array( Chris@76: 'num_replies' => 0, Chris@76: 'unapproved_posts' => 0, Chris@76: 'id_first_msg' => 9999999999, Chris@76: ); Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT MIN(id_msg) AS id_first_msg, MAX(id_msg) AS id_last_msg, COUNT(*) AS message_count, approved, subject Chris@76: FROM {db_prefix}messages Chris@76: WHERE id_topic = {int:from_topic} Chris@76: GROUP BY id_topic, approved Chris@76: ORDER BY approved ASC Chris@76: LIMIT 2', Chris@76: array( Chris@76: 'from_topic' => $from_topic, Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: if ($row['id_first_msg'] < $source_topic_data['id_first_msg']) Chris@76: $source_topic_data['id_first_msg'] = $row['id_first_msg']; Chris@76: $source_topic_data['id_last_msg'] = $row['id_last_msg']; Chris@76: if (!$row['approved']) Chris@76: $source_topic_data['unapproved_posts'] = $row['message_count']; Chris@76: else Chris@76: $source_topic_data['num_replies'] = max(0, $row['message_count'] - 1); Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Update the topic details for the source topic. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}topics Chris@76: SET Chris@76: id_first_msg = {int:id_first_msg}, Chris@76: id_last_msg = {int:id_last_msg}, Chris@76: num_replies = {int:num_replies}, Chris@76: unapproved_posts = {int:unapproved_posts} Chris@76: WHERE id_topic = {int:from_topic}', Chris@76: array( Chris@76: 'id_first_msg' => $source_topic_data['id_first_msg'], Chris@76: 'id_last_msg' => $source_topic_data['id_last_msg'], Chris@76: 'num_replies' => $source_topic_data['num_replies'], Chris@76: 'unapproved_posts' => $source_topic_data['unapproved_posts'], Chris@76: 'from_topic' => $from_topic, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // We have a new post count for the source board. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}boards Chris@76: SET Chris@76: num_posts = num_posts + {int:diff_replies}, Chris@76: unapproved_posts = unapproved_posts + {int:diff_unapproved_posts} Chris@76: WHERE id_board = {int:from_board}', Chris@76: array( Chris@76: 'diff_replies' => $source_topic_data['num_replies'] - $from_replies, // Lets keep in mind that the first message in a topic counts towards num_replies in a board. Chris@76: 'diff_unapproved_posts' => $source_topic_data['unapproved_posts'] - $from_unapproved_posts, Chris@76: 'from_board' => $from_board, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: // Finally get around to updating the destination topic, now all indexes etc on the source are fixed. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}topics Chris@76: SET Chris@76: id_first_msg = {int:id_first_msg}, Chris@76: id_last_msg = {int:id_last_msg}, Chris@76: num_replies = {int:num_replies}, Chris@76: unapproved_posts = {int:unapproved_posts} Chris@76: WHERE id_topic = {int:target_topic}', Chris@76: array( Chris@76: 'id_first_msg' => $target_topic_data['id_first_msg'], Chris@76: 'id_last_msg' => $target_topic_data['id_last_msg'], Chris@76: 'num_replies' => $target_topic_data['num_replies'], Chris@76: 'unapproved_posts' => $target_topic_data['unapproved_posts'], Chris@76: 'target_topic' => $target_topic, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Need it to update some stats. Chris@76: require_once($sourcedir . '/Subs-Post.php'); Chris@76: Chris@76: // Update stats. Chris@76: updateStats('topic'); Chris@76: updateStats('message'); Chris@76: Chris@76: // Subject cache? Chris@76: $cache_updates = array(); Chris@76: if ($target_first_msg != $target_topic_data['id_first_msg']) Chris@76: $cache_updates[] = $target_topic_data['id_first_msg']; Chris@76: if (!empty($source_topic_data['id_first_msg']) && $from_first_msg != $source_topic_data['id_first_msg']) Chris@76: $cache_updates[] = $source_topic_data['id_first_msg']; Chris@76: Chris@76: if (!empty($cache_updates)) Chris@76: { Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_topic, subject Chris@76: FROM {db_prefix}messages Chris@76: WHERE id_msg IN ({array_int:first_messages})', Chris@76: array( Chris@76: 'first_messages' => $cache_updates, Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: updateStats('subject', $row['id_topic'], $row['subject']); Chris@76: $smcFunc['db_free_result']($request); Chris@76: } Chris@76: Chris@76: updateLastMessages(array($from_board, $target_board)); Chris@76: } Chris@76: Chris@76: ?>