summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <machniak@kolabsys.com>2014-08-25 23:02:01 (GMT)
committerAleksander Machniak <machniak@kolabsys.com>2014-08-25 23:02:01 (GMT)
commiteff82d7c5cc100374e93bd39de13af7fe791aa67 (patch)
tree3ec299fcc1cd7e50ec8a18c52fbaa33b85f9fa04
parent70b2e7c805b3aae17daa85c996c2cae912fb3f8a (diff)
downloadkolab-syncroton-eff82d7c5cc100374e93bd39de13af7fe791aa67.tar.gz
Support email categories (#3489), todo: tag changes detection
-rw-r--r--lib/kolab_sync_data_email.php121
1 files changed, 118 insertions, 3 deletions
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index 03d1f78..99d1af5 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -106,6 +106,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
// Outlook 2013 support multi-folder
$this->ext_devices[] = 'windowsoutlook15';
+
+ if ($this->asversion >= 14) {
+ $this->tag_categories = true;
+ }
}
/**
@@ -317,6 +321,12 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
$result['messageClass'] = 'IPM.Note';
$result['contentClass'] = 'urn:content-classes:message';
+ // Categories (Tags)
+ if ($this->tag_categories) {
+ // convert kolab tags into categories
+ $result['categories'] = $this->getKolabTags($message);
+ }
+
// attachments
$attachments = array_merge($message->attachments, $message->inline_parts);
if (!empty($attachments)) {
@@ -552,13 +562,11 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
}
/**
- * update existing entry
+ * Update existing message
*
* @param string $folderId Folder identifier
* @param string $serverId Entry identifier
* @param Syncroton_Model_IEntry $entry Entry
- *
- * @return array
*/
public function updateEntry($folderId, $serverId, Syncroton_Model_IEntry $entry)
{
@@ -589,6 +597,11 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
$this->storage->set_flag($msg['uid'], 'FLAGGED', $msg['foldername']);
}
}
+
+ // Categories (Tags) change
+ if (isset($entry->categories)) {
+ $this->setKolabTags($message, $entry->categories);
+ }
}
/**
@@ -893,6 +906,8 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
}
}
+ // @TODO: tag objects modification detection
+
return $result;
}
@@ -1241,6 +1256,106 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
return mb_strcut(trim($body), 0, $size);
}
+ /**
+ * Returns list of tag names assigned to an email message
+ */
+ protected function getKolabTags($message)
+ {
+ // support only messages with message-id
+ if (!($msg_id = $message->headers->get('message-id', false))) {
+ return null;
+ }
+
+ $config = kolab_storage_config::get_instance();
+ $delta = Syncroton_Registry::getPingTimeout();
+ $folder = $message->folder;
+ $uid = $message->uid;
+
+ // get tag objects raleted to specified message-id
+ $tags = $config->get_tags($msg_id);
+
+ foreach ($tags as $idx => $tag) {
+ // resolve members if it wasn't done recently
+ $force = empty($this->tag_rts[$tag['uid']]) || $this->tag_rts[$tag['uid']] <= time() - $delta;
+ $members = $config->resolve_members($tag, $force);
+
+ if (empty($members[$folder]) || !in_array($uid, $members[$folder])) {
+ unset($tags[$idx]);
+ }
+
+ if ($force) {
+ $this->tag_rts[$tag['uid']] = time();
+ }
+ }
+
+ $tags = array_filter(array_map(function($v) { return $v['name']; }, $tags));
+
+ // make sure current folder is set correctly again
+ $this->storage->set_folder($folder);
+
+ return !empty($tags) ? $tags : null;
+ }
+
+ /**
+ * Set tags to an email message
+ */
+ protected function setKolabTags($message, $tags)
+ {
+ $config = kolab_storage_config::get_instance();
+ $delta = Syncroton_Registry::getPingTimeout();
+ $folder = $message->folder;
+ $uri = kolab_storage_config::get_message_uri($message->headers, $folder);
+
+ // for all tag objects...
+ foreach ($config->get_tags() as $idx => $relation) {
+ // resolve members if it wasn't done recently
+ $uid = $relation['uid'];
+ $force = empty($this->tag_rts[$uid]) || $this->tag_rts[$uid] <= time() - $delta;
+
+ if ($force) {
+ $config->resolve_members($relation, $force);
+ $this->tag_rts[$tag['uid']] = time();
+ }
+
+ $selected = !empty($tags) && in_array($relation['name'], $tags);
+ $found = !empty($relation['members']) && in_array($uri, $relation['members']);
+ $update = false;
+
+ // remove member from the relation
+ if ($found && !$selected) {
+ $relation['members'] = array_diff($relation['members'], (array) $uri);
+ $update = true;
+ }
+ // add member to the relation
+ else if (!$found && $selected) {
+ $relation['members'][] = $uri;
+ $update = true;
+ }
+
+ if ($update) {
+ $config->save($relation, 'relation');
+ }
+
+ $tags = array_diff($tags, (array) $relation['name']);
+ }
+
+ // create new relations
+ if (!empty($tags)) {
+ foreach ($tags as $tag) {
+ $relation = array(
+ 'name' => $tag,
+ 'members' => (array) $uri,
+ 'category' => 'tag',
+ );
+
+ $config->save($relation, 'relation');
+ }
+ }
+
+ // make sure current folder is set correctly again
+ $this->storage->set_folder($folder);
+ }
+
public static function charset_to_cp($charset)
{
// @TODO: ?????