remove non-digits and only search phone-numbers in phoneSearch

This commit is contained in:
Ralf Becker 2021-02-15 21:28:20 +02:00
parent f5e165a07a
commit 57d5176080
3 changed files with 63 additions and 14 deletions

View File

@ -2825,20 +2825,34 @@ class Contacts extends Contacts\Storage
}
if ($only_keys === true) $only_keys = false;
$start = false; // no pagination
// search for
list($country, $area, $rest) = explode(' ',
$phoneNumberUtil->format($number, \libphonenumber\PhoneNumberFormat::INTERNATIONAL), 3);
$rest_without_space = str_replace(' ', '', $rest);
foreach([
$area.' +'.$rest_without_space,
// strip last 4 digits off, in case they are written as extension or formatted like 123 45 67
$area.' +'.substr($rest_without_space, 0, -4),
// use first 2 digit from rest, in case they are written as extension or formatted like 12 3...
$area.' +'.substr($rest_without_space, 0, 2),
// try exact match
'"'.$criteria.'"',
] as $pattern)
/** @var Contacts\Sql */
$backend = $this->get_backend(null, $filter['owner']);
if (is_a($backend, Contacts\Sql::class) && $this->db->regexp_replace('test', '', '') !== 'test')
{
$patterns = [$area.$rest_without_space];
}
else
{
$patterns = [
$area . ' +' . $rest_without_space,
// strip last 4 digits off, in case they are written as extension or formatted like 123 45 67
$area . ' +' . substr($rest_without_space, 0, -4),
// use first 2 digit from rest, in case they are written as extension or formatted like 12 3...
$area . ' +' . substr($rest_without_space, 0, 2),
'"'.$criteria.'"', // try exact match
];
}
foreach($patterns as $pattern)
{
if (is_a($backend, Contacts\Sql::class))
{
$pattern = $backend->search2criteria($pattern, $wildcard, $op, null,
['tel_work', 'tel_cell', 'tel_fax', 'tel_assistent', 'tel_car', 'tel_pager',
'tel_home', 'tel_fax_home', 'tel_cell_private', 'tel_other'], false);
}
$rows = parent::search($pattern, $only_keys, $order_by, $extra_cols, $wildcard, $empty, $op, $start, $filter, $join, $ignore_acl) ?: [];
foreach($rows as $key => $row)
{
@ -2852,7 +2866,12 @@ class Contacts extends Contacts\Storage
// prefer region of contact, to eg. be able to parse US numbers starting direct with areacode but no leading 0
$row[substr($name, -5) === '_home' ? 'adr_two_countrycode' : 'adr_one_countrycode'] ?:
$row['adr_one_countrycode'] ?: $region);
if (($found = $tel->equals($number))) break;
if (($found = $tel->equals($number)))
{
$rows[$key]['tel_matching'] = $name;
break;
}
}
catch (\Exception $e) {
// ignore broken numbers

View File

@ -1239,6 +1239,30 @@ class Db
return $sql;
}
/**
* Calls REGEXP_REPLACE if available for the DB otherwise returns just $expr
*
* Example: REGEXP_REPLACE('tel_work', '[^0-9]', "''") to remove non-numbers from tel_work column
*
* @param string $expr SQL expression, must be quoted for strings, eg. "'string'"
* @param string $regexp no quotes neccessary will be run through quotes()
* @param string $with SQL expression, must be quoted for strings, eg. "'string'"
* @return string SQL REGEXP_REPLACE() function or $expr, if not supported!
*/
function regexp_replace($expr, $regexp, $with)
{
switch($this->Type)
{
case 'mysqli':
case 'mysql':
if ((float)$this->ServerInfo['version'] < 8.0) break; // MySQL 8.0 or MariaDB 10.0 required
// fall through
case 'pgsql':
return 'REGEXP_REPLACE('.$expr.','.$this->quote($regexp).','.$with.')';
}
return $expr;
}
/**
* SQL returning character (not byte!) positions for $substr in $str
*

View File

@ -1248,10 +1248,11 @@ class Base
* @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
* @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
* @return array or column => value pairs
*/
public function search2criteria($_pattern,&$wildcard='',&$op='AND',$extra_col=null, $search_cols = array())
public function search2criteria($_pattern,&$wildcard='',&$op='AND',$extra_col=null, $search_cols=[],$search_cfs=null)
{
$pattern = trim($_pattern);
// This function can get called multiple times. Make sure it doesn't re-process.
@ -1300,6 +1301,11 @@ class Base
{
continue; // will only give sql error
}
// remove all non-number from phone-numbers
if (substr($col, 0, 4) === 'tel_')
{
$col = $this->db->regexp_replace($col, '[^0-9]', "''");
}
$columns[] = sprintf($this->db->capabilities[Api\Db::CAPABILITY_CAST_AS_VARCHAR],"COALESCE($col,'')");
}
if(!$columns)
@ -1370,7 +1376,7 @@ class Base
$GLOBALS['egw']->db->quote($search_token);
// if we have customfields and this is Api\Storage (not Api\Storage\Base)
if (is_a($this, __NAMESPACE__))
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);