'EditSearchSettings', 'weights' => 'EditWeights', 'method' => 'EditSearchMethod', 'createfulltext' => 'EditSearchMethod', 'removecustom' => 'EditSearchMethod', 'removefulltext' => 'EditSearchMethod', 'createmsgindex' => 'CreateMessageIndex', ); // Default the sub-action to 'edit search settings'. $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'settings'; $context['sub_action'] = $_REQUEST['sa']; // Create the tabs for the template. $context['admin_tabs'] = array( 'title' => &$txt['manage_search'], 'help' => 'search', 'description' => $txt['search_settings_desc'], 'tabs' => array( 'weights' => array( 'title' => $txt['search_weights'], 'description' => $txt['search_weights_desc'], 'href' => $scripturl . '?action=managesearch;sa=weights', ), 'method' => array( 'title' => $txt['search_method'], 'description' => $txt['search_method_desc'], 'href' => $scripturl . '?action=managesearch;sa=method', ), 'settings' => array( 'title' => $txt['settings'], 'description' => $txt['search_settings_desc'], 'href' => $scripturl . '?action=managesearch;sa=settings', 'is_last' => true, ), ), ); // Make sure the tab they are using has is_selected set. if (isset($context['admin_tabs']['tabs'][$_REQUEST['sa']])) $context['admin_tabs']['tabs'][$_REQUEST['sa']]['is_selected'] = true; // Call the right function for this sub-acton. $subActions[$_REQUEST['sa']](); } function EditSearchSettings() { global $txt, $context, $sourcedir; $context['page_title'] = $txt['search_settings_title']; $context['sub_template'] = 'modify_settings'; // Including a file needed for inline permissions. require_once($sourcedir . '/ManagePermissions.php'); // A form was submitted. if (isset($_POST['save'])) { checkSession(); updateSettings(array( 'simpleSearch' => isset($_POST['simpleSearch']) ? '1' : '0', 'search_results_per_page' => (int) $_POST['search_results_per_page'], 'search_max_results' => (int) $_POST['search_max_results'], )); // Save the permissions. save_inline_permissions(array('search_posts')); } // Initialize permissions. init_inline_permissions(array('search_posts')); } function EditWeights() { global $txt, $context, $modSettings; $context['page_title'] = $txt['search_weights_title']; $context['sub_template'] = 'modify_weights'; $factors = array( 'search_weight_frequency', 'search_weight_age', 'search_weight_length', 'search_weight_subject', 'search_weight_first_message', 'search_weight_sticky', ); // A form was submitted. if (isset($_POST['save'])) { checkSession(); $changes = array(); foreach ($factors as $factor) $changes[$factor] = (int) $_POST[$factor]; updateSettings($changes); } $context['relative_weights'] = array('total' => 0); foreach ($factors as $factor) $context['relative_weights']['total'] += isset($modSettings[$factor]) ? $modSettings[$factor] : 0; foreach ($factors as $factor) $context['relative_weights'][$factor] = round(100 * (isset($modSettings[$factor]) ? $modSettings[$factor] : 0) / $context['relative_weights']['total'], 1); } function EditSearchMethod() { global $txt, $context, $modSettings, $db_prefix; $context['admin_tabs']['tabs']['method']['is_selected'] = true; $context['page_title'] = $txt['search_method_title']; $context['sub_template'] = 'select_search_method'; // Detect whether a fulltext index is set. $request = db_query(" SHOW INDEX FROM {$db_prefix}messages", false, false); $context['fulltext_index'] = ''; if ($request !== false || mysql_num_rows($request) != 0) { while ($row = mysql_fetch_assoc($request)) if ($row['Column_name'] == 'body' && (isset($row['Index_type']) && $row['Index_type'] == 'FULLTEXT' || isset($row['Comment']) && $row['Comment'] == 'FULLTEXT')) $context['fulltext_index'][] = $row['Key_name']; mysql_free_result($request); if (is_array($context['fulltext_index'])) $context['fulltext_index'] = array_unique($context['fulltext_index']); } $request = db_query(" SHOW COLUMNS FROM {$db_prefix}messages", false, false); if ($request !== false) { while ($row = mysql_fetch_assoc($request)) if ($row['Field'] == 'body' && $row['Type'] == 'mediumtext') $context['cannot_create_fulltext'] = true; mysql_free_result($request); } if (preg_match('~^`(.+?)`\.(.+?)$~', $db_prefix, $match) !== 0) $request = db_query(" SHOW TABLE STATUS FROM `" . strtr($match[1], array('`' => '')) . "` LIKE '" . str_replace('_', '\_', $match[2]) . "messages'", false, false); else $request = db_query(" SHOW TABLE STATUS LIKE '" . str_replace('_', '\_', $db_prefix) . "messages'", false, false); if ($request !== false) { while ($row = mysql_fetch_assoc($request)) if ((isset($row['Type']) && strtolower($row['Type']) != 'myisam') || (isset($row['Engine']) && strtolower($row['Engine']) != 'myisam')) $context['cannot_create_fulltext'] = true; mysql_free_result($request); } if (!empty($_REQUEST['sa']) && $_REQUEST['sa'] == 'createfulltext') { checkSession('get'); // Make sure it's gone before creating it. db_query(" ALTER TABLE {$db_prefix}messages DROP INDEX body", false, false); db_query(" ALTER TABLE {$db_prefix}messages ADD FULLTEXT body (body)", __FILE__, __LINE__); $context['fulltext_index'] = 'body'; } elseif (!empty($_REQUEST['sa']) && $_REQUEST['sa'] == 'removefulltext' && !empty($context['fulltext_index'])) { checkSession('get'); db_query(" ALTER TABLE {$db_prefix}messages DROP INDEX " . implode(', DROP INDEX ', $context['fulltext_index']), __FILE__, __LINE__); $context['fulltext_index'] = ''; // Go back to the default search method. if (!empty($modSettings['search_index']) && $modSettings['search_index'] == 'fulltext') updateSettings(array( 'search_index' => '', )); } elseif (!empty($_REQUEST['sa']) && $_REQUEST['sa'] == 'removecustom') { checkSession('get'); db_query(" DROP TABLE IF EXISTS {$db_prefix}log_search_words", __FILE__, __LINE__); updateSettings(array( 'search_custom_index_config' => '', )); // Go back to the default search method. if (!empty($modSettings['search_index']) && $modSettings['search_index'] == 'custom') updateSettings(array( 'search_index' => '', )); } elseif (isset($_POST['save'])) { checkSession(); updateSettings(array( 'search_index' => empty($_POST['search_index']) || !in_array($_POST['search_index'], array('fulltext', 'custom')) ? '' : $_POST['search_index'], 'search_force_index' => isset($_POST['search_force_index']) ? '1' : '0', 'search_match_words' => isset($_POST['search_match_words']) ? '1' : '0', )); } $context['table_info'] = array( 'data_length' => 0, 'index_length' => 0, 'fulltext_length' => 0, 'custom_index_length' => 0, ); // Get some info about the messages table, to show its size and index size. if (preg_match('~^`(.+?)`\.(.+?)$~', $db_prefix, $match) != 0) $request = db_query(" SHOW TABLE STATUS FROM `" . strtr($match[1], array('`' => '')) . "` LIKE '" . str_replace('_', '\_', $match[2]) . "messages'", false, false); else $request = db_query(" SHOW TABLE STATUS LIKE '" . str_replace('_', '\_', $db_prefix) . "messages'", false, false); if ($request !== false && mysql_num_rows($request) == 1) { // Only do this if the user has permission to execute this query. $row = mysql_fetch_assoc($request); $context['table_info']['data_length'] = $row['Data_length']; $context['table_info']['index_length'] = $row['Index_length']; $context['table_info']['fulltext_length'] = $row['Index_length']; mysql_free_result($request); } // Now check the custom index table, if it exists at all. if (preg_match('~^`(.+?)`\.(.+?)$~', $db_prefix, $match) !== 0) $request = db_query(" SHOW TABLE STATUS FROM `" . strtr($match[1], array('`' => '')) . "` LIKE '" . str_replace('_', '\_', $match[2]) . "log_search_words'", false, false); else $request = db_query(" SHOW TABLE STATUS LIKE '" . str_replace('_', '\_', $db_prefix) . "log_search_words'", false, false); if ($request !== false && mysql_num_rows($request) == 1) { // Only do this if the user has permission to execute this query. $row = mysql_fetch_assoc($request); $context['table_info']['index_length'] += $row['Data_length'] + $row['Index_length']; $context['table_info']['custom_index_length'] = $row['Data_length'] + $row['Index_length']; mysql_free_result($request); } // Format the data and index length in kilobytes. foreach ($context['table_info'] as $type => $size) $context['table_info'][$type] = comma_format($context['table_info'][$type] / 1024); $context['custom_index'] = !empty($modSettings['search_custom_index_config']); $context['partial_custom_index'] = !empty($modSettings['search_custom_index_resume']) && empty($modSettings['search_custom_index_config']); $context['double_index'] = !empty($context['fulltext_index']) && $context['custom_index']; } function CreateMessageIndex() { global $modSettings, $context, $db_prefix; $context['admin_tabs']['tabs']['method']['is_selected'] = true; $messages_per_batch = 100; $index_properties = array( 2 => array( 'column_definition' => 'smallint(5)', ), 4 => array( 'column_definition' => 'mediumint(8)', 'step_size' => 1000000, 'max_size' => 16777215, ), 5 => array( 'column_definition' => 'int(10)', 'step_size' => 100000000, 'max_size' => 4294967295, ), ); if (isset($_REQUEST['resume']) && !empty($modSettings['search_custom_index_resume'])) { $context['index_settings'] = unserialize($modSettings['search_custom_index_resume']); $context['start'] = (int) $context['index_settings']['resume_at']; unset($context['index_settings']['resume_at']); $context['step'] = 1; } else { $context['index_settings'] = array( 'bytes_per_word' => isset($_REQUEST['bytes_per_word']) && isset($index_properties[$_REQUEST['bytes_per_word']]) ? (int) $_REQUEST['bytes_per_word'] : 2, ); $context['start'] = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0; $context['step'] = isset($_REQUEST['step']) ? (int) $_REQUEST['step'] : 0; } if ($context['step'] !== 0) checkSession('request'); // Step 0: let the user determine how they like their index. if ($context['step'] === 0) { $context['sub_template'] = 'create_index'; } // Step 1: insert all the words. if ($context['step'] === 1) { $context['sub_template'] = 'create_index_progress'; if ($context['start'] === 0) { db_query(" DROP TABLE IF EXISTS {$db_prefix}log_search_words", __FILE__, __LINE__); db_query(" CREATE TABLE {$db_prefix}log_search_words ( ID_WORD " . $index_properties[$context['index_settings']['bytes_per_word']]['column_definition'] . " unsigned NOT NULL default '0', ID_MSG int(10) unsigned NOT NULL default '0', PRIMARY KEY (ID_WORD, ID_MSG) ) TYPE=MyISAM", __FILE__, __LINE__); // Temporarily switch back to not using a search index. if (!empty($modSettings['search_index']) && $modSettings['search_index'] == 'custom') updateSettings(array('search_index' => '')); // Don't let simultanious processes be updating the search index. if (!empty($modSettings['search_custom_index_config'])) updateSettings(array('search_custom_index_config' => '')); } $num_messages = array( 'done' => 0, 'todo' => 0, ); $request = db_query(" SELECT ID_MSG >= $context[start] AS todo, COUNT(*) AS numMesages FROM {$db_prefix}messages GROUP BY todo", __FILE__, __LINE__); while ($row = mysql_fetch_assoc($request)) $num_messages[empty($row['todo']) ? 'done' : 'todo'] = $row['numMesages']; if (empty($num_messages['todo'])) { $context['step'] = 2; $context['percentage'] = 80; $context['start'] = 0; } else { // Number of seconds before the next step. $stop = time() + 3; while (time() < $stop) { $inserts = ''; $request = db_query(" SELECT ID_MSG, body FROM {$db_prefix}messages WHERE ID_MSG BETWEEN $context[start] AND " . ($context['start'] + $messages_per_batch - 1) . " LIMIT $messages_per_batch", __FILE__, __LINE__); while ($row = mysql_fetch_assoc($request)) foreach (text2words($row['body'], $context['index_settings']['bytes_per_word'], true) as $ID_WORD) $inserts .= "($ID_WORD, $row[ID_MSG]),\n"; $num_messages['done'] += mysql_num_rows($request); $num_messages['todo'] -= mysql_num_rows($request); mysql_free_result($request); $context['start'] += $messages_per_batch; if (!empty($inserts)) db_query(" INSERT IGNORE INTO {$db_prefix}log_search_words (ID_WORD, ID_MSG) VALUES " . substr($inserts, 0, -2), __FILE__, __LINE__); if ($num_messages['todo'] === 0) { $context['step'] = 2; $context['start'] = 0; break; } else updateSettings(array('search_custom_index_resume' => serialize(array_merge($context['index_settings'], array('resume_at' => $context['start']))))); } // Since there are still two steps to go, 90% is the maximum here. $context['percentage'] = round($num_messages['done'] / ($num_messages['done'] + $num_messages['todo']), 3) * 80; } } // Step 2: removing the words that occur too often and are of no use. elseif ($context['step'] === 2) { if ($context['index_settings']['bytes_per_word'] < 4) $context['step'] = 3; else { $stop_words = $context['start'] === 0 || empty($modSettings['search_stopwords']) ? array() : explode(',', $modSettings['search_stopwords']); $stop = time() + 3; $context['sub_template'] = 'create_index_progress'; $maxMessages = ceil(60 * $modSettings['totalMessages'] / 100); while (time() < $stop) { $request = db_query(" SELECT ID_WORD, count(ID_WORD) AS numWords FROM {$db_prefix}log_search_words WHERE ID_WORD BETWEEN $context[start] AND " . ($context['start'] + $index_properties[$context['index_settings']['bytes_per_word']]['step_size'] - 1) . " GROUP BY ID_WORD HAVING numWords > $maxMessages", __FILE__, __LINE__); while ($row = mysql_fetch_assoc($request)) $stop_words[] = $row['ID_WORD']; mysql_free_result($request); updateSettings(array('search_stopwords' => implode(',', $stop_words))); if (!empty($stop_words)) db_query(" DELETE FROM {$db_prefix}log_search_words WHERE ID_WORD in (" . implode(', ', $stop_words) . ')', __FILE__, __LINE__); $context['start'] += $index_properties[$context['index_settings']['bytes_per_word']]['step_size']; if ($context['start'] > $index_properties[$context['index_settings']['bytes_per_word']]['max_size']) { $context['step'] = 3; break; } } $context['percentage'] = 80 + round($context['start'] / $index_properties[$context['index_settings']['bytes_per_word']]['max_size'], 3) * 20; } } // Step 3: remove words not distinctive enough. if ($context['step'] === 3) { $context['sub_template'] = 'create_index_done'; updateSettings(array('search_index' => 'custom', 'search_custom_index_config' => serialize($context['index_settings']))); db_query(" DELETE FROM {$db_prefix}settings WHERE variable = 'search_custom_index_resume'", __FILE__, __LINE__); } } ?>