diff --git a/etemplate/inc/class.so_sql.inc.php b/etemplate/inc/class.so_sql.inc.php index cef70763be..1a049b8a71 100644 --- a/etemplate/inc/class.so_sql.inc.php +++ b/etemplate/inc/class.so_sql.inc.php @@ -1016,6 +1016,7 @@ class so_sql * @param string &$wildcard='' on return wildcard char to use, if pattern does not already contain wildcards! * @param string &$op='AND' on return boolean operation to use, if pattern does not start with ! we use OR else AND * @param string $extra_col=null extra column to search + * @param array $search_cols=array() List of columns to search. If not provided, all columns in $this->db_cols will be considered * @return array or column => value pairs */ public function search2criteria($pattern,&$wildcard='',&$op='AND',$extra_col=null, $search_cols = array()) @@ -1038,30 +1039,10 @@ class so_sql */ $numeric_types = array('auto', 'int', 'float', 'double'); $numeric_columns = array(); - $skip_columns_with = array('_id', 'modified', 'modifier', 'status', 'cat_id', 'owner'); if(!$search_cols) { - $search_cols = is_null($this->columns_to_search) ? $this->db_cols : $this->columns_to_search; - - // Skip some numeric columns that don't make sense to search if we have to default to all columns - if(is_null($this->columns_to_search)) - { - foreach($search_cols as $key => $col) - { - if(in_array($this->table_def['fd'][$col]['type'], $numeric_types)) - { - foreach($skip_columns_with as $bad) - { - if(strpos($col, $bad) !== false) - { - unset($search_cols[$key]); - continue 2; - } - } - } - } - } + $search_cols = $this->get_default_search_columns(); } if(!$search_cols) { @@ -1141,7 +1122,7 @@ class so_sql $numeric_filter = array(); foreach($numeric_columns as $col) { - if(!$wildcard) + if($wildcard == '') { // Token has a wildcard from user, use LIKE $numeric_filter[] = "($col IS NOT NULL AND CAST($col AS CHAR) LIKE " . @@ -1152,7 +1133,10 @@ class so_sql $numeric_filter[] = "($col IS NOT NULL AND $col = $token)"; } } - $token_filter = '(' . $token_filter . ' OR ' . implode(' OR ', $numeric_filter) . ')'; + if(count($numeric_filter) > 0) + { + $token_filter = '(' . $token_filter . ' OR ' . implode(' OR ', $numeric_filter) . ')'; + } } $criteria[$op][] = $token_filter; @@ -1187,6 +1171,41 @@ class so_sql return array('(' . $result . ')'); } + /** + * Get a default list of columns to search + * This is to be used as a fallback, for when the extending class does not define + * $this->columns_to_search. All the columns are considered, and any with $skip_columns_with in + * their name are discarded because these columns are expected to be foreign keys or other numeric + * values with no meaning to the user. + * + * @return array of column names + */ + protected function get_default_search_columns() + { + $skip_columns_with = array('_id', 'modified', 'modifier', 'status', 'cat_id', 'owner'); + $search_cols = is_null($this->columns_to_search) ? $this->db_cols : $this->columns_to_search; + + // Skip some numeric columns that don't make sense to search if we have to default to all columns + if(is_null($this->columns_to_search)) + { + foreach($search_cols as $key => $col) + { + if(in_array($this->table_def['fd'][$col]['type'], $numeric_types)) + { + foreach($skip_columns_with as $bad) + { + if(strpos($col, $bad) !== false) + { + unset($search_cols[$key]); + continue 2; + } + } + } + } + } + return $search_cols; + } + /** * extract the requested columns from $only_keys and $extra_cols param of a search * @@ -1267,8 +1286,7 @@ class so_sql $op = 'AND'; if ($query['search']) { - $wildcard = '%'; - $criteria = is_null($this->columns_to_search) ? $this->search2criteria($query['search'],$wildcard,$op) : $query['search']; + $criteria = $query['search']; } $rows = $this->search($criteria,$only_keys,$query['order']?$query['order'].' '.$query['sort']:'',$extra_cols, $wildcard,false,$op,$query['num_rows']?array((int)$query['start'],$query['num_rows']):(int)$query['start'], diff --git a/etemplate/inc/class.so_sql_cf.inc.php b/etemplate/inc/class.so_sql_cf.inc.php index b6626c5a5a..560bbccf3b 100644 --- a/etemplate/inc/class.so_sql_cf.inc.php +++ b/etemplate/inc/class.so_sql_cf.inc.php @@ -421,6 +421,8 @@ class so_sql_cf extends so_sql } if ($criteria && is_array($criteria)) { + $join .= $this->extra_join; + // check if we search in the custom fields if (isset($criteria[$this->extra_value])) { @@ -432,7 +434,6 @@ class so_sql_cf extends so_sql $this->db->capabilities[egw_db::CAPABILITY_CASE_INSENSITIV_LIKE]. ' ' . $this->db->quote($wildcard.$criteria[$this->extra_value].$wildcard); unset($criteria[$this->extra_value]); - $join .= $this->extra_join; } // replace ambiguous auto-id with (an exact match of) table_name.autoid if (isset($criteria[$this->autoinc_id])) @@ -507,6 +508,45 @@ class so_sql_cf extends so_sql return parent::search($criteria,$only_keys,$order_by,$extra_cols,$wildcard,$empty,$op,$start,$filter,$join,$need_full_no_count); } + /** + * Return criteria array for a given search pattern + * Reimplemented to search custom fields + * + * @param string $pattern search pattern incl. * or ? as wildcard, if no wildcards used we append and prepend one! + * @param string &$wildcard='' on return wildcard char to use, if pattern does not already contain wildcards! + * @param string &$op='AND' on return boolean operation to use, if pattern does not start with ! we use OR else AND + * @param string $extra_col=null extra column to search + * @param array $search_cols=array() List of columns to search. If not provided, all columns in $this->db_cols will be considered + * @return array or column => value pairs + */ + public function search2criteria($pattern,&$wildcard='',&$op='AND',$extra_col=null, $search_cols = array()) + { + // This function can get called multiple times. Make sure it doesn't re-process. + if (empty($pattern) || is_array($pattern)) return $pattern; + if(strpos($pattern, 'CONCAT') !== false) + { + return $pattern; + } + + $pattern = trim($pattern); + $filter = array(); + if(!$search_cols) + { + $search_cols = $this->get_default_search_columns(); + } + + // Add in custom field column, if it is not already there + if(!in_array($this->extra_table.'.'.$this->extra_value, $search_cols)) + { + $search_cols[] = $this->extra_table.'.'.$this->extra_value; + } + + // Let parent deal with the normal stuff + $criteria = parent::search2criteria($pattern, $wildcard, $op, $extra_col, $search_cols); + + return $criteria; + } + /** * Function to test if $field is a custom field: check for the prefix *