Fix addressbook_bo::find_contact()

This commit is contained in:
Jörg Lehrke 2010-04-21 17:41:34 +00:00
parent f0102eba3f
commit 334a8c6fc3
2 changed files with 84 additions and 163 deletions

View File

@ -95,6 +95,7 @@ class addressbook_bo extends addressbook_so
* @var boolean * @var boolean
*/ */
var $log = false; var $log = false;
var $logfile = '/tmp/log-addressbook_bo';
/** /**
* Number and message of last error or false if no error, atm. only used for saving * Number and message of last error or false if no error, atm. only used for saving
@ -146,6 +147,12 @@ class addressbook_bo extends addressbook_so
function __construct($contact_app='addressbook') function __construct($contact_app='addressbook')
{ {
parent::__construct($contact_app); parent::__construct($contact_app);
if ($this->log)
{
$this->logfile = $GLOBALS['egw_info']['server']['temp_dir'].'/log-addressbook_bo';
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."($contact_app)\n", 3 ,$this->logfile);
}
$this->now_su = egw_time::to('now','ts'); $this->now_su = egw_time::to('now','ts');
$this->prefs =& $GLOBALS['egw_info']['user']['preferences']['addressbook']; $this->prefs =& $GLOBALS['egw_info']['user']['preferences']['addressbook'];
@ -1693,19 +1700,6 @@ class addressbook_bo extends addressbook_so
} }
} }
function all_empty(&$_contact, &$fields)
{
$retval = true;
foreach ($fields as $field) {
if (isset($_contact[$field]) && !empty($_contact[$field])) {
$retval = false;
break;
}
}
return $retval;
}
/** /**
* Try to find a matching db entry * Try to find a matching db entry
* *
@ -1715,11 +1709,14 @@ class addressbook_bo extends addressbook_so
*/ */
function find_contact($contact, $relax=false) function find_contact($contact, $relax=false)
{ {
$empty_addr_one = $empty_addr_two = true;
if ($this->log) if ($this->log)
{ {
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
. '('. ($relax ? 'RELAX': 'EXACT') . ')[ContactData]:' . '('. ($relax ? 'RELAX': 'EXACT') . ')[ContactData]:'
. array2string($contact)); . array2string($contact)
. "\n", 3, $this->logfile);
} }
$matchingContacts = array(); $matchingContacts = array();
@ -1728,7 +1725,8 @@ class addressbook_bo extends addressbook_so
if ($this->log) if ($this->log)
{ {
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
. '()[ContactID]: ' . $contact['id']); . '()[ContactID]: ' . $contact['id']
. "\n", 3, $this->logfile);
} }
// We only do a simple consistency check // We only do a simple consistency check
if (!$relax || ((empty($found['n_family']) || $found['n_family'] == $contact['n_family']) if (!$relax || ((empty($found['n_family']) || $found['n_family'] == $contact['n_family'])
@ -1745,7 +1743,8 @@ class addressbook_bo extends addressbook_so
if ($this->log) if ($this->log)
{ {
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
. '()[ContactUID]: ' . $contact['uid']); . '()[ContactUID]: ' . $contact['uid']
. "\n", 3, $this->logfile);
} }
// Try the given UID first // Try the given UID first
$criteria = array ('contact_uid' => $contact['uid']); $criteria = array ('contact_uid' => $contact['uid']);
@ -1772,124 +1771,75 @@ class addressbook_bo extends addressbook_so
$addr_two_fields = array('adr_two_street', $addr_two_fields = array('adr_two_street',
'adr_two_locality', 'adr_two_region', 'adr_two_locality', 'adr_two_region',
'adr_two_postalcode', 'adr_two_countryname'); 'adr_two_postalcode', 'adr_two_countryname');
$no_addr_one = array();
$no_addr_two = array();
if (!empty($contact['owner'])) if (!empty($contact['owner']))
{ {
$columns_to_search += array('owner'); $columns_to_search += array('owner');
} }
$backend =& $this->get_backend();
// define filter for empty address one
foreach ($addr_one_fields as $field)
{
if (!($db_col = array_search($field, $backend->db_cols)))
{
$db_col = $field;
}
$no_addr_one[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
}
// define filter for empty address two
foreach ($addr_two_fields as $field)
{
if (!($db_col = array_search($field, $backend->db_cols)))
{
$db_col = $field;
}
$no_addr_two[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
}
$result = false; $result = false;
$criteria = array(); $criteria = array();
$empty_columns = array();
foreach ($columns_to_search as $field) foreach ($columns_to_search as $field)
{ {
if (!isset($contact[$field]) || empty($contact[$field])) { if ($relax && in_array($field, $tolerance_fields)) continue;
if (empty($contact[$field]))
{
// Not every device supports all fields // Not every device supports all fields
if (!in_array($field, $tolerance_fields)) if (!in_array($field, $tolerance_fields))
{ {
if (!($db_col = array_search($field, $backend->db_cols))) $criteria[$field] = '';
{
$db_col = $field;
}
$empty_columns[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
} }
} }
else else
{
if (!$relax || !in_array($field, $tolerance_fields))
{ {
$criteria[$field] = $contact[$field]; $criteria[$field] = $contact[$field];
} }
} }
}
$filter = $empty_columns;
if (!$relax) if (!$relax)
{ {
// We use addresses only for strong matching // We use addresses only for strong matching
if ($this->all_empty($contact, $addr_one_fields))
{
$filter = $filter + $no_addr_one;
}
else
{
foreach ($addr_one_fields as $field) foreach ($addr_one_fields as $field)
{ {
if (!isset($contact[$field]) || empty($contact[$field])) if (empty($contact[$field]))
{ {
if (!($db_col = array_search($field, $backend->db_cols))) $criteria[$field] = '';
{
$db_col = $field;
}
$filter[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
} }
else else
{ {
$empty_addr_one = false;
$criteria[$field] = $contact[$field];
}
}
foreach ($addr_two_fields as $field)
{
if (empty($contact[$field]))
{
$criteria[$field] = '';
}
else
{
$empty_addr_two = false;
$criteria[$field] = $contact[$field]; $criteria[$field] = $contact[$field];
} }
} }
} }
if ($this->all_empty($contact, $addr_two_fields))
{
$filter = $filter + $no_addr_two;
}
else
{
foreach ($addr_two_fields as $field)
{
if (!isset($contact[$field]) || empty($contact[$field]))
{
if (!($db_col = array_search($field, $backend->db_cols)))
{
$db_col = $field;
}
$filter[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
}
else
{
$criteria[$field] = $contact[$field];
}
}
}
}
if ($this->log) if ($this->log)
{ {
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
. '()[Addressbook FIND Step 1]: ' . '()[Addressbook FIND Step 1]: '
. 'FILTER:' . array2string($filter) . 'CRITERIA = ' . array2string($criteria)
. 'CRITERIA' . array2string($criteria)); . "\n", 3, $this->logfile);
} }
// first try full match // first try full match
if (($foundContacts = parent::search($criteria, true, '', '', '', False, 'AND', false, $filter))) if (($foundContacts = parent::search($criteria, true, '', '', '', true)))
{ {
foreach ($foundContacts as $egwContact) foreach ($foundContacts as $egwContact)
{ {
@ -1898,24 +1848,26 @@ class addressbook_bo extends addressbook_so
} }
// No need for more searches for relaxed matching // No need for more searches for relaxed matching
if (!$relax || count($matchingContacts)) return $matchingContacts; if ($relax || count($matchingContacts)) return $matchingContacts;
if (!$this->all_empty($contact, $addr_one_fields) if (!$empty_addr_one && $empty_addr_two)
&& $this->all_empty($contact, $addr_two_fields))
{ {
// try given address and ignore the second one in EGW // try given address and ignore the second one in EGW
$filter = array_diff($filter, $no_addr_two); foreach ($addr_two_fields as $field)
{
unset($criteria[$field]);
}
if ($this->log) if ($this->log)
{ {
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
. '()[Addressbook FIND Step 2]: ' . '()[Addressbook FIND Step 2]: '
. 'FILTER:' . array2string($filter) . 'CRITERIA = ' . array2string($criteria)
. 'CRITERIA' . array2string($criteria)); . "\n", 3, $this->logfile);
} }
if (($foundContacts = parent::search($criteria, true, '', '', '', False, 'AND', false, $filter))) if (($foundContacts = parent::search($criteria, true, '', '', '', true)))
{ {
foreach ($foundContacts as $egwContact) foreach ($foundContacts as $egwContact)
{ {
@ -1925,35 +1877,21 @@ class addressbook_bo extends addressbook_so
else else
{ {
// try address as home address -- some devices don't qualify addresses // try address as home address -- some devices don't qualify addresses
$filter = $empty_columns;
foreach ($addr_two_fields as $key => $field) foreach ($addr_two_fields as $key => $field)
{
if (isset($criteria[$addr_one_fields[$key]]))
{ {
$criteria[$field] = $criteria[$addr_one_fields[$key]]; $criteria[$field] = $criteria[$addr_one_fields[$key]];
unset($criteria[$addr_one_fields[$key]]); unset($criteria[$addr_one_fields[$key]]);
} }
else
{
if (!($db_col = array_search($field,$backend->db_cols)))
{
$db_col = $field;
}
$filter[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
}
}
$filter = $filter + $no_addr_one;
if ($this->log) if ($this->log)
{ {
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
. '()[Addressbook FIND Step 3]: ' . '()[Addressbook FIND Step 3]: '
. 'FILTER:' . array2string($filter) . 'CRITERIA = ' . array2string($criteria)
. 'CRITERIA' . array2string($criteria)); . "\n", 3, $this->logfile);
} }
if (($foundContacts = parent::search($criteria, true, '', '', '', False, 'AND', false, $filter))) if (($foundContacts = parent::search($criteria, true, '', '', '', true)))
{ {
foreach ($foundContacts as $egwContact) foreach ($foundContacts as $egwContact)
{ {
@ -1962,54 +1900,23 @@ class addressbook_bo extends addressbook_so
} }
} }
} }
else elseif (!$empty_addr_one && !$empty_addr_two)
{ // try again after address swap { // try again after address swap
$filter = $empty_columns;
foreach ($addr_one_fields as $key => $field) foreach ($addr_one_fields as $key => $field)
{
$_temp_set = false;
if (isset($criteria[$field]))
{ {
$_temp = $criteria[$field]; $_temp = $criteria[$field];
$_temp_set = true;
unset($criteria[$field]);
}
if (isset($criteria[$addr_two_fields[$key]]))
{
$criteria[$field] = $criteria[$addr_two_fields[$key]]; $criteria[$field] = $criteria[$addr_two_fields[$key]];
unset($criteria[$addr_two_fields[$key]]);
}
else
{
if (!($db_col = array_search($field,$backend->db_cols)))
{
$db_col = $field;
}
$filter[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
}
if ($_temp_set)
{
$criteria[$addr_two_fields[$key]] = $_temp; $criteria[$addr_two_fields[$key]] = $_temp;
} }
else
{
if (!($db_col = array_search($addr_two_fields[$key],$backend->db_cols)))
{
$db_col = $field;
}
$filter[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
}
}
if ($this->log) if ($this->log)
{ {
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
. '()[Addressbook FIND Step 4]: ' . '()[Addressbook FIND Step 4]: '
. 'FILTER:' . array2string($filter) . 'CRITERIA = ' . array2string($criteria)
. 'CRITERIA' . array2string($criteria)); . "\n", 3, $this->logfile);
} }
if(($foundContacts = parent::search($criteria, true, '', '', '', False, 'AND', false, $filter))) if (($foundContacts = parent::search($criteria, true, '', '', '', true)))
{ {
foreach ($foundContacts as $egwContact) foreach ($foundContacts as $egwContact)
{ {
@ -2020,7 +1927,8 @@ class addressbook_bo extends addressbook_so
if ($this->log) if ($this->log)
{ {
error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ error_log(__FILE__.'['.__LINE__.'] '.__METHOD__
. '()[FOUND]:' . array2string($matchingContacts)); . '()[FOUND]: ' . array2string($matchingContacts)
. "\n", 3, $this->logfile);
} }
return $matchingContacts; return $matchingContacts;
} }

View File

@ -804,7 +804,21 @@ class so_sql
{ {
$db_col = $col; $db_col = $col;
} }
if ($wildcard || $criteria[$col][0] == '!' || if ($val === '')
{
if (isset($this->table_def['fd'][$db_col]) &&
$this->table_def['fd'][$db_col]['type'] == 'varchar' &&
$this->table_def['fd'][$db_col]['nullable'] !== false)
{
unset($criteria[$col]);
$query[] = '(' . $db_col . ' IS NULL OR ' . $db_col . " = '')";
}
else
{
$query[$db_col] = '';
}
}
elseif ($wildcard || $criteria[$col][0] == '!' ||
is_string($criteria[$col]) && (strpos($criteria[$col],'*')!==false || strpos($criteria[$col],'?')!==false)) is_string($criteria[$col]) && (strpos($criteria[$col],'*')!==false || strpos($criteria[$col],'?')!==false))
{ {
$cmp_op = ' '.$this->db->capabilities['case_insensitive_like'].' '; $cmp_op = ' '.$this->db->capabilities['case_insensitive_like'].' ';
@ -826,16 +840,14 @@ class so_sql
{ {
list($table,$only_col) = explode('.',$db_col); list($table,$only_col) = explode('.',$db_col);
$table_def = $this->db->get_table_definitions(true,$table);
if (is_array($val) && count($val) > 1) if (is_array($val) && count($val) > 1)
{ {
array_walk($val,array($this->db,'quote'),$table_def['fd'][$only_col]['type']); array_walk($val,array($this->db,'quote'),$this->table_def['fd'][$only_col]['type']);
$query[] = $sql = $db_col.' IN (' .implode(',',$val).')'; $query[] = $sql = $db_col.' IN (' .implode(',',$val).')';
} }
else else
{ {
$query[] = $db_col.'='.$this->db->quote(is_array($val)?array_shift($val):$val,$table_def['fd'][$only_col]['type']); $query[] = $db_col.'='.$this->db->quote(is_array($val)?array_shift($val):$val,$this->table_def['fd'][$only_col]['type']);
} }
} }
else else
@ -1002,6 +1014,7 @@ class so_sql
return new so_sql_db2data_iterator($this,$rs); return new so_sql_db2data_iterator($this,$rs);
} }
$arr = array(); $arr = array();
$n = 0;
if ($rs) foreach($rs as $row) if ($rs) foreach($rs as $row)
{ {
$data = array(); $data = array();
@ -1316,7 +1329,7 @@ class so_sql
$criteria = $query['search']; $criteria = $query['search'];
} }
$rows = $this->search($criteria,$only_keys,$query['order']?$query['order'].' '.$query['sort']:'',$extra_cols, $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'], '',false,$op,$query['num_rows']?array((int)$query['start'],$query['num_rows']):(int)$query['start'],
$query['col_filter'],$join,$need_full_no_count); $query['col_filter'],$join,$need_full_no_count);
if (!$rows) $rows = array(); // otherwise false returned from search would be returned as array(false) if (!$rows) $rows = array(); // otherwise false returned from search would be returned as array(false)