summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2014-08-22 12:01:13 (GMT)
committerAleksander Machniak <alec@alec.pl>2014-08-22 12:01:13 (GMT)
commitce151cada2d0fe73c2cdf903d613028f06729a88 (patch)
tree42dd65504685b0f958b40908e86624dedc8d5551
parent8374789041933ea20e68fafe4bf98f090602d139 (diff)
downloadkolab-syncroton-ce151cada2d0fe73c2cdf903d613028f06729a88.tar.gz
Implement tags based on Relation objects (#3473)
-rw-r--r--lib/kolab_sync_data.php165
-rw-r--r--lib/kolab_sync_data_notes.php10
-rw-r--r--lib/kolab_sync_data_tasks.php9
3 files changed, 169 insertions, 15 deletions
diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
index 7fdee71..55fe439 100644
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -511,9 +511,9 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
/**
* Search for existing entries
*
- * @param string $folderid
- * @param array $filter
- * @param int $result_type Type of the result (see RESULT_* constants)
+ * @param string $folderid Folder identifier
+ * @param array $filter Search filter
+ * @param int $result_type Type of the result (see RESULT_* constants)
*
* @return array|int Search result as count or array of uids/objects
*/
@@ -543,13 +543,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
foreach ($folders as $folderid) {
$foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
- if ($foldername === null) {
- continue;
- }
-
- $folder = $this->getFolderObject($foldername);
-
- if (!$folder) {
+ if ($foldername === null || !($folder = $this->getFolderObject($foldername))) {
continue;
}
@@ -589,10 +583,105 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
}
+ // consider Tag object modifications if needed
+ if ($this->tag_categories) {
+ $this->searchEntriesByTagChanges($filter, $folders, $result_type, $result);
+ }
+
return $result;
}
/**
+ * Checks if any Tags have been modified in specified time
+ * and returns UIDs (or count) of objects assigned to them
+ */
+ protected function searchEntriesByTagChanges($filter, $folders, $result_type, &$result)
+ {
+ $tag_filter = array();
+ $obj_filter = array();
+
+ // get period filter, create new objects filter
+ foreach ($filter as $f) {
+ if ($f[0] == 'changed') {
+ $tag_filter[] = $f;
+ }
+ else {
+ $obj_filter[] = $f;
+ }
+ }
+
+ // this is not search for changes, do nothing
+ if (empty($tag_filter)) {
+ return;
+ }
+
+ // we're detecting changes here, let's check if any tags have been modified
+ // we're covering here cases when tag name or tag assignment has been changed
+
+ $config = kolab_storage_config::get_instance();
+ $members = array();
+ $default = true;
+ $filter = array(
+ array('type', '=', 'relation'),
+ array('category', '=', 'tag')
+ );
+
+ $filter = array_merge($filter, $tag_filter);
+ $tags = $config->get_objects($filter, $default, 100);
+
+ // get UIDs of tag members
+ foreach ($tags as $tag) {
+ foreach ((array)$tag['members'] as $url) {
+ if (strpos($url, 'urn:uuid:') === 0) {
+ $members[] = substr($url, 9);
+ }
+ }
+ }
+
+ $members = array_unique($members);
+
+ // if we have UIDs in result already we can remove them here
+ // FIXME: if the result is an int we can end up
+ // with wrong result (some objects might be counted twice)
+ if ($result_type == self::RESULT_UID) {
+ $members = array_diff($members, $result);
+ }
+
+ if (empty($members)) {
+ return;
+ }
+
+ // search objects mathing current filter,
+ // tags/relations may contain members of many types, we need to
+ // search them by UID in all requested folders to get
+ // only these with requested type (and that really exist)
+ $obj_filter[] = array('uid', '=', $members);
+
+ foreach ($folders as $folderid) {
+ $foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
+
+ if ($foldername === null || !($folder = $this->getFolderObject($foldername))) {
+ continue;
+ }
+
+ switch ($result_type) {
+ case self::RESULT_COUNT:
+ $count = $folder->count($obj_filter);
+ $result += (int) $count;
+ break;
+
+ case self::RESULT_UID:
+ $uids = $folder->get_uids($obj_filter);
+
+ if (is_array($uids)) {
+ $result = array_merge($result, $uids);
+ }
+ break;
+ }
+ }
+ }
+
+ /**
* Returns filter query array according to specified ActiveSync FilterType
*
* @param int $filter_type Filter type
@@ -628,7 +717,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
}
/**
- * get count of entries changed between two dates
+ * Get count of entries changed between two dates
*
* @param string $folderId
* @param DateTime $start
@@ -774,10 +863,20 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
$folderid = isset($default['realid']) ? $default['realid'] : $default['serverId'];
}
+ // convert categories into tags, save them after creating an object
+ if ($this->tag_categories) {
+ $tags = $data['categories'];
+ unset($data['categories']);
+ }
+
$foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
$folder = $this->getFolderObject($foldername);
if ($folder && $folder->save($data)) {
+ if (!empty($tags)) {
+ $this->setKolabTags($data['uid'], $tags);
+ }
+
return $data;
}
}
@@ -792,7 +891,17 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
if ($object) {
$folder = $this->getFolderObject($object['_mailbox']);
+ // convert categories into tags, save them after updating an object
+ if ($this->tag_categories && array_key_exists('categories', $data)) {
+ $tags = (array) $data['categories'];
+ unset($data['categories']);
+ }
+
if ($folder && $folder->save($data)) {
+ if (isset($tags)) {
+ $this->setKolabTags($data['uid'], $tags);
+ }
+
return $data;
}
}
@@ -807,7 +916,16 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
if ($object) {
$folder = $this->getFolderObject($object['_mailbox']);
- return $folder && $folder->delete($entryid);
+
+ if ($folder && $folder->delete($entryid)) {
+ if ($this->tag_categories) {
+ $this->setKolabTags($object['uid'], null);
+ }
+
+ return true;
+ }
+
+ return false;
}
// object doesn't exist, confirm deletion
@@ -1515,6 +1633,29 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
}
/**
+ * Returns list of tag names assigned to kolab object
+ */
+ protected function getKolabTags($uid)
+ {
+ $config = kolab_storage_config::get_instance();
+ $tags = $config->get_tags($uid);
+ $tags = array_filter(array_map(function($v) { return $v['name']; }, $tags));
+
+ return !empty($tags) ? $tags : null;
+ }
+
+ /**
+ * Set tags to kolab object
+ */
+ protected function setKolabTags($uid, $tags)
+ {
+ if (isset($data->categories)) {
+ $config = kolab_storage_config::get_instance();
+ $config->save_tags($uid, $tags);
+ }
+ }
+
+ /**
* Converts string of days (TU,TH) to bitmask used by ActiveSync
*
* @param string $days
diff --git a/lib/kolab_sync_data_notes.php b/lib/kolab_sync_data_notes.php
index 2e442be..8c6ad92 100644
--- a/lib/kolab_sync_data_notes.php
+++ b/lib/kolab_sync_data_notes.php
@@ -39,8 +39,6 @@ class kolab_sync_data_notes extends kolab_sync_data
'subject' => 'title',
);
-
-
/**
* Kolab object type
*
@@ -69,6 +67,11 @@ class kolab_sync_data_notes extends kolab_sync_data
*/
protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_NOTE_USER_CREATED;
+ /**
+ * Enable mapping Activesync categories into Kolab tags (relations)
+ */
+ protected $tag_categories = true;
+
/**
* Appends note data to xml element
@@ -108,6 +111,9 @@ class kolab_sync_data_notes extends kolab_sync_data
$result['messageClass'] = 'IPM.StickyNote';
+ // convert kolab tags into categories
+ $result['categories'] = $this->getKolabTags($note['uid']);
+
return $as_array ? $result : new Syncroton_Model_Note($result);
}
diff --git a/lib/kolab_sync_data_tasks.php b/lib/kolab_sync_data_tasks.php
index e524c00..5e20178 100644
--- a/lib/kolab_sync_data_tasks.php
+++ b/lib/kolab_sync_data_tasks.php
@@ -67,7 +67,6 @@ class kolab_sync_data_tasks extends kolab_sync_data
'confidential' => self::SENSITIVITY_CONFIDENTIAL,
);
-
/**
* Kolab object type
*
@@ -96,6 +95,11 @@ class kolab_sync_data_tasks extends kolab_sync_data
*/
protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_TASK_USER_CREATED;
+ /**
+ * Enable mapping Activesync categories into Kolab tags (relations)
+ */
+ protected $tag_categories = true;
+
/**
* Appends contact data to xml element
@@ -151,6 +155,9 @@ class kolab_sync_data_tasks extends kolab_sync_data
$result[$key] = $value;
}
+ // convert kolab tags into categories
+ $result['categories'] = $this->getKolabTags($task['uid']);
+
// Recurrence
$this->recurrence_from_kolab($collection, $task, $result, 'Task');