Index: includes/handlers.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views/includes/handlers.inc,v
retrieving revision 1.38
diff -u -r1.38 handlers.inc
--- includes/handlers.inc	18 Mar 2008 16:20:37 -0000	1.38
+++ includes/handlers.inc	20 Mar 2008 20:13:50 -0000
@@ -238,12 +238,12 @@
    *   - label: The label to use for this piece.
    */
   function exposed_info() { }
-  
+
  /**
   * Check whether current user has access to this handler.
   *
   * @return boolean
-  */ 
+  */
   function access() {
     return TRUE;
   }
@@ -1183,6 +1183,122 @@
 }
 
 /**
+ * Simple filter to handle like / not like filters
+ */
+class views_handler_filter_like extends views_handler_filter {
+  // exposed filter options
+  var $no_single = TRUE;
+
+  /**
+   * Provide basic defaults for the equality operator
+   */
+  function options(&$options) {
+    parent::options($options);
+    $options['operator'] = '=';
+    $options['value'] = '';
+  }
+
+  function like_options() {
+    return array(
+        '=' => t('Is Equal To'),
+        'contains' => t('Contains'),
+        'word' => t('Contains Any Word'),
+        'allwords' => t('Contains All Words'),
+        'starts' => t('Starts With'),
+        'ends' => t('Ends With'),
+        'not' => t('Does Not Contain'),
+      );
+  }
+
+  /**
+   * Provide simple equality operator
+   */
+  function operator_form(&$form, &$form_state) {
+    $form['operator'] = array(
+      '#type' => 'radios',
+      '#title' => t('Operator'),
+      '#default_value' => $this->operator,
+      '#options' => $this->like_options(),
+    );
+  }
+
+  function admin_summary() {
+    $options = $this->like_options();
+    return (!empty($this->options['exposed']) ? t('exposed<br />') : '') . $options[$this->operator];
+  }
+
+  /**
+   * Provide a simple textfield for equality
+   */
+  function value_form(&$form, &$form_state) {
+    $form['value'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Value'),
+      '#size' => 30,
+      '#default_value' => $this->value,
+    );
+  }
+
+  /**
+   * Add this filter to the query.
+   *
+   * Due to the nature of fapi, the value and the operator have an unintended
+   * level of indirection. You will find them in $this->operator
+   * and $this->value respectively.
+   */
+  function query() {
+    $this->ensure_my_table();
+    $field = "$this->table_alias.$this->real_field";
+
+    switch ($this->operator) {
+      case 'contains':
+        $this->query->add_where($this->options['group'], "UPPER(%s) LIKE UPPER('%%%s%%')", $field, $this->value);
+        break;
+      case 'word':
+      case 'allwords':
+        preg_match_all('/ (-?)("[^"]+"|[^" ]+)/i', ' '. $this->value, $matches, PREG_SET_ORDER);
+        foreach ($matches as $match) {
+          $phrase = false;
+          // Strip off phrase quotes
+          if ($match[2]{0} == '"') {
+            $match[2] = substr($match[2], 1, -1);
+            $phrase = true;
+          }
+          $words = trim($match[2], ',?!();:-');
+          $words = $phrase ? array($words) : preg_split('/ /', $words, -1, PREG_SPLIT_NO_EMPTY);
+          foreach ($words as $word) {
+            $where[] = "UPPER(%s) LIKE UPPER('%%%s%%')";
+            $values[] = $field;
+            $values[] = trim($word, " ,!?");
+          }
+        }
+        if ($this->operator == 'word') {
+          $where = '('. implode(' OR ', $where) .')';
+        }
+        else {
+          $where = implode(' AND ', $where);
+        }
+        // previously this was a call_user_func_array but that's unnecessary
+        // as views will unpack an array that is a single arg.
+        $this->query->add_where($this->options['group'], $where, $values);
+        break;
+      case 'starts':
+        $this->query->add_where($this->options['group'], "UPPER(%s) LIKE UPPER('%s%%')", $field, $this->value);
+        break;
+      case 'ends':
+        $this->query->add_where($this->options['group'], "UPPER(%s) LIKE UPPER('%%%s')", $field, $this->value);
+        break;
+      case 'not':
+        $this->query->add_where($this->options['group'], "UPPER(%s) NOT LIKE UPPER('%%%s%%')", $field, $this->value);
+        break;
+      case '=':
+        $this->query->add_where($this->options['group'], "UPPER(%s) = UPPER('%s')", $field, $this->value);
+        break;
+    }
+  }
+}
+
+/**
  * Simple filter to handle matching of boolean values
  */
 class views_handler_filter_boolean_operator extends views_handler_filter {
Index: modules/node.views.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views/modules/node.views.inc,v
retrieving revision 1.24
diff -u -r1.24 node.views.inc
--- modules/node.views.inc	16 Mar 2008 01:36:34 -0000	1.24
+++ modules/node.views.inc	20 Mar 2008 19:45:43 -0000
@@ -56,6 +56,10 @@
       'handler' => 'views_handler_field_node',
       'click sortable' => TRUE,
      ),
+    // Information for accepting a title as a filter
+    'filter' => array(
+      'handler' => 'views_handler_filter_like',
+    ),
   );
 
   // nid
