Index: modules/node/content_types.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v retrieving revision 1.50 diff -u -p -r1.50 content_types.inc --- modules/node/content_types.inc 27 Jan 2008 18:03:05 -0000 1.50 +++ modules/node/content_types.inc 4 Apr 2008 00:59:00 -0000 @@ -343,12 +343,27 @@ function node_type_form_submit($form, &$ * Implementation of hook_node_type(). */ function node_node_type($op, $info) { - if ($op != 'delete' && !empty($info->old_type) && $info->old_type != $info->type) { - $update_count = node_type_update_nodes($info->old_type, $info->type); - - if ($update_count) { - drupal_set_message(format_plural($update_count, 'Changed the content type of 1 post from %old-type to %type.', 'Changed the content type of @count posts from %old-type to %type.', array('%old-type' => $info->old_type, '%type' => $info->type))); - } + switch ($op) { + case 'delete': + if (!empty($info->old_type) && $info->old_type != $info->type) { + $update_count = node_type_update_nodes($info->old_type, $info->type); + + if ($update_count) { + drupal_set_message(format_plural($update_count, 'Changed the content type of 1 post from %old-type to %type.', 'Changed the content type of @count posts from %old-type to %type.', array('%old-type' => $info->old_type, '%type' => $info->type))); + } + } + break; + + case 'update': + $excluded_types = variable_get('search_excluded_content_types', array()); + foreach ($excluded_types as $key => $type) { + if ($type == $info->old_type) { + $excluded_types[$key] = $info->type; + break; + } + } + variable_set('search_excluded_content_types', $excluded_types); + break; } } Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.953 diff -u -p -r1.953 node.module --- modules/node/node.module 1 Apr 2008 19:45:21 -0000 1.953 +++ modules/node/node.module 4 Apr 2008 00:59:01 -0000 @@ -1151,8 +1151,18 @@ function node_search($op = 'search', $ke return; case 'status': - $total = db_result(db_query('SELECT COUNT(*) FROM {node} WHERE status = 1')); - $remaining = db_result(db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")); + $excluded_types = variable_get('search_excluded_content_types', array()); + + $type_exclude = ''; + $args = array(); + if (!empty($excluded_types)) { + $type_exclude = 'n.type NOT IN('. implode(',', array_fill(0, count($excluded_types), "'%s'")) .') AND '; + $args = array_values($excluded_types); + } + + $total = db_result(db_query("SELECT COUNT(*) FROM {node} n WHERE $type_exclude n.status = 1")); + $remaining = db_result(db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE $type_exclude n.status = 1 AND d.sid IS NULL OR d.reindex <> 0", $args)); + return array('remaining' => $remaining, 'total' => $total); case 'admin': @@ -1296,6 +1306,46 @@ function node_search($op = 'search', $ke } /** + * Validate handler for search_admin_settings - added through hook_form_alter. + */ +function node_search_admin_settings_validate($form, &$form_state) { + // What we actually store is the list of excluded content types. + $included_types = $form_state['values']['search_indexed_content_types']; + $excluded_types = drupal_map_assoc(array_diff(array_keys(node_get_types('names')), $included_types)); + unset($form_state['values']['search_indexed_content_types']); + $form_state['values']['search_excluded_content_types'] = $excluded_types; + + // Store the current value of the variable before system_theme_settings_submit + // updates it. + $form_state['form']['prev_search_excluded_content_types'] = variable_get('search_excluded_content_types', array()); +} + +/** + * Submit handler for search_admin_settings - added through hook_form_alter. + * Gets executed after system_theme_settings_submit has updated the variables. + */ +function node_search_admin_settings_submit($form, &$form_state) { + $new_excluded_types = variable_get('search_excluded_content_types', array()); + $old_excluded_types = $form_state['form']['prev_search_excluded_content_types']; + + // Wipe indexed data for the newly excluded content types + $newly_excluded = array_diff($new_excluded_types, $old_excluded_types); + if (!empty($newly_excluded)) { + $result = db_query('SELECT nid FROM {node} WHERE type IN('. implode(',', array_fill(0, count($newly_excluded), "'%s'")) .')', $newly_excluded); + while ($row = db_fetch_array($result)) { + search_wipe($row['nid'], 'node'); + } + } + + // If some content types were re-included, the whole index will need to be rebuilt. + $newly_included = array_diff($old_excluded_types, $new_excluded_types); + if (!empty($newly_included)) { + drupal_set_message(t('The index will be rebuilt.')); + search_wipe(); + } +} + +/** * Implementation of hook_user(). */ function node_user($op, &$edit, &$user) { @@ -1764,12 +1814,19 @@ function node_page_view($node, $cid = NU */ function node_update_index() { $limit = (int)variable_get('search_cron_limit', 100); + $excluded_types = variable_get('search_excluded_content_types', array()); // Store the maximum possible comments per thread (used for ranking by reply count) variable_set('node_cron_comments_scale', 1.0 / max(1, db_result(db_query('SELECT MAX(comment_count) FROM {node_comment_statistics}')))); variable_set('node_cron_views_scale', 1.0 / max(1, db_result(db_query('SELECT MAX(totalcount) FROM {node_counter}')))); - $result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit); + $type_exclude = ''; + $args = array(); + if (!empty($excluded_types)) { + $type_exclude = 'n.type NOT IN('. implode(',', array_fill(0, count($excluded_types), "'%s'")) .') AND '; + $args = array_values($excluded_types); + } + $result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE $type_exclude d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", $args, 0, $limit); while ($node = db_fetch_object($result)) { _node_index_node($node); @@ -1857,6 +1914,9 @@ function node_form_alter(&$form, $form_s // Node types: $types = array_map('check_plain', node_get_types('names')); + foreach (variable_get('search_excluded_content_types', array()) as $excluded_type) { + unset($types[$excluded_type]); + } $form['advanced']['type'] = array( '#type' => 'checkboxes', '#title' => t('Only of the type(s)'), @@ -1873,6 +1933,49 @@ function node_form_alter(&$form, $form_s $form['#validate'][] = 'node_search_validate'; } + // Search settings form + elseif ($form_id == 'search_admin_settings') { + $form['content_indexing'] = array('#type' => 'fieldset', '#title' => t('Content indexing settings')); + $form['content_indexing']['info'] = array('#value' => ''. t('Changing the settings below can cause the site index to be rebuilt.') .''); + + // Content indexing is opt-out : the actual setting is a list of + // excluded content types, so that newly added content types are + // indexed by default. + // However, to keep the UI simple, we let the user select the content + // types that should be indexed, and store the complement. + $excluded_types = variable_get('search_excluded_content_types', array()); + $included_types = drupal_map_assoc(array_diff(array_keys(node_get_types('names')), $excluded_types)); + $form['content_indexing']['search_indexed_content_types'] = array( + '#type' => 'checkboxes', + '#multiple' => TRUE, + '#title' => t('Indexed content types'), + '#options' => node_get_types('names'), + '#default_value' => $included_types, + '#description' => t('Unselect a content type to have it excluded from search results.
Excluding a content type will wipe the search index from the corresponding data.
Re-including a content type will cause the whole site index to be rebuilt.'), + ); + + // Output form for defining rank factor weights. + $form['content_ranking'] = array('#type' => 'fieldset', '#title' => t('Content ranking')); + $form['content_ranking']['#theme'] = 'node_search_admin'; + $form['content_ranking']['info'] = array('#value' => ''. t('The following numbers control which properties the content search should favor when ordering the results. Higher numbers mean more influence, zero means the property is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') .''); + + $ranking = array('node_rank_relevance' => t('Keyword relevance'), + 'node_rank_recent' => t('Recently posted')); + if (module_exists('comment')) { + $ranking['node_rank_comments'] = t('Number of comments'); + } + if (module_exists('statistics') && variable_get('statistics_count_content_views', 0)) { + $ranking['node_rank_views'] = t('Number of views'); + } + + // Note: reversed to reflect that higher number = higher ranking. + $options = drupal_map_assoc(range(0, 10)); + foreach ($ranking as $var => $title) { + $form['content_ranking']['factors'][$var] = array('#title' => $title, '#type' => 'select', '#options' => $options, '#default_value' => variable_get($var, 5)); + } + $form['#validate'][] = 'node_search_admin_settings_validate'; + $form['#submit'][] = 'node_search_admin_settings_submit'; + } } /** Index: modules/search/search.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/search/search.admin.inc,v retrieving revision 1.4 diff -u -p -r1.4 search.admin.inc --- modules/search/search.admin.inc 8 Jan 2008 10:35:42 -0000 1.4 +++ modules/search/search.admin.inc 4 Apr 2008 00:59:01 -0000 @@ -62,15 +62,18 @@ function search_admin_settings() { $form['indexing_settings']['minimum_word_size'] = array('#type' => 'textfield', '#title' => t('Minimum word length to index'), '#default_value' => variable_get('minimum_word_size', 3), '#size' => 5, '#maxlength' => 3, '#description' => t('The number of characters a word has to be to be indexed. A lower setting means better search result ranking, but also a larger database. Each search query must contain at least one keyword that is this size (or longer).')); $form['indexing_settings']['overlap_cjk'] = array('#type' => 'checkbox', '#title' => t('Simple CJK handling'), '#default_value' => variable_get('overlap_cjk', TRUE), '#description' => t('Whether to apply a simple Chinese/Japanese/Korean tokenizer based on overlapping sequences. Turn this off if you want to use an external preprocessor for this instead. Does not affect other languages.')); - $form['#validate'] = array('search_admin_settings_validate'); + $form['#validate'][] = 'search_admin_settings_validate'; + $form = system_settings_form($form); // Per module settings $form = array_merge($form, module_invoke_all('search', 'admin')); - return system_settings_form($form); + $form['#submit'][] = 'search_admin_settings_submit'; + + return $form; } /** - * Validate callback. + * Validate handler handler for search_admin_settings. */ function search_admin_settings_validate($form, &$form_state) { if ($form_state['values']['op'] == t('Re-index site')) {