forked from extern/egroupware
integrate custom-field search in token processing
to allow to use something like: "<regluar-match-token> +<custom-field-match-token>" to return correct entries matching both also no longer search private custom-fields not accessible by current user (gives a slower query, if private cfs exist)
This commit is contained in:
parent
5086e6cca3
commit
1d8f2a606b
@ -407,31 +407,37 @@ class Storage extends Storage\Base
|
||||
}
|
||||
|
||||
/**
|
||||
* Return criteria array for a given search pattern
|
||||
* Return SQL fragment to search custom-fields for given $pattern
|
||||
*
|
||||
* Reimplemented to handle search in custom-fields by ORing with a sub-query
|
||||
* returning all auto-ids of custom-fields matching the search-criteria
|
||||
* To be or-ed to query for $_pattern in regular columns of main-table.
|
||||
*
|
||||
* @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
|
||||
* @return string with SQL fragment running on main table: "id IN (SELECT id FROM extra-table WHERE extra_value like '$pattern')"
|
||||
*/
|
||||
public function search2criteria($_pattern,&$wildcard='',&$op='AND',$extra_col=null, $search_cols = array())
|
||||
public function cf_match($_pattern)
|
||||
{
|
||||
$pattern = $wildcard.$_pattern.$wildcard;
|
||||
static $private_cfs=null;
|
||||
|
||||
$criteria = parent::search2criteria($_pattern, $wildcard, $op, $extra_col, $search_cols);
|
||||
if (!$this->customfields) return ''; // no custom-fields --> no search
|
||||
|
||||
$criteria[0] = '('.$criteria[0].' OR '.
|
||||
$this->table_name.'.'.$this->autoinc_id.' IN (SELECT '.$this->autoinc_id.
|
||||
$sql = ' OR '.$this->table_name.'.'.$this->autoinc_id.' IN (SELECT '.$this->autoinc_id.
|
||||
' FROM '.$this->extra_table.' WHERE '.$this->extra_value.' '.
|
||||
$this->db->capabilities[Db::CAPABILITY_CASE_INSENSITIV_LIKE].' '.
|
||||
$GLOBALS['egw']->db->quote($pattern).'))';
|
||||
$GLOBALS['egw']->db->quote($_pattern);
|
||||
|
||||
return $criteria;
|
||||
// check if there are private cfs not available to current user --> filter by available cfs
|
||||
if (!isset($private_cfs))
|
||||
{
|
||||
$private_cfs = array_diff_key(
|
||||
Storage\Customfields::get($this->app, true, null, $this->db), // true: get private cfs too
|
||||
$this->customfields);
|
||||
//error_log(__METHOD__."() private_cfs=".array2string($private_cfs));
|
||||
}
|
||||
if ($private_cfs)
|
||||
{
|
||||
$sql .= ' AND '.$this->db->expression($this->extra_table, array($this->extra_key => array_keys($this->customfields)));
|
||||
}
|
||||
return $sql.')';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1056,16 +1056,16 @@ class Base
|
||||
* Parse an array of search criteria into something that can be passed on
|
||||
* to the DB
|
||||
*
|
||||
* @param array $criteria
|
||||
* @param array $_criteria
|
||||
* @param string $wildcard ='' appended befor and after each criteria
|
||||
* @param boolean $empty =false False=empty criteria are ignored in query, True=empty have to be empty in row
|
||||
* @param string $op ='AND' defaults to 'AND', can be set to 'OR' too, then criteria's are OR'ed together
|
||||
* @return Array
|
||||
* @throws Api\Db\Exception
|
||||
*/
|
||||
protected function parse_search(Array $criteria, $wildcard, $empty, $op)
|
||||
protected function parse_search(Array $_criteria, $wildcard, $empty, $op)
|
||||
{
|
||||
$criteria = $this->data2db($criteria);
|
||||
$criteria = $this->data2db($_criteria);
|
||||
foreach($criteria as $col => $val)
|
||||
{
|
||||
if (is_int($col))
|
||||
@ -1351,9 +1351,17 @@ class Base
|
||||
$op = 'OR';
|
||||
break;
|
||||
}
|
||||
$search_token = $wildcard.str_replace(array('%','_','*','?'),array('\\%','\\_','%','_'),$token).$wildcard;
|
||||
$token_filter = ' '.call_user_func_array(array($GLOBALS['egw']->db,'concat'),$columns).' '.
|
||||
$this->db->capabilities['case_insensitive_like'] . ' ' .
|
||||
$GLOBALS['egw']->db->quote($wildcard.str_replace(array('%','_','*','?'),array('\\%','\\_','%','_'),$token).$wildcard);
|
||||
$GLOBALS['egw']->db->quote($search_token);
|
||||
|
||||
// if we have customfields and this is Api\Storage (not Api\Storage\Base)
|
||||
if (is_a($this, __NAMESPACE__))
|
||||
{
|
||||
// add custom-field search: OR id IN (SELECT id FROM extra_table WHERE extra_value LIKE '$search_token')
|
||||
$token_filter .= $this->cf_match($search_token);
|
||||
}
|
||||
|
||||
// Compare numeric token as equality for numeric columns
|
||||
// skip user-wildcards (*,?) in is_numeric test, but not SQL wildcards, which get escaped and give sql-error
|
||||
@ -1376,10 +1384,10 @@ class Base
|
||||
}
|
||||
if(count($numeric_filter) > 0)
|
||||
{
|
||||
$token_filter = '(' . $token_filter . ' OR ' . implode(' OR ', $numeric_filter) . ')';
|
||||
$token_filter .= ' OR ' . implode(' OR ', $numeric_filter);
|
||||
}
|
||||
}
|
||||
$criteria[$op][] = $token_filter;
|
||||
$criteria[$op][] = '('.$token_filter.')';
|
||||
|
||||
$token = strtok($break);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user