diff --git a/api/src/Contacts/Storage.php b/api/src/Contacts/Storage.php index fc8ee28954..7d651ccc64 100755 --- a/api/src/Contacts/Storage.php +++ b/api/src/Contacts/Storage.php @@ -715,7 +715,7 @@ class Storage { if($col != Sql::EXTRA_VALUE && $col != Sql::EXTRA_TABLE.'.'.Sql::EXTRA_VALUE && - !array_key_exists($col, $backend->db_cols)) + !array_key_exists($col, $backend->db_cols) && $key !== 'search_cfs') { if(!($col = array_search($col, $backend->db_cols))) { diff --git a/api/src/Storage.php b/api/src/Storage.php index ae2c94e8e3..15d11a604a 100644 --- a/api/src/Storage.php +++ b/api/src/Storage.php @@ -414,9 +414,10 @@ class Storage extends Storage\Base * 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|string[] $_type=null only search cfs of given type(s), e.g. "url-email" * @return string with SQL fragment running on main table: "id IN (SELECT id FROM extra-table WHERE extra_value like '$pattern')" */ - public function cf_match($_pattern) + public function cf_match($_pattern, $_type=null) { static $private_cfs=null; @@ -435,9 +436,21 @@ class Storage extends Storage\Base $this->customfields); //error_log(__METHOD__."() private_cfs=".array2string($private_cfs)); } - if ($private_cfs) + if ($_type) { - $sql .= ' AND '.$this->db->expression($this->extra_table, array($this->extra_key => array_keys($this->customfields))); + $cfs = []; + foreach($this->customfields as $name => $data) + { + if (in_array($data['type'], (array)$_type, true)) + { + $cfs[] = $name; + } + } + if (!$cfs) return ''; + } + if ($private_cfs || isset($cfs)) + { + $sql .= ' AND '.$this->db->expression($this->extra_table, array($this->extra_key => $cfs ?? array_keys($this->customfields))); } return $sql.')'; } diff --git a/api/src/Storage/Base.php b/api/src/Storage/Base.php index 2177471bbf..7bf73c8363 100644 --- a/api/src/Storage/Base.php +++ b/api/src/Storage/Base.php @@ -1251,7 +1251,8 @@ class Base * @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 =[] List of columns to search. If not provided, all columns in $this->db_cols will be considered - * @param ?bool $search_cfs =null null: do it only for Api\Storage, false: never do it + * allows to specify $search_cfs parameter with key 'search_cfs', which has precedence over $search_cfs parameter + * @param null|bool|string|string[] $search_cfs null: do it only for Api\Storage, false: never do it, or string type(s) of cfs to search, e.g. "url-email" * @return array or column => value pairs */ public function search2criteria($_pattern,&$wildcard='',&$op='AND',$extra_col=null, $search_cols=[],$search_cfs=null) @@ -1284,8 +1285,13 @@ class Base { $search_cols = $this->get_default_search_columns(); } + if (array_key_exists('search_cfs', $search_cols)) + { + $search_cfs = $search_cols['search_cfs']; + unset($search_cols['search_cfs']); + } // Concat all fields to be searched together, so the conditions operate across the whole record - foreach($search_cols as $col) + foreach($search_cols as $key => $col) { $col_name = $col; $table = $this->table_name; @@ -1381,7 +1387,7 @@ class Base if ($search_cfs ?? 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); + $token_filter .= $this->cf_match($search_token, is_string($search_cfs) || is_array($search_cfs) ? $search_cfs : null); } // Compare numeric token as equality for numeric columns diff --git a/mail/inc/class.mail_compose.inc.php b/mail/inc/class.mail_compose.inc.php index 2722eea12a..9aa8c447bd 100644 --- a/mail/inc/class.mail_compose.inc.php +++ b/mail/inc/class.mail_compose.inc.php @@ -3630,7 +3630,7 @@ class mail_compose $search_str = implode(' +', $search); // tell contacts/so_sql to AND search patterns //error_log(__METHOD__.__LINE__.$_searchString); $filter = $showAccounts ? array() : array('account_id' => null); - $filter['cols_to_search'] = array('n_prefix','n_given','n_family','org_name','email','email_home', 'contact_id'); + $filter['cols_to_search'] = array('n_prefix','n_given','n_family','org_name','email','email_home', 'contact_id', 'search_cfs' => false); $cols = array('n_fn','n_prefix','n_given','n_family','org_name','email','email_home', 'contact_id', 'etag'); $contacts = $contacts_obj->search($search_str, $cols, 'n_fn', '', '%', false, 'OR', array(0,100), $filter); $cfs_type_email = Api\Storage\Customfields::get_email_cfs('addressbook');