Chris@76: $txt['maintain_title'], Chris@76: 'help' => '', Chris@76: 'description' => $txt['maintain_info'], Chris@76: 'tabs' => array(), Chris@76: ); Chris@76: Chris@76: // Start displaying errors without fixing them. Chris@76: if (isset($_GET['fixErrors'])) Chris@76: checkSession('get'); Chris@76: Chris@76: // Will want this. Chris@76: loadForumTests(); Chris@76: Chris@76: // Giant if/else. The first displays the forum errors if a variable is not set and asks Chris@76: // if you would like to continue, the other fixes the errors. Chris@76: if (!isset($_GET['fixErrors'])) Chris@76: { Chris@76: $context['error_search'] = true; Chris@76: $context['repair_errors'] = array(); Chris@76: $context['to_fix'] = findForumErrors(); Chris@76: Chris@76: if (!empty($context['to_fix'])) Chris@76: { Chris@76: $_SESSION['repairboards_to_fix'] = $context['to_fix']; Chris@76: $_SESSION['repairboards_to_fix2'] = null; Chris@76: Chris@76: if (empty($context['repair_errors'])) Chris@76: $context['repair_errors'][] = '???'; Chris@76: } Chris@76: } Chris@76: else Chris@76: { Chris@76: $context['error_search'] = false; Chris@76: $context['to_fix'] = isset($_SESSION['repairboards_to_fix']) ? $_SESSION['repairboards_to_fix'] : array(); Chris@76: Chris@76: require_once($sourcedir . '/Subs-Boards.php'); Chris@76: Chris@76: // Get the MySQL version for future reference. Chris@76: $mysql_version = $smcFunc['db_server_info']($db_connection); Chris@76: Chris@76: // Actually do the fix. Chris@76: findForumErrors(true); Chris@76: Chris@76: // Note that we've changed everything possible ;) Chris@76: updateSettings(array( Chris@76: 'settings_updated' => time(), Chris@76: )); Chris@76: updateStats('message'); Chris@76: updateStats('topic'); Chris@76: updateSettings(array( Chris@76: 'calendar_updated' => time(), Chris@76: )); Chris@76: Chris@76: if (!empty($salvageBoardID)) Chris@76: { Chris@76: $context['redirect_to_recount'] = true; Chris@76: } Chris@76: Chris@76: $_SESSION['repairboards_to_fix'] = null; Chris@76: $_SESSION['repairboards_to_fix2'] = null; Chris@76: } Chris@76: } Chris@76: Chris@76: function pauseRepairProcess($to_fix, $current_step_description, $max_substep = 0, $force = false) Chris@76: { Chris@76: global $context, $txt, $time_start, $db_temp_cache, $db_cache; Chris@76: Chris@76: // More time, I need more time! Chris@76: @set_time_limit(600); Chris@76: if (function_exists('apache_reset_timeout')) Chris@76: @apache_reset_timeout(); Chris@76: Chris@76: // Errr, wait. How much time has this taken already? Chris@76: if (!$force && time() - array_sum(explode(' ', $time_start)) < 3) Chris@76: return; Chris@76: Chris@76: // Restore the query cache if interested. Chris@76: if (!empty($db_temp_cache)) Chris@76: $db_cache = $db_temp_cache; Chris@76: Chris@76: $context['continue_get_data'] = '?action=admin;area=repairboards' . (isset($_GET['fixErrors']) ? ';fixErrors' : '') . ';step=' . $_GET['step'] . ';substep=' . $_GET['substep'] . ';' . $context['session_var'] . '=' . $context['session_id']; Chris@76: $context['page_title'] = $txt['not_done_title']; Chris@76: $context['continue_post_data'] = ''; Chris@76: $context['continue_countdown'] = '2'; Chris@76: $context['sub_template'] = 'not_done'; Chris@76: Chris@76: // Change these two if more steps are added! Chris@76: if (empty($max_substep)) Chris@76: $context['continue_percent'] = round(($_GET['step'] * 100) / $context['total_steps']); Chris@76: else Chris@76: $context['continue_percent'] = round((($_GET['step'] + ($_GET['substep'] / $max_substep)) * 100) / $context['total_steps']); Chris@76: Chris@76: // Never more than 100%! Chris@76: $context['continue_percent'] = min($context['continue_percent'], 100); Chris@76: Chris@76: // What about substeps? Chris@76: $context['substep_enabled'] = $max_substep != 0; Chris@76: $context['substep_title'] = sprintf($txt['repair_currently_' . (isset($_GET['fixErrors']) ? 'fixing' : 'checking')], (isset($txt['repair_operation_' . $current_step_description]) ? $txt['repair_operation_' . $current_step_description] : $current_step_description)); Chris@76: $context['substep_continue_percent'] = $max_substep == 0 ? 0 : round(($_GET['substep'] * 100) / $max_substep, 1); Chris@76: Chris@76: $_SESSION['repairboards_to_fix'] = $to_fix; Chris@76: $_SESSION['repairboards_to_fix2'] = $context['repair_errors']; Chris@76: Chris@76: obExit(); Chris@76: } Chris@76: Chris@76: // Load up all the tests we might want to do ;) Chris@76: function loadForumTests() Chris@76: { Chris@76: global $smcFunc, $errorTests; Chris@76: Chris@76: /* Here this array is defined like so: Chris@76: string check_query: Query to be executed when testing if errors exist. Chris@76: string check_type: Defines how it knows if a problem was found. If set to count looks for the first variable from check_query Chris@76: being > 0. Anything else it looks for some results. If not set assumes you want results. Chris@76: string fix_it_query: When doing fixes if an error was detected this query is executed to "fix" it. Chris@76: string fix_query: The query to execute to get data when doing a fix. If not set check_query is used again. Chris@76: array fix_collect: This array is used if the fix is basically gathering all broken ids and then doing something with it. Chris@76: - string index: The value returned from the main query and passed to the processing function. Chris@76: - process: A function passed an array of ids to execute the fix on. Chris@76: function fix_processing: Chris@76: Function called for each row returned from fix_query to execute whatever fixes are required. Chris@76: function fix_full_processing: Chris@76: As above but does the while loop and everything itself - except the freeing. Chris@76: array force_fix: If this is set then the error types included within this array will also be assumed broken. Chris@76: Note: At the moment only processes these if they occur after the primary error in the array. Chris@76: */ Chris@76: Chris@76: // This great array contains all of our error checks, fixes, etc etc etc. Chris@76: $errorTests = array( Chris@76: // Make a last-ditch-effort check to get rid of topics with zeros.. Chris@76: 'zero_topics' => array( Chris@76: 'check_query' => ' Chris@76: SELECT COUNT(*) Chris@76: FROM {db_prefix}topics Chris@76: WHERE id_topic = 0', Chris@76: 'check_type' => 'count', Chris@76: 'fix_it_query' => ' Chris@76: UPDATE {db_prefix}topics Chris@76: SET id_topic = NULL Chris@76: WHERE id_topic = 0', Chris@76: 'message' => 'repair_zero_ids', Chris@76: ), Chris@76: // ... and same with messages. Chris@76: 'zero_messages' => array( Chris@76: 'check_query' => ' Chris@76: SELECT COUNT(*) Chris@76: FROM {db_prefix}messages Chris@76: WHERE id_msg = 0', Chris@76: 'check_type' => 'count', Chris@76: 'fix_it_query' => ' Chris@76: UPDATE {db_prefix}messages Chris@76: SET id_msg = NULL Chris@76: WHERE id_msg = 0', Chris@76: 'message' => 'repair_zero_ids', Chris@76: ), Chris@76: // Find messages that don't have existing topics. Chris@76: 'missing_topics' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 1000, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_topic) Chris@76: FROM {db_prefix}messages' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT m.id_topic, m.id_msg Chris@76: FROM {db_prefix}messages AS m Chris@76: LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) Chris@76: WHERE m.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND t.id_topic IS NULL Chris@76: ORDER BY m.id_topic, m.id_msg', Chris@76: 'fix_query' => ' Chris@76: SELECT Chris@76: m.id_board, m.id_topic, MIN(m.id_msg) AS myid_first_msg, MAX(m.id_msg) AS myid_last_msg, Chris@76: COUNT(*) - 1 AS my_num_replies Chris@76: FROM {db_prefix}messages AS m Chris@76: LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) Chris@76: WHERE t.id_topic IS NULL Chris@76: GROUP BY m.id_topic, m.id_board', Chris@76: 'fix_processing' => create_function('$row', ' Chris@76: global $smcFunc, $salvageBoardID; Chris@76: Chris@76: // Only if we don\'t have a reasonable idea of where to put it. Chris@76: if ($row[\'id_board\'] == 0) Chris@76: { Chris@76: createSalvageArea(); Chris@76: $row[\'id_board\'] = (int) $salvageBoardID; Chris@76: } Chris@76: Chris@76: // Make sure that no topics claim the first/last message as theirs. Chris@76: $smcFunc[\'db_query\'](\'\', \' Chris@76: UPDATE {db_prefix}topics Chris@76: SET id_first_msg = 0 Chris@76: WHERE id_first_msg = {int:id_first_msg}\', Chris@76: array( Chris@76: \'id_first_msg\' => $row[\'myid_first_msg\'], Chris@76: ) Chris@76: ); Chris@76: $smcFunc[\'db_query\'](\'\', \' Chris@76: UPDATE {db_prefix}topics Chris@76: SET id_last_msg = 0 Chris@76: WHERE id_last_msg = {int:id_last_msg}\', Chris@76: array( Chris@76: \'id_last_msg\' => $row[\'myid_last_msg\'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: $memberStartedID = (int) getMsgMemberID($row[\'myid_first_msg\']); Chris@76: $memberUpdatedID = (int) getMsgMemberID($row[\'myid_last_msg\']); Chris@76: Chris@76: $smcFunc[\'db_insert\'](\'\', Chris@76: \'{db_prefix}topics\', Chris@76: array( Chris@76: \'id_board\' => \'int\', Chris@76: \'id_member_started\' => \'int\', Chris@76: \'id_member_updated\' => \'int\', Chris@76: \'id_first_msg\' => \'int\', Chris@76: \'id_last_msg\' => \'int\', Chris@76: \'num_replies\' => \'int\' Chris@76: ), Chris@76: array( Chris@76: $row[\'id_board\'], Chris@76: $memberStartedID, Chris@76: $memberUpdatedID, Chris@76: $row[\'myid_first_msg\'], Chris@76: $row[\'myid_last_msg\'], Chris@76: $row[\'my_num_replies\'] Chris@76: ), Chris@76: array(\'id_topic\') Chris@76: ); Chris@76: Chris@76: $newTopicID = $smcFunc[\'db_insert_id\']("{db_prefix}topics", \'id_topic\'); Chris@76: Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}messages Chris@76: SET id_topic = $newTopicID, id_board = $row[id_board] Chris@76: WHERE id_topic = $row[id_topic]", Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: 'force_fix' => array('stats_topics'), Chris@76: 'messages' => array('repair_missing_topics', 'id_msg', 'id_topic'), Chris@76: ), Chris@76: // Find topics with no messages. Chris@76: 'missing_messages' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 1000, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_topic) Chris@76: FROM {db_prefix}topics' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT t.id_topic, COUNT(m.id_msg) AS num_msg Chris@76: FROM {db_prefix}topics AS t Chris@76: LEFT JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic) Chris@76: WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY t.id_topic Chris@76: HAVING COUNT(m.id_msg) = 0', Chris@76: // Remove all topics that have zero messages in the messages table. Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_topic', Chris@76: 'process' => create_function('$topics', ' Chris@76: global $smcFunc; 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_topics Chris@76: WHERE id_topic IN ({array_int:topics})", Chris@76: array( Chris@76: \'topics\' => $topics Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_messages', 'id_topic'), Chris@76: ), Chris@76: 'polls_missing_topics' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_poll) Chris@76: FROM {db_prefix}polls' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT p.id_poll, p.id_member, p.poster_name, t.id_board Chris@76: FROM {db_prefix}polls AS p Chris@76: LEFT JOIN {db_prefix}topics AS t ON (t.id_poll = p.id_poll) Chris@76: WHERE p.id_poll BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND t.id_poll IS NULL', Chris@76: 'fix_processing' => create_function('$row', ' Chris@76: global $smcFunc, $salvageBoardID, $txt; Chris@76: Chris@76: // Only if we don\'t have a reasonable idea of where to put it. Chris@76: if ($row[\'id_board\'] == 0) Chris@76: { Chris@76: createSalvageArea(); Chris@76: $row[\'id_board\'] = (int) $salvageBoardID; Chris@76: } Chris@76: Chris@76: $row[\'poster_name\'] = !empty($row[\'poster_name\']) ? $row[\'poster_name\'] : $txt[\'guest\']; Chris@76: Chris@76: $smcFunc[\'db_insert\'](\'\', Chris@76: \'{db_prefix}messages\', Chris@76: array( Chris@76: \'id_board\' => \'int\', Chris@76: \'id_topic\' => \'int\', Chris@76: \'poster_time\' => \'int\', Chris@76: \'id_member\' => \'int\', Chris@76: \'subject\' => \'string-255\', Chris@76: \'poster_name\' => \'string-255\', Chris@76: \'poster_email\' => \'string-255\', Chris@76: \'poster_ip\' => \'string-16\', Chris@76: \'smileys_enabled\' => \'int\', Chris@76: \'body\' => \'string-65534\', Chris@76: \'icon\' => \'string-16\', Chris@76: \'approved\' => \'int\', Chris@76: ), Chris@76: array( Chris@76: $row[\'id_board\'], Chris@76: 0, Chris@76: time(), Chris@76: $row[\'id_member\'], Chris@76: $txt[\'salvaged_poll_topic_name\'], Chris@76: $row[\'poster_name\'], Chris@76: \'\', Chris@76: \'127.0.0.1\', Chris@76: 1, Chris@76: $txt[\'salvaged_poll_message_body\'], Chris@76: \'xx\', Chris@76: 1, Chris@76: ), Chris@76: array(\'id_topic\') Chris@76: ); Chris@76: Chris@76: $newMessageID = $smcFunc[\'db_insert_id\']("{db_prefix}messages", \'id_msg\'); Chris@76: Chris@76: $smcFunc[\'db_insert\'](\'\', Chris@76: \'{db_prefix}topics\', Chris@76: array( Chris@76: \'id_board\' => \'int\', Chris@76: \'id_poll\' => \'int\', Chris@76: \'id_member_started\' => \'int\', Chris@76: \'id_member_updated\' => \'int\', Chris@76: \'id_first_msg\' => \'int\', Chris@76: \'id_last_msg\' => \'int\', Chris@76: \'num_replies\' => \'int\', Chris@76: ), Chris@76: array( Chris@76: $row[\'id_board\'], Chris@76: $row[\'id_poll\'], Chris@76: $row[\'id_member\'], Chris@76: $row[\'id_member\'], Chris@76: $newMessageID, Chris@76: $newMessageID, Chris@76: 0, Chris@76: ), Chris@76: array(\'id_topic\') Chris@76: ); Chris@76: Chris@76: $newTopicID = $smcFunc[\'db_insert_id\']("{db_prefix}topics", \'id_topic\'); Chris@76: Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}messages Chris@76: SET id_topic = $newTopicID, id_board = $row[id_board] Chris@76: WHERE id_msg = $newMessageID", Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: Chris@76: updateStats(\'subject\', $newTopicID, $txt[\'salvaged_poll_topic_name\']); Chris@76: Chris@76: '), Chris@76: 'force_fix' => array('stats_topics'), Chris@76: 'messages' => array('repair_polls_missing_topics', 'id_poll', 'id_topic'), Chris@76: ), Chris@76: 'stats_topics' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 200, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_topic) Chris@76: FROM {db_prefix}topics' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT Chris@76: t.id_topic, t.id_first_msg, t.id_last_msg, Chris@76: CASE WHEN MIN(ma.id_msg) > 0 THEN Chris@76: CASE WHEN MIN(mu.id_msg) > 0 THEN Chris@76: CASE WHEN MIN(mu.id_msg) < MIN(ma.id_msg) THEN MIN(mu.id_msg) ELSE MIN(ma.id_msg) END ELSE Chris@76: MIN(ma.id_msg) END ELSE Chris@76: MIN(mu.id_msg) END AS myid_first_msg, Chris@76: CASE WHEN MAX(ma.id_msg) > 0 THEN MAX(ma.id_msg) ELSE MIN(mu.id_msg) END AS myid_last_msg, Chris@76: t.approved, mf.approved, mf.approved AS firstmsg_approved Chris@76: FROM {db_prefix}topics AS t Chris@76: LEFT JOIN {db_prefix}messages AS ma ON (ma.id_topic = t.id_topic AND ma.approved = 1) Chris@76: LEFT JOIN {db_prefix}messages AS mu ON (mu.id_topic = t.id_topic AND mu.approved = 0) Chris@76: LEFT JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) Chris@76: WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY t.id_topic, t.id_first_msg, t.id_last_msg, t.approved, mf.approved Chris@76: ORDER BY t.id_topic', Chris@76: 'fix_processing' => create_function('$row', ' Chris@76: global $smcFunc; Chris@76: $row[\'firstmsg_approved\'] = (int) $row[\'firstmsg_approved\']; Chris@76: $row[\'myid_first_msg\'] = (int) $row[\'myid_first_msg\']; Chris@76: $row[\'myid_last_msg\'] = (int) $row[\'myid_last_msg\']; Chris@76: Chris@76: // Not really a problem? Chris@76: if ($row[\'myid_first_msg\'] == $row[\'myid_first_msg\'] && $row[\'myid_first_msg\'] == $row[\'myid_first_msg\'] && $row[\'approved\'] == $row[\'firstmsg_approved\']) Chris@76: return false; Chris@76: Chris@76: $memberStartedID = (int) getMsgMemberID($row[\'myid_first_msg\']); Chris@76: $memberUpdatedID = (int) getMsgMemberID($row[\'myid_last_msg\']); Chris@76: Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}topics Chris@76: SET id_first_msg = $row[myid_first_msg], Chris@76: id_member_started = $memberStartedID, id_last_msg = $row[myid_last_msg], Chris@76: id_member_updated = $memberUpdatedID, approved = $row[firstmsg_approved] Chris@76: WHERE id_topic = $row[id_topic]", Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: 'message_function' => create_function('$row', ' Chris@76: global $txt, $context; Chris@76: Chris@76: // A pretend error? Chris@76: if ($row[\'myid_first_msg\'] == $row[\'myid_first_msg\'] && $row[\'myid_first_msg\'] == $row[\'myid_first_msg\'] && $row[\'approved\'] == $row[\'firstmsg_approved\']) Chris@76: return false; Chris@76: Chris@76: if ($row[\'id_first_msg\'] != $row[\'myid_first_msg\']) Chris@76: $context[\'repair_errors\'][] = sprintf($txt[\'repair_stats_topics_1\'], $row[\'id_topic\'], $row[\'id_first_msg\']); Chris@76: if ($row[\'id_last_msg\'] != $row[\'myid_last_msg\']) Chris@76: $context[\'repair_errors\'][] = sprintf($txt[\'repair_stats_topics_2\'], $row[\'id_topic\'], $row[\'id_last_msg\']); Chris@76: if ($row[\'approved\'] != $row[\'firstmsg_approved\']) Chris@76: $context[\'repair_errors\'][] = sprintf($txt[\'repair_stats_topics_5\'], $row[\'id_topic\']); Chris@76: Chris@76: return true; Chris@76: '), Chris@76: ), Chris@76: // Find topics with incorrect num_replies. Chris@76: 'stats_topics2' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 300, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_topic) Chris@76: FROM {db_prefix}topics' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT Chris@76: t.id_topic, t.num_replies, mf.approved, Chris@76: CASE WHEN COUNT(ma.id_msg) > 0 THEN CASE WHEN mf.approved > 0 THEN COUNT(ma.id_msg) - 1 ELSE COUNT(ma.id_msg) END ELSE 0 END AS my_num_replies Chris@76: FROM {db_prefix}topics AS t Chris@76: LEFT JOIN {db_prefix}messages AS ma ON (ma.id_topic = t.id_topic AND ma.approved = 1) Chris@76: LEFT JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) Chris@76: WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY t.id_topic, t.num_replies, mf.approved Chris@76: ORDER BY t.id_topic', Chris@76: 'fix_processing' => create_function('$row', ' Chris@76: global $smcFunc; Chris@76: $row[\'my_num_replies\'] = (int) $row[\'my_num_replies\']; Chris@76: Chris@76: // Not really a problem? Chris@76: if ($row[\'my_num_replies\'] == $row[\'num_replies\']) Chris@76: return false; Chris@76: Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}topics Chris@76: SET num_replies = $row[my_num_replies] Chris@76: WHERE id_topic = $row[id_topic]", Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: 'message_function' => create_function('$row', ' Chris@76: global $txt, $context; Chris@76: Chris@76: // Just joking? Chris@76: if ($row[\'my_num_replies\'] == $row[\'num_replies\']) Chris@76: return false; Chris@76: Chris@76: if ($row[\'num_replies\'] != $row[\'my_num_replies\']) Chris@76: $context[\'repair_errors\'][] = sprintf($txt[\'repair_stats_topics_3\'], $row[\'id_topic\'], $row[\'num_replies\']); Chris@76: Chris@76: return true; Chris@76: '), Chris@76: ), Chris@76: // Find topics with incorrect unapproved_posts. Chris@76: 'stats_topics3' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 1000, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_topic) Chris@76: FROM {db_prefix}topics' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT Chris@76: t.id_topic, t.unapproved_posts, COUNT(mu.id_msg) AS my_unapproved_posts Chris@76: FROM {db_prefix}topics AS t Chris@76: LEFT JOIN {db_prefix}messages AS mu ON (mu.id_topic = t.id_topic AND mu.approved = 0) Chris@76: WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY t.id_topic, t.unapproved_posts Chris@76: HAVING unapproved_posts != COUNT(mu.id_msg) Chris@76: ORDER BY t.id_topic', Chris@76: 'fix_processing' => create_function('$row', ' Chris@76: global $smcFunc; Chris@76: $row[\'my_unapproved_posts\'] = (int) $row[\'my_unapproved_posts\']; Chris@76: Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}topics Chris@76: SET unapproved_posts = $row[my_unapproved_posts] Chris@76: WHERE id_topic = $row[id_topic]", Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: 'messages' => array('repair_stats_topics_4', 'id_topic', 'unapproved_posts'), Chris@76: ), Chris@76: // Find topics with nonexistent boards. Chris@76: 'missing_boards' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 1000, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_topic) Chris@76: FROM {db_prefix}topics' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT t.id_topic, t.id_board Chris@76: FROM {db_prefix}topics AS t Chris@76: LEFT JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) Chris@76: WHERE b.id_board IS NULL Chris@76: AND t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: ORDER BY t.id_board, t.id_topic', Chris@76: 'fix_query' => ' Chris@76: SELECT t.id_board, COUNT(*) AS my_num_topics, COUNT(m.id_msg) AS my_num_posts Chris@76: FROM {db_prefix}topics AS t Chris@76: LEFT JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) Chris@76: LEFT JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic) Chris@76: WHERE b.id_board IS NULL Chris@76: AND t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY t.id_board', Chris@76: 'fix_processing' => create_function('$row', ' Chris@76: global $smcFunc, $salvageCatID; Chris@76: createSalvageArea(); Chris@76: Chris@76: $row[\'my_num_topics\'] = (int) $row[\'my_num_topics\']; Chris@76: $row[\'my_num_posts\'] = (int) $row[\'my_num_posts\']; Chris@76: Chris@76: $smcFunc[\'db_insert\'](\'\', Chris@76: \'{db_prefix}boards\', Chris@76: array(\'id_cat\' => \'int\', \'name\' => \'string\', \'description\' => \'string\', \'num_topics\' => \'int\', \'num_posts\' => \'int\', \'member_groups\' => \'string\'), Chris@76: array($salvageCatID, \'Salvaged board\', \'\', $row[\'my_num_topics\'], $row[\'my_num_posts\'], \'1\'), Chris@76: array(\'id_board\') Chris@76: ); Chris@76: $newBoardID = $smcFunc[\'db_insert_id\'](\'{db_prefix}boards\', \'id_board\'); Chris@76: Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}topics Chris@76: SET id_board = $newBoardID Chris@76: WHERE id_board = $row[id_board]", Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}messages Chris@76: SET id_board = $newBoardID Chris@76: WHERE id_board = $row[id_board]", Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: 'messages' => array('repair_missing_boards', 'id_topic', 'id_board'), Chris@76: ), Chris@76: // Find boards with nonexistent categories. Chris@76: 'missing_categories' => array( Chris@76: 'check_query' => ' Chris@76: SELECT b.id_board, b.id_cat Chris@76: FROM {db_prefix}boards AS b Chris@76: LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat) Chris@76: WHERE c.id_cat IS NULL Chris@76: ORDER BY b.id_cat, b.id_board', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_cat', Chris@76: 'process' => create_function('$cats', ' Chris@76: global $smcFunc, $salvageCatID; Chris@76: createSalvageArea(); Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}boards Chris@76: SET id_cat = $salvageCatID Chris@76: WHERE id_cat IN ({array_int:categories})", Chris@76: array( Chris@76: \'categories\' => $cats Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_categories', 'id_board', 'id_cat'), Chris@76: ), Chris@76: // Find messages with nonexistent members. Chris@76: 'missing_posters' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 2000, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_msg) Chris@76: FROM {db_prefix}messages' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT m.id_msg, m.id_member Chris@76: FROM {db_prefix}messages AS m Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) Chris@76: WHERE mem.id_member IS NULL Chris@76: AND m.id_member != 0 Chris@76: AND m.id_msg BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: ORDER BY m.id_msg', Chris@76: // Last step-make sure all non-guest posters still exist. Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_msg', Chris@76: 'process' => create_function('$msgs', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}messages Chris@76: SET id_member = 0 Chris@76: WHERE id_msg IN ({array_int:msgs})", Chris@76: array( Chris@76: \'msgs\' => $msgs Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_posters', 'id_msg', 'id_member'), Chris@76: ), Chris@76: // Find boards with nonexistent parents. Chris@76: 'missing_parents' => array( Chris@76: 'check_query' => ' Chris@76: SELECT b.id_board, b.id_parent Chris@76: FROM {db_prefix}boards AS b Chris@76: LEFT JOIN {db_prefix}boards AS p ON (p.id_board = b.id_parent) Chris@76: WHERE b.id_parent != 0 Chris@76: AND (p.id_board IS NULL OR p.id_board = b.id_board) Chris@76: ORDER BY b.id_parent, b.id_board', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_parent', Chris@76: 'process' => create_function('$parents', ' Chris@76: global $smcFunc, $salvageBoardID, $salvageCatID; Chris@76: createSalvageArea(); Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}boards Chris@76: SET id_parent = $salvageBoardID, id_cat = $salvageCatID, child_level = 1 Chris@76: WHERE id_parent IN ({array_int:parents})", Chris@76: array( Chris@76: \'parents\' => $parents Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_parents', 'id_board', 'id_parent'), Chris@76: ), Chris@76: 'missing_polls' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_poll) Chris@76: FROM {db_prefix}topics' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT t.id_poll, t.id_topic Chris@76: FROM {db_prefix}topics AS t Chris@76: LEFT JOIN {db_prefix}polls AS p ON (p.id_poll = t.id_poll) Chris@76: WHERE t.id_poll != 0 Chris@76: AND t.id_poll BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND p.id_poll IS NULL', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_poll', Chris@76: 'process' => create_function('$polls', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}topics Chris@76: SET id_poll = 0 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: 'messages' => array('repair_missing_polls', 'id_topic', 'id_poll'), Chris@76: ), Chris@76: 'missing_calendar_topics' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 1000, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_topic) Chris@76: FROM {db_prefix}calendar' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT cal.id_topic, cal.id_event Chris@76: FROM {db_prefix}calendar AS cal Chris@76: LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = cal.id_topic) Chris@76: WHERE cal.id_topic != 0 Chris@76: AND cal.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND t.id_topic IS NULL Chris@76: ORDER BY cal.id_topic', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_topic', Chris@76: 'process' => create_function('$events', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', \' Chris@76: UPDATE {db_prefix}calendar Chris@76: SET id_topic = 0, id_board = 0 Chris@76: WHERE id_topic IN ({array_int:events})\', Chris@76: array( Chris@76: \'events\' => $events Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_calendar_topics', 'id_event', 'id_topic'), Chris@76: ), Chris@76: 'missing_log_topics' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 150, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_member) Chris@76: FROM {db_prefix}log_topics' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lt.id_topic Chris@76: FROM {db_prefix}log_topics AS lt Chris@76: LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = lt.id_topic) Chris@76: WHERE t.id_topic IS NULL Chris@76: AND lt.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_topic', Chris@76: 'process' => create_function('$topics', ' Chris@76: global $smcFunc; 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: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_log_topics', 'id_topic'), Chris@76: ), Chris@76: 'missing_log_topics_members' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 150, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_member) Chris@76: FROM {db_prefix}log_topics' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lt.id_member Chris@76: FROM {db_prefix}log_topics AS lt Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lt.id_member) Chris@76: WHERE mem.id_member IS NULL Chris@76: AND lt.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY lt.id_member', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_member', Chris@76: 'process' => create_function('$members', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_topics Chris@76: WHERE id_member IN ({array_int:members})", Chris@76: array( Chris@76: \'members\' => $members Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_log_topics_members', 'id_member'), Chris@76: ), Chris@76: 'missing_log_boards' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_member) Chris@76: FROM {db_prefix}log_boards' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lb.id_board Chris@76: FROM {db_prefix}log_boards AS lb Chris@76: LEFT JOIN {db_prefix}boards AS b ON (b.id_board = lb.id_board) Chris@76: WHERE b.id_board IS NULL Chris@76: AND lb.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY lb.id_board', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_board', Chris@76: 'process' => create_function('$boards', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_boards Chris@76: WHERE id_board IN ({array_int:boards})", Chris@76: array( Chris@76: \'boards\' => $boards Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_log_boards', 'id_board'), Chris@76: ), Chris@76: 'missing_log_boards_members' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_member) Chris@76: FROM {db_prefix}log_boards' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lb.id_member Chris@76: FROM {db_prefix}log_boards AS lb Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lb.id_member) Chris@76: WHERE mem.id_member IS NULL Chris@76: AND lb.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY lb.id_member', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_member', Chris@76: 'process' => create_function('$members', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_boards Chris@76: WHERE id_member IN ({array_int:members})", Chris@76: array( Chris@76: \'members\' => $members Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_log_boards_members', 'id_member'), Chris@76: ), Chris@76: 'missing_log_mark_read' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_member) Chris@76: FROM {db_prefix}log_mark_read' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lmr.id_board Chris@76: FROM {db_prefix}log_mark_read AS lmr Chris@76: LEFT JOIN {db_prefix}boards AS b ON (b.id_board = lmr.id_board) Chris@76: WHERE b.id_board IS NULL Chris@76: AND lmr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY lmr.id_board', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_board', Chris@76: 'process' => create_function('$boards', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_mark_read Chris@76: WHERE id_board IN ({array_int:boards})", Chris@76: array( Chris@76: \'boards\' => $boards Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_log_mark_read', 'id_board'), Chris@76: ), Chris@76: 'missing_log_mark_read_members' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_member) Chris@76: FROM {db_prefix}log_mark_read' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lmr.id_member Chris@76: FROM {db_prefix}log_mark_read AS lmr Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lmr.id_member) Chris@76: WHERE mem.id_member IS NULL Chris@76: AND lmr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY lmr.id_member', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_member', Chris@76: 'process' => create_function('$members', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_mark_read Chris@76: WHERE id_member IN ({array_int:members})", Chris@76: array( Chris@76: \'members\' => $members Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_log_mark_read_members', 'id_member'), Chris@76: ), Chris@76: 'missing_pms' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_pm) Chris@76: FROM {db_prefix}pm_recipients' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT pmr.id_pm Chris@76: FROM {db_prefix}pm_recipients AS pmr Chris@76: LEFT JOIN {db_prefix}personal_messages AS pm ON (pm.id_pm = pmr.id_pm) Chris@76: WHERE pm.id_pm IS NULL Chris@76: AND pmr.id_pm BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: GROUP BY pmr.id_pm', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_pm', Chris@76: 'process' => create_function('$pms', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}pm_recipients Chris@76: WHERE id_pm IN ({array_int:pms})", Chris@76: array( Chris@76: \'pms\' => $pms Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_pms', 'id_pm'), Chris@76: ), Chris@76: 'missing_recipients' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_member) Chris@76: FROM {db_prefix}pm_recipients' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT pmr.id_member Chris@76: FROM {db_prefix}pm_recipients AS pmr Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = pmr.id_member) Chris@76: WHERE pmr.id_member != 0 Chris@76: AND pmr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND mem.id_member IS NULL Chris@76: GROUP BY pmr.id_member', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_member', Chris@76: 'process' => create_function('$members', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}pm_recipients Chris@76: WHERE id_member IN ({array_int:members})", Chris@76: array( Chris@76: \'members\' => $members Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_recipients', 'id_member'), Chris@76: ), Chris@76: 'missing_senders' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_pm) Chris@76: FROM {db_prefix}personal_messages' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT pm.id_pm, pm.id_member_from Chris@76: FROM {db_prefix}personal_messages AS pm Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = pm.id_member_from) Chris@76: WHERE pm.id_member_from != 0 Chris@76: AND pm.id_pm BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND mem.id_member IS NULL', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_pm', Chris@76: 'process' => create_function('$guestMessages', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: UPDATE {db_prefix}personal_messages Chris@76: SET id_member_from = 0 Chris@76: WHERE id_pm IN ({array_int:guestMessages})", Chris@76: array( Chris@76: \'guestMessages\' => $guestMessages Chris@76: )); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_senders', 'id_pm', 'id_member_from'), Chris@76: ), Chris@76: 'missing_notify_members' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_member) Chris@76: FROM {db_prefix}log_notify' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT ln.id_member Chris@76: FROM {db_prefix}log_notify AS ln Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = ln.id_member) Chris@76: WHERE ln.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND mem.id_member IS NULL Chris@76: GROUP BY ln.id_member', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_member', Chris@76: 'process' => create_function('$members', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_notify Chris@76: WHERE id_member IN ({array_int:members})", Chris@76: array( Chris@76: \'members\' => $members Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_notify_members', 'id_member'), Chris@76: ), Chris@76: 'missing_cached_subject' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 100, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_topic) Chris@76: FROM {db_prefix}topics' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT t.id_topic, fm.subject Chris@76: FROM {db_prefix}topics AS t Chris@76: INNER JOIN {db_prefix}messages AS fm ON (fm.id_msg = t.id_first_msg) Chris@76: LEFT JOIN {db_prefix}log_search_subjects AS lss ON (lss.id_topic = t.id_topic) Chris@76: WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND lss.id_topic IS NULL', Chris@76: 'fix_full_processing' => create_function('$result', ' Chris@76: global $smcFunc; Chris@76: Chris@76: $inserts = array(); Chris@76: while ($row = $smcFunc[\'db_fetch_assoc\']($result)) Chris@76: { Chris@76: foreach (text2words($row[\'subject\']) as $word) Chris@76: $inserts[] = array($word, $row[\'id_topic\']); Chris@76: if (count($inserts) > 500) Chris@76: { Chris@76: $smcFunc[\'db_insert\'](\'ignore\', Chris@76: "{db_prefix}log_search_subjects", Chris@76: array(\'word\' => \'string\', \'id_topic\' => \'int\'), Chris@76: $inserts, Chris@76: array(\'word\', \'id_topic\') Chris@76: ); Chris@76: $inserts = array(); Chris@76: } Chris@76: Chris@76: } Chris@76: Chris@76: if (!empty($inserts)) Chris@76: $smcFunc[\'db_insert\'](\'ignore\', Chris@76: "{db_prefix}log_search_subjects", Chris@76: array(\'word\' => \'string\', \'id_topic\' => \'int\'), Chris@76: $inserts, Chris@76: array(\'word\', \'id_topic\') Chris@76: ); Chris@76: '), Chris@76: 'message_function' => create_function('$row', ' Chris@76: global $txt, $context; Chris@76: Chris@76: if (count(text2words($row[\'subject\'])) != 0) Chris@76: { Chris@76: $context[\'repair_errors\'][] = sprintf($txt[\'repair_missing_cached_subject\'], $row[\'id_topic\']); Chris@76: return true; Chris@76: } Chris@76: Chris@76: return false; Chris@76: '), Chris@76: ), Chris@76: 'missing_topic_for_cache' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 50, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_topic) Chris@76: FROM {db_prefix}log_search_subjects' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lss.id_topic, lss.word Chris@76: FROM {db_prefix}log_search_subjects AS lss Chris@76: LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = lss.id_topic) Chris@76: WHERE lss.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND t.id_topic IS NULL', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_topic', Chris@76: 'process' => create_function('$deleteTopics', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_search_subjects Chris@76: WHERE id_topic IN ({array_int:deleteTopics})", Chris@76: array( Chris@76: \'deleteTopics\' => $deleteTopics Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_topic_for_cache', 'word'), Chris@76: ), Chris@76: 'missing_member_vote' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_member) Chris@76: FROM {db_prefix}log_polls' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lp.id_poll, lp.id_member Chris@76: FROM {db_prefix}log_polls AS lp Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lp.id_member) Chris@76: WHERE lp.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND lp.id_member > 0 Chris@76: AND mem.id_member IS NULL', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_member', Chris@76: 'process' => create_function('$members', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_polls Chris@76: WHERE id_member IN ({array_int:members})", Chris@76: array( Chris@76: \'members\' => $members Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_missing_log_poll_member', 'id_poll', 'id_member'), Chris@76: ), Chris@76: 'missing_log_poll_vote' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_poll) Chris@76: FROM {db_prefix}log_polls' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lp.id_poll, lp.id_member Chris@76: FROM {db_prefix}log_polls AS lp Chris@76: LEFT JOIN {db_prefix}polls AS p ON (p.id_poll = lp.id_poll) Chris@76: WHERE lp.id_poll BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND p.id_poll IS NULL', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_poll', Chris@76: 'process' => create_function('$polls', ' Chris@76: global $smcFunc; 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: 'messages' => array('repair_missing_log_poll_vote', 'id_member', 'id_poll'), Chris@76: ), Chris@76: 'report_missing_comments' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 500, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_report) Chris@76: FROM {db_prefix}log_reported' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lr.id_report, lr.subject Chris@76: FROM {db_prefix}log_reported AS lr Chris@76: LEFT JOIN {db_prefix}log_reported_comments AS lrc ON (lrc.id_report = lr.id_report) Chris@76: WHERE lr.id_report BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND lrc.id_report IS NULL', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_report', Chris@76: 'process' => create_function('$reports', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_reported Chris@76: WHERE id_report IN ({array_int:reports})", Chris@76: array( Chris@76: \'reports\' => $reports Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_report_missing_comments', 'id_report', 'subject'), Chris@76: ), Chris@76: 'comments_missing_report' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 200, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_report) Chris@76: FROM {db_prefix}log_reported_comments' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lrc.id_report, lrc.membername Chris@76: FROM {db_prefix}log_reported_comments AS lrc Chris@76: LEFT JOIN {db_prefix}log_reported AS lr ON (lr.id_report = lrc.id_report) Chris@76: WHERE lrc.id_report BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND lr.id_report IS NULL', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_report', Chris@76: 'process' => create_function('$reports', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_reported_comments Chris@76: WHERE id_report IN ({array_int:reports})", Chris@76: array( Chris@76: \'reports\' => $reports Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_comments_missing_report', 'id_report', 'membername'), Chris@76: ), Chris@76: 'group_request_missing_member' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 200, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_member) Chris@76: FROM {db_prefix}log_group_requests' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lgr.id_member Chris@76: FROM {db_prefix}log_group_requests AS lgr Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lgr.id_member) Chris@76: WHERE lgr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND mem.id_member IS NULL Chris@76: GROUP BY lgr.id_member', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_member', Chris@76: 'process' => create_function('$members', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', " Chris@76: DELETE FROM {db_prefix}log_group_requests Chris@76: WHERE id_member IN ({array_int:members})", Chris@76: array( Chris@76: \'members\' => $members Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_group_request_missing_member', 'id_member'), Chris@76: ), Chris@76: 'group_request_missing_group' => array( Chris@76: 'substeps' => array( Chris@76: 'step_size' => 200, Chris@76: 'step_max' => ' Chris@76: SELECT MAX(id_group) Chris@76: FROM {db_prefix}log_group_requests' Chris@76: ), Chris@76: 'check_query' => ' Chris@76: SELECT lgr.id_group Chris@76: FROM {db_prefix}log_group_requests AS lgr Chris@76: LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = lgr.id_group) Chris@76: WHERE lgr.id_group BETWEEN {STEP_LOW} AND {STEP_HIGH} Chris@76: AND mg.id_group IS NULL Chris@76: GROUP BY lgr.id_group', Chris@76: 'fix_collect' => array( Chris@76: 'index' => 'id_group', Chris@76: 'process' => create_function('$groups', ' Chris@76: global $smcFunc; Chris@76: $smcFunc[\'db_query\'](\'\', \' Chris@76: DELETE FROM {db_prefix}log_group_requests Chris@76: WHERE id_group IN ({array_int:groups})\', Chris@76: array( Chris@76: \'groups\' => $groups Chris@76: ) Chris@76: ); Chris@76: '), Chris@76: ), Chris@76: 'messages' => array('repair_group_request_missing_group', 'id_group'), Chris@76: ), Chris@76: ); Chris@76: } Chris@76: Chris@76: function findForumErrors($do_fix = false) Chris@76: { Chris@76: global $context, $txt, $smcFunc, $errorTests, $db_cache, $db_temp_cache; Chris@76: Chris@76: // This may take some time... Chris@76: @set_time_limit(600); Chris@76: Chris@76: $to_fix = !empty($_SESSION['repairboards_to_fix']) ? $_SESSION['repairboards_to_fix'] : array(); Chris@76: $context['repair_errors'] = isset($_SESSION['repairboards_to_fix2']) ? $_SESSION['repairboards_to_fix2'] : array(); Chris@76: Chris@76: $_GET['step'] = empty($_GET['step']) ? 0 : (int) $_GET['step']; Chris@76: $_GET['substep'] = empty($_GET['substep']) ? 0 : (int) $_GET['substep']; Chris@76: Chris@76: // Don't allow the cache to get too full. Chris@76: $db_temp_cache = $db_cache; Chris@76: $db_cache = ''; Chris@76: Chris@76: $context['total_steps'] = count($errorTests); Chris@76: Chris@76: // For all the defined error types do the necessary tests. Chris@76: $current_step = -1; Chris@76: $total_queries = 0; Chris@76: foreach ($errorTests as $error_type => $test) Chris@76: { Chris@76: $current_step++; Chris@76: Chris@76: // Already done this? Chris@76: if ($_GET['step'] > $current_step) Chris@76: continue; Chris@76: Chris@76: // If we're fixing it but it ain't broke why try? Chris@76: if ($do_fix && !in_array($error_type, $to_fix)) Chris@76: { Chris@76: $_GET['step']++; Chris@76: continue; Chris@76: } Chris@76: Chris@76: // Has it got substeps? Chris@76: if (isset($test['substeps'])) Chris@76: { Chris@76: $step_size = isset($test['substeps']['step_size']) ? $test['substeps']['step_size'] : 100; Chris@76: $request = $smcFunc['db_query']('', Chris@76: $test['substeps']['step_max'], Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: list ($step_max) = $smcFunc['db_fetch_row']($request); Chris@76: Chris@76: $total_queries++; Chris@76: $smcFunc['db_free_result']($request); Chris@76: } Chris@76: Chris@76: // We in theory keep doing this... the substeps. Chris@76: $done = false; Chris@76: while (!$done) Chris@76: { Chris@76: // Make sure there's at least one ID to test. Chris@76: if (isset($test['substeps']) && empty($step_max)) Chris@76: break; Chris@76: Chris@76: // What is the testing query (Changes if we are testing or fixing) Chris@76: if (!$do_fix) Chris@76: $test_query = 'check_query'; Chris@76: else Chris@76: $test_query = isset($test['fix_query']) ? 'fix_query' : 'check_query'; Chris@76: Chris@76: // Do the test... Chris@76: $request = $smcFunc['db_query']('', Chris@76: isset($test['substeps']) ? strtr($test[$test_query], array('{STEP_LOW}' => $_GET['substep'], '{STEP_HIGH}' => $_GET['substep'] + $step_size - 1)) : $test[$test_query], Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: $needs_fix = false; Chris@76: Chris@76: // Does it need a fix? Chris@76: if (!empty($test['check_type']) && $test['check_type'] == 'count') Chris@76: list ($needs_fix) = $smcFunc['db_fetch_row']($request); Chris@76: else Chris@76: $needs_fix = $smcFunc['db_num_rows']($request); Chris@76: Chris@76: $total_queries++; Chris@76: Chris@76: if ($needs_fix) Chris@76: { Chris@76: // What about a message to the user? Chris@76: if (!$do_fix) Chris@76: { Chris@76: // Assume need to fix. Chris@76: $found_errors = true; Chris@76: Chris@76: if (isset($test['message'])) Chris@76: $context['repair_errors'][] = $txt[$test['message']]; Chris@76: Chris@76: // One per row! Chris@76: elseif (isset($test['messages'])) Chris@76: { Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: $variables = $test['messages']; Chris@76: foreach ($variables as $k => $v) Chris@76: { Chris@76: if ($k == 0 && isset($txt[$v])) Chris@76: $variables[$k] = $txt[$v]; Chris@76: elseif ($k > 0 && isset($row[$v])) Chris@76: $variables[$k] = $row[$v]; Chris@76: } Chris@76: $context['repair_errors'][] = call_user_func_array('sprintf', $variables); Chris@76: } Chris@76: } Chris@76: Chris@76: // A function to process? Chris@76: elseif (isset($test['message_function'])) Chris@76: { Chris@76: // Find out if there are actually errors. Chris@76: $found_errors = false; Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $found_errors |= $test['message_function']($row); Chris@76: } Chris@76: Chris@76: // Actually have something to fix? Chris@76: if ($found_errors) Chris@76: $to_fix[] = $error_type; Chris@76: } Chris@76: Chris@76: // We want to fix, we need to fix - so work out what exactly to do! Chris@76: else Chris@76: { Chris@76: // Are we simply getting a collection of ids? Chris@76: if (isset($test['fix_collect'])) Chris@76: { Chris@76: $ids = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $ids[] = $row[$test['fix_collect']['index']]; Chris@76: if (!empty($ids)) Chris@76: { Chris@76: // Fix it! Chris@76: $test['fix_collect']['process']($ids); Chris@76: } Chris@76: } Chris@76: Chris@76: // Simply executing a fix it query? Chris@76: elseif (isset($test['fix_it_query'])) Chris@76: $smcFunc['db_query']('', Chris@76: $test['fix_it_query'], Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Do we have some processing to do? Chris@76: elseif (isset($test['fix_processing'])) Chris@76: { Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $test['fix_processing']($row); Chris@76: } Chris@76: Chris@76: // What about the full set of processing? Chris@76: elseif (isset($test['fix_full_processing'])) Chris@76: $test['fix_full_processing']($request); Chris@76: Chris@76: // Do we have other things we need to fix as a result? Chris@76: if (!empty($test['force_fix'])) Chris@76: { Chris@76: foreach ($test['force_fix'] as $item) Chris@76: if (!in_array($item, $to_fix)) Chris@76: $to_fix[] = $item; Chris@76: } Chris@76: } Chris@76: } Chris@76: Chris@76: // Free the result. Chris@76: $smcFunc['db_free_result']($request); Chris@76: // Keep memory down. Chris@76: $db_cache = ''; Chris@76: Chris@76: // Are we done yet? Chris@76: if (isset($test['substeps'])) Chris@76: { Chris@76: $_GET['substep'] += $step_size; Chris@76: // Not done? Chris@76: if ($_GET['substep'] <= $step_max) Chris@76: { Chris@76: pauseRepairProcess($to_fix, $error_type, $step_max); Chris@76: } Chris@76: else Chris@76: $done = true; Chris@76: } Chris@76: else Chris@76: $done = true; Chris@76: Chris@76: // Don't allow more than 1000 queries at a time. Chris@76: if ($total_queries >= 1000) Chris@76: pauseRepairProcess($to_fix, $error_type, $step_max, true); Chris@76: } Chris@76: Chris@76: // Keep going. Chris@76: $_GET['step']++; Chris@76: $_GET['substep'] = 0; Chris@76: Chris@76: $to_fix = array_unique($to_fix); Chris@76: Chris@76: // If we're doing fixes and this needed a fix and we're all done then don't do it again. Chris@76: if ($do_fix) Chris@76: { Chris@76: $key = array_search($error_type, $to_fix); Chris@76: if ($key !== false && isset($to_fix[$key])) Chris@76: unset($to_fix[$key]); Chris@76: } Chris@76: Chris@76: // Are we done? Chris@76: pauseRepairProcess($to_fix, $error_type); Chris@76: } Chris@76: Chris@76: // Restore the cache. Chris@76: $db_cache = $db_temp_cache; Chris@76: Chris@76: return $to_fix; Chris@76: } Chris@76: Chris@76: // Create a salvage area for repair purposes. Chris@76: function createSalvageArea() Chris@76: { Chris@76: global $txt, $language, $salvageBoardID, $salvageCatID, $smcFunc; Chris@76: static $createOnce = false; Chris@76: Chris@76: // Have we already created it? Chris@76: if ($createOnce) Chris@76: return; Chris@76: else Chris@76: $createOnce = true; Chris@76: Chris@76: // Back to the forum's default language. Chris@76: loadLanguage('Admin', $language); Chris@76: Chris@76: // Check to see if a 'Salvage Category' exists, if not => insert one. Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT id_cat Chris@76: FROM {db_prefix}categories Chris@76: WHERE name = {string:cat_name} Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'cat_name' => $txt['salvaged_category_name'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($result) != 0) Chris@76: list ($salvageCatID) = $smcFunc['db_fetch_row']($result); Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: if (empty($salveageCatID)) Chris@76: { Chris@76: $smcFunc['db_insert']('', Chris@76: '{db_prefix}categories', Chris@76: array('name' => 'string-255', 'cat_order' => 'int'), Chris@76: array($txt['salvaged_category_name'], -1), Chris@76: array('id_cat') Chris@76: ); Chris@76: Chris@76: if ($smcFunc['db_affected_rows']() <= 0) Chris@76: { Chris@76: loadLanguage('Admin'); Chris@76: fatal_lang_error('salvaged_category_error', false); Chris@76: } Chris@76: Chris@76: $salvageCatID = $smcFunc['db_insert_id']('{db_prefix}categories', 'id_cat'); Chris@76: } Chris@76: Chris@76: // Check to see if a 'Salvage Board' exists, if not => insert one. Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT id_board Chris@76: FROM {db_prefix}boards Chris@76: WHERE id_cat = {int:id_cat} Chris@76: AND name = {string:board_name} Chris@76: LIMIT 1', Chris@76: array( Chris@76: 'id_cat' => $salvageCatID, Chris@76: 'board_name' => $txt['salvaged_board_name'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_num_rows']($result) != 0) Chris@76: list ($salvageBoardID) = $smcFunc['db_fetch_row']($result); Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: if (empty($salvageBoardID)) Chris@76: { Chris@76: $smcFunc['db_insert']('', Chris@76: '{db_prefix}boards', Chris@76: array('name' => 'string-255', 'description' => 'string-255', 'id_cat' => 'int', 'member_groups' => 'string', 'board_order' => 'int', 'redirect' => 'string'), Chris@76: array($txt['salvaged_board_name'], $txt['salvaged_board_description'], $salvageCatID, '1', -1, ''), Chris@76: array('id_board') Chris@76: ); Chris@76: Chris@76: if ($smcFunc['db_affected_rows']() <= 0) Chris@76: { Chris@76: loadLanguage('Admin'); Chris@76: fatal_lang_error('salvaged_board_error', false); Chris@76: } Chris@76: Chris@76: $salvageBoardID = $smcFunc['db_insert_id']('{db_prefix}boards', 'id_board'); Chris@76: } Chris@76: Chris@76: $smcFunc['db_query']('alter_table_boards', ' Chris@76: ALTER TABLE {db_prefix}boards Chris@76: ORDER BY board_order', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Restore the user's language. Chris@76: loadLanguage('Admin'); Chris@76: } Chris@76: Chris@76: ?>