Branch 'dev/kolab3' - plugins/kolab_addressbook plugins/libkolab
Thomas Brüderli
bruederli at kolabsys.com
Wed May 16 10:11:13 CEST 2012
plugins/kolab_addressbook/lib/rcube_kolab_contacts.php | 55 ++++++++++-------
plugins/libkolab/SQL/mysql.sql | 2
plugins/libkolab/lib/kolab_format_contact.php | 2
plugins/libkolab/lib/kolab_storage_cache.php | 22 +++---
4 files changed, 49 insertions(+), 32 deletions(-)
New commits:
commit 4b5c2ce98551c8dbff40e679793c6901466132dc
Author: Thomas Bruederli <thomas at roundcube.net>
Date: Wed May 16 10:10:51 2012 +0200
Add some fulltext searching capabilities to kolab_storage_cache and use them for search (autocompletion) in Kolab address books
diff --git a/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php b/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php
index 37ba1f1..5b7fd8d 100644
--- a/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php
+++ b/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php
@@ -314,8 +314,6 @@ class rcube_kolab_contacts extends rcube_addressbook
*/
public function search($fields, $value, $mode=0, $select=true, $nocount=false, $required=array())
{
- $this->_fetch_contacts();
-
// search by ID
if ($fields == $this->primary_key) {
$ids = !is_array($value) ? explode(',', $value) : $value;
@@ -350,6 +348,25 @@ class rcube_kolab_contacts extends rcube_addressbook
// build key name regexp
$regexp = '/^(' . implode($fields, '|') . ')(?:.*)$/';
+ // pass query to storage if only indexed cols are involved
+ // NOTE: this is only some rough pre-filtering but probably includes false positives
+ $squery = array();
+ if (count(array_intersect(kolab_format_contact::$fulltext_cols, $fields)) == $scount) {
+ switch ($mode) {
+ case 1: $prefix = ' '; $suffix = ' '; break; // strict
+ case 2: $prefix = ' '; $suffix = ''; break; // prefix
+ default: $prefix = ''; $suffix = ''; break; // substring
+ }
+
+ $search_string = is_array($value) ? join(' ', $value) : $value;
+ foreach (rcube_utils::normalize_string($search_string, true) as $word) {
+ $squery[] = array('words', 'LIKE', '%' . $prefix . $word . $suffix . '%');
+ }
+ }
+
+ // get all/matching records
+ $this->_fetch_contacts($squery);
+
// save searching conditions
$this->filter = array('fields' => $fields, 'value' => $value, 'mode' => $mode, 'ids' => array());
@@ -374,17 +391,19 @@ class rcube_kolab_contacts extends rcube_addressbook
}
foreach ((array)$contact[$col] as $val) {
- $val = mb_strtolower($val);
- switch ($mode) {
- case 1:
- $got = ($val == $search);
- break;
- case 2:
- $got = ($search == substr($val, 0, strlen($search)));
- break;
- default:
- $got = (strpos($val, $search) !== false);
- break;
+ foreach ((array)$val as $str) {
+ $str = mb_strtolower($str);
+ switch ($mode) {
+ case 1:
+ $got = ($str == $search);
+ break;
+ case 2:
+ $got = ($search == substr($str, 0, strlen($search)));
+ break;
+ default:
+ $got = (strpos($str, $search) !== false);
+ break;
+ }
}
if ($got) {
@@ -916,17 +935,13 @@ class rcube_kolab_contacts extends rcube_addressbook
}
/**
- * Simply fetch all records and store them in private member vars
+ * Query storage layer and store records in private member var
*/
- private function _fetch_contacts()
+ private function _fetch_contacts($query = array())
{
if (!isset($this->contacts)) {
$this->contacts = array();
- foreach ((array)$this->storagefolder->get_objects() as $record) {
- // Because of a bug, sometimes group records are returned
- if ($record['__type'] == 'Group')
- continue;
-
+ foreach ((array)$this->storagefolder->select($query) as $record) {
$contact = $this->_to_rcube_contact($record);
$id = $contact['ID'];
$this->contacts[$id] = $contact;
diff --git a/plugins/libkolab/SQL/mysql.sql b/plugins/libkolab/SQL/mysql.sql
index 5f49e92..55d0dbc 100644
--- a/plugins/libkolab/SQL/mysql.sql
+++ b/plugins/libkolab/SQL/mysql.sql
@@ -11,10 +11,12 @@ CREATE TABLE IF NOT EXISTS `kolab_cache` (
`type` VARCHAR(32) CHARACTER SET ascii NOT NULL,
`msguid` BIGINT UNSIGNED NOT NULL,
`uid` VARCHAR(128) CHARACTER SET ascii NOT NULL,
+ `created` DATETIME DEFAULT NULL,
`data` TEXT NOT NULL,
`xml` TEXT NOT NULL,
`dtstart` DATETIME,
`dtend` DATETIME,
`tags` VARCHAR(255) NOT NULL,
+ `words` TEXT NOT NULL,
PRIMARY KEY(`resource`,`type`,`msguid`)
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
diff --git a/plugins/libkolab/lib/kolab_format_contact.php b/plugins/libkolab/lib/kolab_format_contact.php
index 646f6ca..1f20e3e 100644
--- a/plugins/libkolab/lib/kolab_format_contact.php
+++ b/plugins/libkolab/lib/kolab_format_contact.php
@@ -427,7 +427,7 @@ class kolab_format_contact extends kolab_format
{
$data = '';
foreach (self::$fulltext_cols as $col) {
- $val = is_array($this->data[$col]) ? join(" ", $this->data[$col]) : $this->data[$col];
+ $val = is_array($this->data[$col]) ? join(' ', $this->data[$col]) : $this->data[$col];
if (strlen($val))
$data .= $val . ' ';
}
diff --git a/plugins/libkolab/lib/kolab_storage_cache.php b/plugins/libkolab/lib/kolab_storage_cache.php
index 72373e1..7978411 100644
--- a/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/plugins/libkolab/lib/kolab_storage_cache.php
@@ -364,7 +364,7 @@ class kolab_storage_cache
{
$sql_where = '';
foreach ($query as $param) {
- $sql_where .= sprintf(' AND %s%s%s',
+ $sql_where .= sprintf(' AND %s %s %s',
$this->db->quote_identifier($param[0]),
$param[1],
$this->db->quote($param[2])
@@ -431,8 +431,8 @@ class kolab_storage_cache
if ($object['_formatobj']) {
$sql_data['xml'] = (string)$object['_formatobj']->write();
- $sql_data['tags'] = join(' ', $object['_formatobj']->get_tags());
- $sql_data['words'] = join(' ', $object['_formatobj']->get_words());
+ $sql_data['tags'] = ' ' . join(' ', $object['_formatobj']->get_tags()) . ' '; // pad with spaces for strict/prefix search
+ $sql_data['words'] = ' ' . join(' ', $object['_formatobj']->get_words()) . ' ';
}
// extract object data
@@ -492,7 +492,7 @@ class kolab_storage_cache
return false;
$sql_arr = $this->db->fetch_assoc($this->db->query(
- "SELECT msguid AS locked FROM kolab_cache ".
+ "SELECT msguid AS locked, ".$this->db->unixtimestamp('created')." AS created FROM kolab_cache ".
"WHERE resource=? AND type=?",
$this->resource_uri,
'lock'
@@ -501,24 +501,24 @@ class kolab_storage_cache
// create lock record if not exists
if (!$sql_arr) {
$this->db->query(
- "INSERT INTO kolab_cache (resource, type, msguid, uid, data, xml)".
- " VALUES (?, ?, ?, '', '', '')",
+ "INSERT INTO kolab_cache (resource, type, msguid, created, uid, data, xml)".
+ " VALUES (?, ?, 1, ?, '', '', '')",
$this->resource_uri,
'lock',
- time()
+ date('Y-m-d H:i:s')
);
}
// wait if locked (expire locks after 10 minutes)
- else if (intval($sql_arr['locked']) > 0 && (time() - $sql_arr['locked']) < 600) {
+ else if (intval($sql_arr['locked']) > 0 && (time() - $sql_arr['created']) < 600) {
usleep(500000);
return $this->_sync_lock();
}
// set lock
else {
$this->db->query(
- "UPDATE kolab_cache SET msguid=? ".
+ "UPDATE kolab_cache SET msguid=1, created=? ".
"WHERE resource=? AND type=?",
- time(),
+ date('Y-m-d H:i:s'),
$this->resource_uri,
'lock'
);
@@ -533,7 +533,7 @@ class kolab_storage_cache
private function _sync_unlock()
{
$this->db->query(
- "UPDATE kolab_cache SET msguid=0 ".
+ "UPDATE kolab_cache SET msguid=0, created='' ".
"WHERE resource=? AND type=?",
$this->resource_uri,
'lock'
More information about the commits
mailing list