Index: modules/nodereference/nodereference.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/modules/nodereference/nodereference.module,v
retrieving revision 1.138.2.25
diff -u -p -r1.138.2.25 nodereference.module
--- modules/nodereference/nodereference.module	23 Aug 2008 00:12:19 -0000	1.138.2.25
+++ modules/nodereference/nodereference.module	25 Aug 2008 20:04:52 -0000
@@ -167,13 +167,14 @@ function nodereference_field_settings($o
 function nodereference_field($op, &$node, $field, &$items, $teaser, $page) {
   switch ($op) {
     case 'validate':
-      $refs = _nodereference_potential_references($field);
       foreach ($items as $delta => $item) {
         if (is_array($item)) {
           $error_element = isset($item['_error_element']) ? $item['_error_element'] : '';
           unset($item['_error_element']);
           if (!empty($item['nid'])) {
-            if (!isset($refs[$item['nid']])) {
+            // Try to lookup the specified nid.
+            $reference = _nodereference_potential_references($field, $item['nid'], 'nid', 'equals', 1);
+            if (count($reference) == 0) {
               form_set_error($error_element, t("%name: this post can't be referenced.", array('%name' => t($field['widget']['label']))));
             }
           }
@@ -583,8 +584,8 @@ function nodereference_autocomplete_vali
     }
     else {
       // No explicit nid.
-      $nids = _nodereference_potential_references($field, $value, TRUE);
-      if (empty($nids)) {
+      $references = _nodereference_potential_references($field, $value, 'title', 'equals', 1);
+      if (empty($references)) {
         form_error($element[$field_key], t('%name: found no valid post with that title.', array('%name' => t($field['widget']['label']))));
       }
       else {
@@ -592,7 +593,7 @@ function nodereference_autocomplete_vali
         // the best thing would be to present the user with an additional form,
         // allowing the user to choose between valid candidates with the same title
         // ATM, we pick the first matching candidate...
-        $nid = array_shift(array_keys($nids));
+        $nid = key($references);
       }
     }
   }
@@ -627,9 +628,13 @@ function nodereference_allowed_values($f
  * @param $field
  *   The field description.
  * @param $string
- *   Optional string to filter titles on (used by autocomplete)
- * @param $exact_string
- *   Optional: should the title filter be an exact match.
+ *   Optional string to filter on (used by autocomplete).
+ * @param $column
+ *   Column of the {node} table to filter on. Defaults to 'title'.
+ * @param $op
+ *   Operator to match filtered string against: equals, starts, or contains.
+ * @param $limit
+ *   If non-zero, limit the size of the result set.
  *
  * @return
  *   An array of valid nodes in the form:
@@ -641,32 +646,34 @@ function nodereference_allowed_values($f
  *     ...
  *   )
  */
-function _nodereference_potential_references($field, $string = '', $exact_string = FALSE) {
+function _nodereference_potential_references($field, $string = '', $column = 'title', $op = 'contains', $limit = NULL) {
   static $results = array();
 
-  if (!isset($results[$field['field_name']][$string][$exact_string])) {
+  // Create unique cache id.
+  $cid = $column .':'. $op .':'. $string .':'. $limit;
+  if (!isset($results[$field['field_name']][$cid])) {
     $references = FALSE;
     if (module_exists('views') && !empty($field['advanced_view']) && $field['advanced_view'] != '--') {
-      $references = _nodereference_potential_references_views($field, $string, $exact_string);
+      $references = _nodereference_potential_references_views($field, $string, $column, $op, $limit);
     }
     // If the view doesn't exist, we got FALSE, and fallback to the regular 'standard mode'.
 
     if ($references === FALSE) {
-      $references = _nodereference_potential_references_standard($field, $string, $exact_string);
+      $references = _nodereference_potential_references_standard($field, $string, $column, $op, $limit);
     }
 
     // Store the results.
-    $results[$field['field_name']][$string][$exact_string] = $references;
+    $results[$field['field_name']][$cid] = $references;
   }
 
-  return $results[$field['field_name']][$string][$exact_string];
+  return $results[$field['field_name']][$cid];
 }
 
 /**
  * Helper function for _nodereference_potential_references():
  * case of Views-defined referenceable nodes.
  */
-function _nodereference_potential_references_views($field, $string = '', $exact_string = FALSE) {
+function _nodereference_potential_references_views($field, $string = '', $column = 'title', $op = 'contains', $limit = NULL) {
   $view_name = $field['advanced_view'];
 
   if ($view = views_get_view($view_name)) {
@@ -697,10 +704,16 @@ function _nodereference_potential_refere
     if (!isset($fields['title'])) {
       $view->add_item($display, 'field', 'node', 'title');
     }
-    if ($string !== '') {
-      // Add an instance of the 'title' filter.
-      $options = array('value' => $string, 'operator' => $exact_string ? '=' : 'contains');
-      $id = $view->add_item($display, 'filter', 'node', 'title', $options);
+
+    if ($string != '') {
+      // Add a filter instance for the requested column.
+      $options = array('value' => $string, 'operator' => ($op == 'equals' ? '=' : $op));
+      $view->add_item($display, 'filter', 'node', $column, $options);
+    }
+
+    // Limit result set size.
+    if ($limit) {
+      $view->set_items_per_page($limit);
     }
 
     // If not set, make all fields inline and define a separator.
@@ -730,7 +743,7 @@ function _nodereference_potential_refere
  * Helper function for _nodereference_potential_references():
  * referenceable nodes defined by content types.
  */
-function _nodereference_potential_references_standard($field, $string = '', $exact_string = FALSE) {
+function _nodereference_potential_references_standard($field, $string = '', $column = 'title', $op = 'contains', $limit = NULL) {
   $related_types = array();
   $args = array();
 
@@ -747,13 +760,26 @@ function _nodereference_potential_refere
     return array();
   }
 
-  if (isset($string)) {
-    $string_clause = $exact_string ? " AND n.title = '%s'" : " AND n.title LIKE '%%%s%'";
-    $related_clause = "(". $related_clause .")". $string_clause;
+  if ($string != '') {
+    // Add filter clause.
+    switch ($op) {
+      case 'equals':
+        $op = "= '%s'";
+        break;
+      case 'starts':
+        $op = "LIKE '%s%%'";
+        break;
+      default:
+        $op = "LIKE '%%%s%%'";
+        break;
+    }
+    $filter_clause = "n.$column $op";
+    $related_clause = "(". $related_clause .") AND ". $filter_clause;
     $args[] = $string;
   }
 
-  $result = db_query(db_rewrite_sql("SELECT n.nid, n.title AS node_title, n.type AS node_type FROM {node} n WHERE ". $related_clause ." ORDER BY n.title, n.type"), $args);
+  $sql = db_rewrite_sql("SELECT n.nid, n.title AS node_title, n.type AS node_type FROM {node} n WHERE ". $related_clause ." ORDER BY n.title, n.type");
+  $result = $limit ? db_query_range($sql, $args, 0, $limit) : db_query($sql, $args);
   $references = array();
   while ($node = db_fetch_object($result)) {
     $references[$node->nid] = array(
@@ -773,7 +799,7 @@ function nodereference_autocomplete($fie
   $field = $fields[$field_name];
   $matches = array();
 
-  $references = _nodereference_potential_references($field, $string);
+  $references = _nodereference_potential_references($field, $string, 'title', 'contains', 10);
   foreach ($references as $id => $row) {
     // Add a class wrapper for a few required CSS overrides.
     $matches[$row['title'] ." [nid:$id]"] = '<div class="reference-autocomplete">'. $row['rendered'] . '</div>';
