Index: content_views.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/content_views.inc,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 content_views.inc
--- content_views.inc	16 Oct 2006 11:33:41 -0000	1.1.2.5
+++ content_views.inc	6 Dec 2006 01:27:07 -0000
@@ -68,6 +68,10 @@
       }
 
       $filters = module_invoke($module, 'field_settings', 'filters', $field);
+      // if no filter defined, we will add our own "empty / not empty")
+      if (empty($filters)) {
+        $filters = array('default' => array());
+      }
       if (is_array($filters) && count($filters)) {
         $table['filters'] = array();
         foreach ($filters as $key => $filter) {
@@ -80,7 +84,31 @@
           $init = array(
             'name' => $name,
             'field' => $main_column['column'],
+            'content_db_info' => $db_info,
+            'content_field' => $field,
+            'content_field_module' => $module,
           );
+
+          // add "empty / not empty" operators to the 'default' filter
+          if ($key == 'default') {
+            $operator = array('EMPTY' => t('Is Empty'), 'NEMPTY' => t('Is Not Empty'));
+            if (!is_array($filter['operator'])) {
+              if (function_exists($filter['operator'])) {
+                $init['operator'] = call_user_func($filter['operator']);
+              }
+              else {
+                $init['operator'] = array();
+              }
+            }
+            $init['operator'] = array_merge($init['operator'], $operator);
+
+            // add our own handler, and save the module-defined handler
+            $init['handler'] = 'content_views_filter_handler';
+            if (isset($filter['handler'])) {
+              $init['alt_handler'] = $filter['handler'];
+            }
+          }
+
           $table['filters'][$main_column['column'] .'_'. $key] = array_merge($filter, $init);
         }
       }
@@ -104,6 +132,96 @@
   return content_format($field, $item, $field_data['options']);
 }
 
+function content_views_filter_handler($op, $filter, $filterinfo, &$query) {
+  $operator = $filter['operator'];
+
+  // if operator is empty / not empty, deal with it
+  if (in_array($operator, array('EMPTY', 'NEMPTY'))) {
+    content_views_filter_handler_empty($op, $filter, $filterinfo, $query);
+  }
+  // if the field module provided a handler, defer to it
+  elseif (isset($filterinfo['alt_handler']) && function_exists($filterinfo['alt_handler'])) {
+    $filterinfo['handler'] = $filterinfo['alt_handler'];
+    $filterinfo['handler']($op, $filter, $filterinfo, $query);
+  }
+  // default : use views default filter building
+  else {
+    content_views_filter_handler_default($op, $filter, $filterinfo, $query);
+  }
+}
+
+function content_views_filter_handler_empty($op, $filter, $filterinfo, &$query) {
+  $field = $filterinfo['content_field'];
+  $table = $filterinfo['table'];
+  $db_info = $filterinfo['content_db_info'];
+  $main_column = reset($db_info['columns']);
+  $operator = $filter['operator'];
+
+  switch ($main_column['type']) {
+      case 'int':
+      case 'mediumint':
+      case 'tinyint':
+      case 'bigint':
+        $column_placeholder = '%d';
+        break;
+      case 'float':
+        $column_placeholder = '%f';
+        break;
+      default:
+        $column_placeholder = "'%s'";
+  }
+  if (isset($main_column['default'])) {
+    $op = ($operator == 'EMPTY') ? ' = ' : ' != ';
+    $clause = $table .'.'. $main_column['column'] . $op . $column_placeholder;
+    $arg = trim($main_column['default'], "'");
+  }
+  else {
+    $op = ($operator == 'EMPTY') ? ' IS NULL' : ' IS NOT NULL';
+    $clause .= $table .'.'. $main_column['column'] .' IS NULL';
+  }
+  $query->ensure_table($table);
+  $query->add_where($clause , $arg);
+}
+
+function content_views_filter_handler_default($op, $filter, $filterinfo, &$query) {
+  // copy / paste of views default management...
+  // TODO : propose a patch for Views that would defer this in a function call,
+  // and avoid code duplication.
+  if (is_array($filter['value']) && count($filter['value'])) {
+    if ($filter['operator'] == 'OR' || $filter['operator'] == 'NOR') {
+      $query->ensure_table($table);
+      $where_args = array_merge(array($query->use_alias_prefix . $table, $field), $filter['value']);
+      $placeholder = array_fill(0, count($filter['value']), '%s');
+      if ($filter['operator'] == 'OR') {
+        $query->add_where("%s.%s IN ('". implode("','", $placeholder) ."')", $where_args);
+      }
+      else {
+        $where_args[] = $where_args[0];
+        $where_args[] = $where_args[1];
+        $query->add_where("(%s.%s NOT IN ('". implode("','", $placeholder) ."') OR %s.%s IS NULL)", $where_args);
+      }
+    }
+    else {
+      $howmany = count($filter['value']);
+      $high_table = $query->add_table($table, true, $howmany);
+      if (!$high_table) { // couldn't add the table
+        break;
+      }
+
+      $table_num = $high_table - $howmany;
+      foreach ($filter['value'] as $item) {
+        $table_num++;
+        $tn = $query->get_table_name($table, $table_num);
+        $query->add_where("%s.%s = '%s'", $tn, $field, $item);
+      }
+    }
+  }
+  else {
+    $query->ensure_table("$table");
+    $query->add_where("%s.%s %s '%s'", $query->use_alias_prefix . $table, $field, $filter['operator'], $filter['value']);
+  }
+}
+
 /**
  * Implementation of hook_views_arguments().
  *
