Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1334
diff -u -r1.1334 node.module
--- modules/node/node.module	30 Dec 2010 03:47:36 -0000	1.1334
+++ modules/node/node.module	2 Jan 2011 01:55:08 -0000
@@ -1646,6 +1646,10 @@
   // Insert special keywords.
   $query->setOption('type', 'n.type');
   $query->setOption('language', 'n.language');
+  // Note: there is currently no UI in node.module's advanced search form
+  // for taxonomy terms, but this code here handles the processing of
+  // taxonomy term filtering, in case another module added taxonomy to
+  // the advanced search form.
   if ($query->setOption('term', 'ti.tid')) {
     $query->join('taxonomy_index', 'ti', 'n.nid = ti.nid');
   }
@@ -2642,12 +2646,67 @@
  */
 function node_form_search_form_alter(&$form, $form_state) {
   if (isset($form['module']) && $form['module']['#value'] == 'node' && user_access('use advanced search')) {
+    // Extract the current values of the special search fields from the previous
+    // search keys. See node_search_validate(), which puts these into $keys.
+    $keys = $form['basic']['keys']['#default_value'];
+    $types_value = explode(',', search_expression_extract($keys, 'type'));
+    $keys = search_expression_insert($keys, 'type');
+    $languages_value = explode(',', search_expression_extract($keys, 'language'));
+    $keys = search_expression_insert($keys, 'language');
+    // Note: No need to do taxonomy terms, since node.module doesn't provide
+    // this field in the advanced search form.
+
+    // At this point, we have in $keys the basic query, possibly with OR and
+    // not (-word) and maybe a phrase in it. We can attempt to pick these out,
+    // in case they came from the Advanced Search form.
+
+    // First, pick out negative keywords and phrases.
+    $matches = array();
+    $negative = '';
+    $keys = ' ' . $keys;
+    $word_phrase = '("[^"]+"|[^" ]+)';
+    $pattern = "/ -$word_phrase/";
+    if (preg_match_all($pattern, $keys, $matches)) {
+      $negative = implode(' ', $matches[1]);
+      $keys = preg_replace($pattern, '', $keys);
+    }
+
+    // Next, if there is a single phrase, pick that out. If there are multiple
+    // phrases, then they were not created via the advanced search form,
+    // so don't bother.
+    $phrase = '';
+    $pattern = '/ ("[^"]+")/';
+    if (preg_match_all($pattern, $keys, $matches) == 1) {
+      $phrase = trim($matches[1][0], '"');
+      $keys = preg_replace($pattern, '', $keys);
+    }
+
+    // Finally, if there is a single set of OR-separated words/phrases, pick
+    // them off. Again, if there is more than one set, don't bother. The way
+    // this works is that if you have abc def ghi OR jkl OR mno, then keywords
+    // abc and def are required, and (ghi, jkl, mno) form a set of OR words
+    // (one of the three must be there). This logic is in
+    // SearchQuery::parseSearchExpression().
+    $pattern = "/( $word_phrase OR)+ $word_phrase/";
+    $or = '';
+    if (preg_match_all($pattern, $keys, $matches) == 1) {
+      $or = trim(str_replace(' OR', '', $matches[0][0]));
+      $keys = preg_replace($pattern, '', $keys);
+    }
+
+    // Put anything remaining in the keywords back into the main box, and
+    // if it has been altered, expand the advanced search box so users can
+    // see this part of the form with their query information in it.
+    $keys = trim($keys);
+    $collapse = (trim($form['basic']['keys']['#default_value']) == $keys);
+    $form['basic']['keys']['#default_value'] = $keys;
+
     // Keyword boxes:
     $form['advanced'] = array(
       '#type' => 'fieldset',
       '#title' => t('Advanced search'),
       '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
+      '#collapsed' => $collapse,
       '#attributes' => array('class' => array('search-advanced')),
     );
     $form['advanced']['keywords'] = array(
@@ -2659,18 +2718,21 @@
       '#title' => t('Containing any of the words'),
       '#size' => 30,
       '#maxlength' => 255,
+      '#default_value' => $or,
     );
     $form['advanced']['keywords']['phrase'] = array(
       '#type' => 'textfield',
       '#title' => t('Containing the phrase'),
       '#size' => 30,
       '#maxlength' => 255,
+      '#default_value' => $phrase,
     );
     $form['advanced']['keywords']['negative'] = array(
       '#type' => 'textfield',
       '#title' => t('Containing none of the words'),
       '#size' => 30,
       '#maxlength' => 255,
+      '#default_value' => $negative,
     );
 
     // Node types:
@@ -2681,6 +2743,7 @@
       '#prefix' => '<div class="criterion">',
       '#suffix' => '</div>',
       '#options' => $types,
+      '#default_value' => $types_value,
     );
     $form['advanced']['submit'] = array(
       '#type' => 'submit',
@@ -2704,6 +2767,7 @@
         '#prefix' => '<div class="criterion">',
         '#suffix' => '</div>',
         '#options' => $language_options,
+        '#default_value' => $languages_value,
       );
     }
 
@@ -2728,6 +2792,10 @@
     }
   }
 
+  // Note: there is currently no UI in node.module's advanced search form
+  // for taxonomy terms, but this code here handles the processing of
+  // taxonomy term filtering, in case another module added taxonomy to
+  // the advanced search form.
   if (isset($form_state['values']['term']) && is_array($form_state['values']['term']) && count($form_state['values']['term'])) {
     $keys = search_expression_insert($keys, 'term', implode(',', $form_state['values']['term']));
   }
