### Eclipse Workspace Patch 1.0
#P Test Drupal 6
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.832
diff -u -r1.832 node.module
--- modules/node/node.module	17 Jun 2007 14:37:33 -0000	1.832
+++ modules/node/node.module	17 Jun 2007 17:02:00 -0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: node.module,v 1.832 2007/06/17 14:37:33 goba Exp $
+// $Id: node.module,v 1.831 2007/06/15 22:00:30 dries Exp $
 
 /**
  * @file
@@ -870,12 +870,40 @@
     case 'status':
       $last = variable_get('node_cron_last', 0);
       $last_nid = variable_get('node_cron_last_nid', 0);
-      $total = db_result(db_query('SELECT COUNT(*) FROM {node} WHERE status = 1'));
-      $remaining = db_result(db_query('SELECT COUNT(*) FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND ((GREATEST(n.created, n.changed, c.last_comment_timestamp) = %d AND n.nid > %d ) OR (n.created > %d OR n.changed > %d OR c.last_comment_timestamp > %d))', $last, $last_nid, $last, $last, $last));
+      $excluded_types = variable_get('search_excluded_content_types', array());
+
+      $args = array($last, $last_nid, $last, $last, $last);
+      $type_exclude = '';
+      if (!empty($excluded_types)) {
+        $type_exclude = 'n.type NOT IN('. implode(',', array_fill(0, count($excluded_types), "'%s'")) .') AND ';
+        $args = array_merge(array_values($excluded_types), $args);
+      }
+      $total = db_result(db_query("SELECT COUNT(*) FROM {node} n WHERE $type_exclude n.status = 1", $excluded_types));
+      $remaining = db_result(db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE $type_exclude n.status = 1 AND ((GREATEST(n.created, n.changed, c.last_comment_timestamp) = %d AND n.nid > %d ) OR (n.created > %d OR n.changed > %d OR c.last_comment_timestamp > %d))", $args));
+
       return array('remaining' => $remaining, 'total' => $total);
 
     case 'admin':
       $form = array();
+      $form['content_indexing'] = array('#type' => 'fieldset', '#title' => t('Content indexing settings'));
+      $form['content_indexing']['info'] = array('#value' => '<em>'. t('Changing the settings below can cause the site index to be rebuilt.') .'</em>');
+
+      // 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' => 'select',
+        '#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.<br/>Excluding a content type will wipe the search index from the corresponding data.<br/>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';
@@ -895,6 +923,7 @@
       foreach ($ranking as $var => $title) {
         $form['content_ranking']['factors'][$var] = array('#title' => $title, '#type' => 'select', '#options' => $options, '#default_value' => variable_get($var, 5));
       }
+
       return $form;
 
     case 'search':
@@ -1002,6 +1031,35 @@
 }
 
 /**
+ * Validate handler for search_admin_settings - added through hook_form_alter.
+ */
+function node_search_admin_settings_validate($form, &$form_state) {
+  $included_types = $form_state['values']['search_indexed_content_types'];
+  $new_excluded_types = drupal_map_assoc(array_diff(array_keys(node_get_types('names')), $included_types));
+  $old_excluded_types = variable_get('search_excluded_content_types', array());
+
+  // 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();
+  }
+
+  // What we actually store is the list of excluded content types.
+  unset($form_state['values']['search_indexed_content_types']);
+  $form_state['values']['search_excluded_content_types'] = $new_excluded_types;
+}
+
+/**
  * Implementation of hook_user().
  */
 function node_user($op, &$edit, &$user) {
@@ -1383,7 +1441,7 @@
   }
 
   $filters['type'] = array('title' => t('type'), 'options' => node_get_types('names'));
-  
+
   // The taxonomy filter
   if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
     $filters['category'] = array('title' => t('category'), 'options' => $taxonomy);
@@ -2543,12 +2601,19 @@
   $last = variable_get('node_cron_last', 0);
   $last_nid = variable_get('node_cron_last_nid', 0);
   $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 GREATEST(IF(c.last_comment_timestamp IS NULL, 0, c.last_comment_timestamp), n.changed) as last_change, n.nid FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND ((GREATEST(n.changed, c.last_comment_timestamp) = %d AND n.nid > %d) OR (n.changed > %d OR c.last_comment_timestamp > %d)) ORDER BY GREATEST(n.changed, c.last_comment_timestamp) ASC, n.nid ASC', $last, $last_nid, $last, $last, $last, 0, $limit);
+  $args = array($last, $last_nid, $last, $last, $last);
+  $type_exclude = '';
+  if (!empty($excluded_types)) {
+    $type_exclude = 'n.type NOT IN('. implode(',', array_fill(0, count($excluded_types), "'%s'")) .') AND ';
+    $args = array_merge(array_values($excluded_types), $args);
+  }
+  $result = db_query_range("SELECT GREATEST(IF(c.last_comment_timestamp IS NULL, 0, c.last_comment_timestamp), n.changed) as last_change, n.nid FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE $type_exclude n.status = 1 AND ((GREATEST(n.changed, c.last_comment_timestamp) = %d AND n.nid > %d) OR (n.changed > %d OR c.last_comment_timestamp > %d)) ORDER BY GREATEST(n.changed, c.last_comment_timestamp) ASC, n.nid ASC", $args, 0, $limit);
 
   while ($node = db_fetch_object($result)) {
     $last_change = $node->last_change;
@@ -2624,6 +2689,9 @@
 
     // Node types:
     $types = 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)'),
@@ -2640,6 +2708,10 @@
 
     $form['#validate'][] = 'node_search_validate';
   }
+  // Search settings form
+  elseif ($form_id == 'search_admin_settings') {
+    $form['#validate'][] = 'node_search_admin_settings_validate';
+  }
 }
 
 /**
