plugins/kolab_notes plugins/kolab_tags plugins/libkolab
Aleksander Machniak
machniak at kolabsys.com
Wed Aug 6 16:40:14 CEST 2014
plugins/kolab_notes/kolab_notes.php | 25 ++-
plugins/kolab_tags/lib/kolab_tags_engine.php | 113 -----------------
plugins/libkolab/lib/kolab_storage_config.php | 166 +++++++++++++++++++++++++-
3 files changed, 180 insertions(+), 124 deletions(-)
New commits:
commit 08581c0a94f816ba94e0ba9c3a70a36b70b32c8c
Author: Aleksander Machniak <machniak at kolabsys.com>
Date: Wed Aug 6 10:39:47 2014 -0400
Improved relation members handling code
diff --git a/plugins/kolab_notes/kolab_notes.php b/plugins/kolab_notes/kolab_notes.php
index 6dbfa17..cf88772 100644
--- a/plugins/kolab_notes/kolab_notes.php
+++ b/plugins/kolab_notes/kolab_notes.php
@@ -983,6 +983,9 @@ class kolab_notes extends rcube_plugin
$this->relations = null; // clear in-memory cache
}
else {
+ // make relation members up-to-date
+ kolab_storage_config::resolve_members($relation);
+
// assign all links to one relation, others will be removed
$members = array_merge($links, array($search));
$diff1 = array_diff($members, $relation['members']);
@@ -1020,6 +1023,9 @@ class kolab_notes extends rcube_plugin
foreach ($this->get_relations($uid) as $relation) {
if (in_array($search, (array) $relation['members'])) {
+ // make relation members up-to-date
+ kolab_storage_config::resolve_members($relation);
+
foreach ($relation['members'] as $member) {
if ($member != $search) {
$result[] = $member;
@@ -1043,18 +1049,15 @@ class kolab_notes extends rcube_plugin
// get UIDs of assigned notes
foreach ($this->get_relations() as $relation) {
- foreach ($relation['members'] as $member) {
- $member = kolab_storage_config::parse_member_url($member);
- if ($member['folder'] == $folder && $member['uid'] == $message->uid) {
- reset($relation['members']);
- // find note UID(s)
- foreach ($relation['members'] as $member) {
- if (strpos($member, 'urn:uuid:') === 0) {
- $uids[] = substr($member, 9);
- }
- }
+ // get Folder/UIDs of relation members
+ $messages = kolab_storage_config::resolve_members($relation);
- continue 2;
+ if (!empty($messages[$folder]) && in_array($message->uid, $messages[$folder])) {
+ // find note UID(s)
+ foreach ($relation['members'] as $member) {
+ if (strpos($member, 'urn:uuid:') === 0) {
+ $uids[] = substr($member, 9);
+ }
}
}
}
diff --git a/plugins/kolab_tags/lib/kolab_tags_engine.php b/plugins/kolab_tags/lib/kolab_tags_engine.php
index 1551726..eb8298e 100644
--- a/plugins/kolab_tags/lib/kolab_tags_engine.php
+++ b/plugins/kolab_tags/lib/kolab_tags_engine.php
@@ -220,12 +220,6 @@ class kolab_tags_engine
// for every tag...
foreach ($taglist as $tag) {
- $updated = false;
-
- // make sure members list is up-to-date (UIDs are up-to-date)
- // @todo: maybe there's a faster way?
- $this->get_tag_messages($tag);
-
$tag['members'] = array_unique(array_merge((array) $tag['members'], $members));
// update tag object
@@ -429,91 +423,9 @@ class kolab_tags_engine
*
* @return array Folder/UID list
*/
- protected function get_tag_messages(&$tag)
+ protected function get_tag_messages(&$tag, $force = true)
{
- $result = array();
-
- foreach ((array) $tag['members'] as $member) {
- if ($url = $this->parse_member_url($member)) {
- $folder = $url['folder'];
- $result[$folder]['uid'][] = $url['uid'];
- $result[$folder]['params'][] = $url['params'];
- $result[$folder]['member'][] = $member;
- }
- }
-
- if (empty($result)) {
- return array();
- }
-
- // @TODO: caching?
-
- $rcube = rcube::get_instance();
- $storage = $rcube->get_storage();
-
- foreach ($result as $folder => $data) {
- // first, we search messages by UID
- // @FIXME: maybe better use index() which is cached?
- // @TODO: consider skip_deleted option
- $index = $storage->search_once($folder, 'UID ' . rcube_imap_generic::compressMessageSet($data['uid']));
- $uids = $index->get();
-
- // search by search parameters
- $not_found = array_diff($data['uid'], $uids);
- if (!empty($not_found)) {
- $params = array();
- $old_members = array();
- $new_members = array();
-
- foreach ($not_found as $uid) {
- $idx = array_search($uid, $data['uid']);
-
- if ($p = $data['params'][$idx]) {
- $params[$idx] = $p;
- }
-
- $old_members[] = $data['member'][$idx];
- }
-
- if (!empty($params)) {
- // @TODO: do this search in chunks (for e.g. 10 messages)?
- $search_str = '';
-
- foreach ($params as $p) {
- $search = array();
- foreach ($p as $key => $val) {
- $search[] = 'HEADER ' . strtoupper($key) . ' ' . rcube_imap_generic::escape($val);
- }
-
- $search_str .= ' (' . implode(' ', $search) . ')';
- }
-
- $search_str = str_repeat(' OR', count($params)-1) . $search_str;
-
- // @TODO: we should search all folders
- $index = $storage->search_once($folder, $search_str);
- $_uids = $index->get();
-
- if (!empty($_uids)) {
- $uids = array_merge($uids, $_uids);
- $msgs = $storage->fetch_headers($folder, $_uids, false);
-
- $new_members = array_merge($new_members, $this->build_members($folder, $msgs));
- }
- }
-
- // merge members
- $tag['members'] = array_diff($tag['members'], $old_members);
- $tag['members'] = array_unique(array_merge($tag['members'], $new_members));
-
- // update tag object with new members list
- $this->backend->update($tag);
- }
-
- $result[$folder] = array_unique($uids);
- }
-
- return $result;
+ return kolab_storage_config::resolve_members($tag, $force);
}
/**
@@ -521,26 +433,7 @@ class kolab_tags_engine
*/
protected function build_members($folder, $messages)
{
- $members = array();
-
- foreach ((array) $messages as $msg) {
- $params = array(
- 'folder' => $folder,
- 'uid' => $msg->uid,
- );
-
- // add search parameters
- // we don't want to build "invalid" searches e.g. that
- // will return false positives (more or wrong messages)
- if (($messageid = $msg->get('message-id', false)) && ($date = $msg->get('date', false))) {
- $params['message-id'] = $messageid;
- $params['date'] = $date;
- }
-
- $members[] = $this->build_member_url($params);
- }
-
- return $members;
+ return kolab_storage_config::build_members($folder, $messages);
}
/**
diff --git a/plugins/libkolab/lib/kolab_storage_config.php b/plugins/libkolab/lib/kolab_storage_config.php
index f5b891d..b759e1d 100644
--- a/plugins/libkolab/lib/kolab_storage_config.php
+++ b/plugins/libkolab/lib/kolab_storage_config.php
@@ -27,6 +27,7 @@ class kolab_storage_config
{
const FOLDER_TYPE = 'configuration';
+
/**
* Singleton instace of kolab_storage_config
*
@@ -165,9 +166,11 @@ class kolab_storage_config
$folder = $this->find_folder($object);
- $object['type'] = $type;
+ if ($type) {
+ $object['type'] = $type;
+ }
- return $folder->save($object, self::FOLDER_TYPE . '.' . $type, $object['uid']);
+ return $folder->save($object, self::FOLDER_TYPE . '.' . $object['type'], $object['uid']);
}
/**
@@ -199,7 +202,7 @@ class kolab_storage_config
/**
* Find folder
*/
- private function find_folder($object = array())
+ public function find_folder($object = array())
{
// find folder object
if ($object['_mailbox']) {
@@ -345,4 +348,161 @@ class kolab_storage_config
);
}
}
+
+ /**
+ * Build array of member URIs from set of messages
+ *
+ * @param string $folder Folder name
+ * @param array $messages Array of rcube_message objects
+ *
+ * @return array List of members (IMAP URIs)
+ */
+ public static function build_members($folder, $messages)
+ {
+ $members = array();
+
+ foreach ((array) $messages as $msg) {
+ $params = array(
+ 'folder' => $folder,
+ 'uid' => $msg->uid,
+ );
+
+ // add search parameters:
+ // we don't want to build "invalid" searches e.g. that
+ // will return false positives (more or wrong messages)
+ if (($messageid = $msg->get('message-id', false)) && ($date = $msg->get('date', false))) {
+ $params['message-id'] = $messageid;
+ $params['date'] = $date;
+
+ if ($subject = $msg->get('subject', false)) {
+ $params['subject'] = substr($subject, 0, 256);
+ }
+ }
+
+ $members[] = self::build_member_url($params);
+ }
+
+ return $members;
+ }
+
+ /**
+ * Resolve/validate/update members (which are IMAP URIs) of relation object.
+ *
+ * @param array $tag Tag object
+ * @param bool $force Force members list update
+ *
+ * @return array Folder/UIDs list
+ */
+ public static function resolve_members(&$tag, $force = true)
+ {
+ $result = array();
+
+ foreach ((array) $tag['members'] as $member) {
+ // IMAP URI members
+ if ($url = self::parse_member_url($member)) {
+ $folder = $url['folder'];
+
+ if (!$force) {
+ $result[$folder][] = $url['uid'];
+ }
+ else {
+ $result[$folder]['uid'][] = $url['uid'];
+ $result[$folder]['params'][] = $url['params'];
+ $result[$folder]['member'][] = $member;
+ }
+ }
+ }
+
+ if (empty($result) || !$force) {
+ return $result;
+ }
+
+ $rcube = rcube::get_instance();
+ $storage = $rcube->get_storage();
+ $search = array();
+ $missing = array();
+
+ // first we search messages by Folder+UID
+ foreach ($result as $folder => $data) {
+ // @FIXME: maybe better use index() which is cached?
+ // @TODO: consider skip_deleted option
+ $index = $storage->search_once($folder, 'UID ' . rcube_imap_generic::compressMessageSet($data['uid']));
+ $uids = $index->get();
+
+ // messages that were not found need to be searched by search parameters
+ $not_found = array_diff($data['uid'], $uids);
+ if (!empty($not_found)) {
+ foreach ($not_found as $uid) {
+ $idx = array_search($uid, $data['uid']);
+
+ if ($p = $data['params'][$idx]) {
+ $search[] = $p;
+ }
+
+ $missing[] = $result[$folder]['member'][$idx];
+
+ unset($result[$folder]['uid'][$idx]);
+ unset($result[$folder]['params'][$idx]);
+ unset($result[$folder]['member'][$idx]);
+ }
+ }
+
+ $result[$folder] = $uids;
+ }
+
+ // search in all subscribed mail folders using search parameters
+ if (!empty($search)) {
+ // remove not found members from the members list
+ $tag['members'] = array_diff($tag['members'], $missing);
+
+ // get subscribed folders
+ $folders = $storage->list_folders_subscribed('', '*', 'mail', null, true);
+
+ // @TODO: do this search in chunks (for e.g. 10 messages)?
+ $search_str = '';
+
+ foreach ($search as $p) {
+ $search_params = array();
+ foreach ($p as $key => $val) {
+ $key = strtoupper($key);
+ // don't search by subject, we don't want false-positives
+ if ($key != 'SUBJECT') {
+ $search_params[] = 'HEADER ' . $key . ' ' . rcube_imap_generic::escape($val);
+ }
+ }
+
+ $search_str .= ' (' . implode(' ', $search_params) . ')';
+ }
+
+ $search_str = trim(str_repeat(' OR', count($search)-1) . $search_str);
+
+ // search
+ $search = $storage->search_once($folders, $search_str);
+
+ // handle search result
+ $folders = (array) $search->get_parameters('MAILBOX');
+
+ foreach ($folders as $folder) {
+ $set = $search->get_set($folder);
+ $uids = $set->get();
+
+ if (!empty($uids)) {
+ $msgs = $storage->fetch_headers($folder, $uids, false);
+ $members = self::build_members($folder, $msgs);
+
+ // merge new members into the tag members list
+ $tag['members'] = array_merge($tag['members'], $members);
+
+ // add UIDs into the result
+ $result[$folder] = array_unique(array_merge((array)$result[$folder], $uids));
+ }
+ }
+
+ // update tag object with new members list
+ $tag['members'] = array_unique($tag['members']);
+ kolab_storage_config::get_instance()->save($tag, 'relation', false);
+ }
+
+ return $result;
+ }
}
More information about the commits
mailing list