Page MenuHomePhorge

D5062.1775244012.diff
No OneTemporary

Authored By
Unknown
Size
13 KB
Referenced Files
None
Subscribers
None

D5062.1775244012.diff

diff --git a/lib/kolab_sync.php b/lib/kolab_sync.php
--- a/lib/kolab_sync.php
+++ b/lib/kolab_sync.php
@@ -149,7 +149,8 @@
Syncroton_Registry::set(Syncroton_Registry::LOGGERBACKEND, $this->logger);
Syncroton_Registry::set(Syncroton_Registry::DATABASE, $this->get_dbh());
Syncroton_Registry::set(Syncroton_Registry::TRANSACTIONMANAGER, kolab_sync_transaction_manager::getInstance());
- // The unauthenticated OPTIONS request doesn't require these backends and we can't instantiate them without credentials for the underlying storage backend
+ // The unauthenticated OPTIONS request doesn't require these backends and we can't
+ // instantiate them without credentials for the underlying storage backend
if (!empty($userid)) {
Syncroton_Registry::set(Syncroton_Registry::DEVICEBACKEND, new kolab_sync_backend_device());
Syncroton_Registry::set(Syncroton_Registry::FOLDERBACKEND, new kolab_sync_backend_folder());
diff --git a/lib/kolab_sync_storage.php b/lib/kolab_sync_storage.php
--- a/lib/kolab_sync_storage.php
+++ b/lib/kolab_sync_storage.php
@@ -56,7 +56,7 @@
protected $folders = [];
protected $root_meta;
protected $relations = [];
- public $relationSupport = true;
+ protected $relationSupport = [self::MODEL_TASKS, self::MODEL_NOTES, self::MODEL_EMAIL];
protected $tag_rts = [];
private $modseq = [];
@@ -109,7 +109,7 @@
$this->storage->set_options([
// @TODO: there can be Roundcube plugins defining additional headers,
// we maybe would need to add them here
- 'fetch_headers' => 'X-KOLAB-TYPE X-KOLAB-MIME-VERSION',
+ 'fetch_headers' => 'X-KOLAB-TYPE X-KOLAB-MIME-VERSION MESSAGE-ID',
'skip_deleted' => true,
'threading' => false,
]);
@@ -694,7 +694,7 @@
return $uid;
}
- $useTags = $this->relationSupport && ($type == self::MODEL_TASKS || $type == self::MODEL_NOTES);
+ $useTags = in_array($type, $this->relationSupport);
// convert categories into tags, save them after creating an object
if ($useTags && !empty($data['categories'])) {
@@ -752,7 +752,7 @@
return $this->storage->delete_message($uid, $foldername);
}
- $useTags = $this->relationSupport && ($type == self::MODEL_TASKS || $type == self::MODEL_NOTES);
+ $useTags = in_array($type, $this->relationSupport);
$folder = $this->getFolder($folderid, $deviceid, $type);
@@ -795,14 +795,14 @@
}
// Categories (Tags) change
- if (isset($params['categories']) && $this->relationSupport) {
- $message = new rcube_message($uid, $foldername);
+ if (isset($params['categories']) && in_array($type, $this->relationSupport)) {
+ $headers = $this->storage->fetch_headers($foldername, $uid, false);
- if (empty($message->headers)) {
+ if (empty($headers) || empty($headers[$uid])) {
throw new Syncroton_Exception_Status_Sync(Syncroton_Exception_Status_Sync::SYNC_SERVER_ERROR);
}
- $this->setCategories($message, $params['categories']);
+ $this->setCategories($headers[$uid], $params['categories']);
}
return $uid;
@@ -810,7 +810,7 @@
$folder = $this->getFolder($folderid, $deviceid, $type);
- $useTags = $this->relationSupport && ($type == self::MODEL_TASKS || $type == self::MODEL_NOTES);
+ $useTags = in_array($type, $this->relationSupport);
// convert categories into tags, save them after updating an object
if ($useTags && array_key_exists('categories', $data)) {
@@ -836,16 +836,16 @@
/**
* Returns list of categories assigned to an object
*
- * @param object|string $object UID or rcube_message object
- * @param array $categories Addition tag names to merge with
+ * @param rcube_message_header|string $object UID or mail message headers
+ * @param array $categories Addition tag names to merge with
*
* @return array List of categories
*/
- public function getCategories($object, $categories = [])
+ protected function getCategories($object, $categories = [])
{
if (is_object($object)) {
// support only messages with message-id
- if (!($msg_id = $object->headers->get('message-id', false))) {
+ if (!($msg_id = $object->get('message-id', false))) {
return [];
}
@@ -952,8 +952,10 @@
$message = new rcube_message($uid, $foldername);
if (!empty($message->headers)) {
- if ($this->relationSupport) {
- $message->headers->others['categories'] = $this->getCategories($message);
+ if (in_array($type, $this->relationSupport)) {
+ $message->headers->folder = $foldername;
+ $message->headers->uid = $uid;
+ $message->headers->others['categories'] = $this->getCategories($message->headers);
}
return $message;
@@ -974,7 +976,7 @@
throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
}
- $useTags = $this->relationSupport && ($type == self::MODEL_TASKS || $type == self::MODEL_NOTES);
+ $useTags = in_array($type, $this->relationSupport);
if ($useTags) {
$result['categories'] = $this->getCategories($uid, $result['categories'] ?? []);
@@ -1071,10 +1073,10 @@
/**
* Set categories to an object
*
- * @param object|string $object UID or rcube_message object
- * @param array $categories List of Category names
+ * @param rcube_message_header|string $object UID or mail message headers
+ * @param array $categories List of Category names
*/
- public function setCategories($object, $categories)
+ protected function setCategories($object, $categories)
{
if (!is_object($object)) {
$config = kolab_storage_config::get_instance();
@@ -1084,7 +1086,7 @@
$config = kolab_storage_config::get_instance();
$delta = Syncroton_Registry::getPingTimeout();
- $uri = kolab_storage_config::get_message_uri($object->headers, $object->folder);
+ $uri = kolab_storage_config::get_message_uri($object, $object->folder);
// for all tag objects...
foreach ($config->get_tags() as $relation) {
@@ -1250,7 +1252,7 @@
}
// get members of modified relations
- if ($this->relationSupport) {
+ if (in_array($type, $this->relationSupport)) {
$changed_msgs = $this->getChangesByRelations($folderid, $device_key, $type, $filter);
// handle relation changes
if (!empty($changed_msgs)) {
@@ -1319,7 +1321,7 @@
// there's a PHP Warning from kolab_storage if $filter isn't an array
if (empty($filter)) {
$filter = [];
- } elseif ($this->relationSupport && ($type == self::MODEL_TASKS || $type == self::MODEL_NOTES)) {
+ } elseif (in_array($type, $this->relationSupport)) {
$changed_objects = $this->getChangesByRelations($folderid, $device_key, $type, $filter);
}
diff --git a/lib/kolab_sync_storage_kolab4.php b/lib/kolab_sync_storage_kolab4.php
--- a/lib/kolab_sync_storage_kolab4.php
+++ b/lib/kolab_sync_storage_kolab4.php
@@ -29,7 +29,8 @@
class kolab_sync_storage_kolab4 extends kolab_sync_storage
{
protected $davStorage = null;
- public $relationSupport = false;
+ protected $tagStorage = null;
+ protected $relationSupport = [self::MODEL_EMAIL];
/**
* This implements the 'singleton' design pattern
@@ -66,6 +67,7 @@
// Inject user+password to the URL, there's no other way to pass it to the DAV client
$url = str_replace('://', '://' . rawurlencode($sync->username) . ':' . rawurlencode($sync->password) . '@', $url);
+ $this->tagStorage = new kolab_storage_tags();
$this->davStorage = new kolab_storage_dav($url); // DAV
$this->storage = $sync->get_storage(); // IMAP
@@ -464,6 +466,35 @@
return $name ?? null;
}
+ /**
+ * Returns list of categories assigned to an object
+ *
+ * @param rcube_message_header|string $object UID or mail message headers
+ * @param array $categories Addition tag names to merge with
+ *
+ * @return array List of categories
+ */
+ protected function getCategories($object, $categories = [])
+ {
+ $tags = $this->tagStorage->get_tags_for($object);
+
+ // merge result with old categories
+ if (!empty($categories)) {
+ $tags = array_unique(array_merge($tags, (array) $categories));
+ }
+
+ return $tags;
+ }
+
+ /**
+ * Detect changes of tag objects data and assigned messages
+ */
+ protected function getChangesByRelations($folderid, $device_key, $type, $filter)
+ {
+ // This is not needed with Kolab4 that uses METADATA/ANNOTATE and immutable tags
+ return [];
+ }
+
/**
* Gets kolab_storage_folder object from Activesync folder ID.
*
@@ -568,4 +599,15 @@
}
return parent::getExtraData($folderid, $deviceid);
}
+
+ /**
+ * Set categories to an object
+ *
+ * @param rcube_message_header|string $object UID or mail message headers
+ * @param array $categories List of Category names
+ */
+ protected function setCategories($object, $categories)
+ {
+ $this->tagStorage->set_tags_for($object, $categories);
+ }
}
diff --git a/tests/Sync/Sync/RelationsTest.php b/tests/Sync/Sync/RelationsTest.php
--- a/tests/Sync/Sync/RelationsTest.php
+++ b/tests/Sync/Sync/RelationsTest.php
@@ -73,12 +73,13 @@
public function testRelationsSync()
{
$sync = \kolab_sync::get_instance();
- if (!$sync->storage()->relationSupport) {
- $this->markTestSkipped('No relation support');
- }
$this->emptyTestFolder('INBOX', 'mail');
- $this->emptyTestFolder('Configuration', 'configuration');
+ if ($this->isStorageDriver('kolab4')) {
+ $sync->get_storage()->set_metadata(\kolab_storage_tags::METADATA_ROOT, [\kolab_storage_tags::METADATA_TAGS_KEY => null]);
+ } else {
+ $this->emptyTestFolder('Configuration', 'configuration');
+ }
$this->registerDevice();
// Test INBOX
@@ -161,7 +162,9 @@
$this->assertSame("test1test2", $xpath->query("{$root}/ns:ApplicationData/Email:Categories")->item(0)->nodeValue);
// Assert the db state
- $this->assertSame(2, count($this->getRelationsState(self::$deviceId, $folderId)));
+ if ($this->isStorageDriver('kolab')) {
+ $this->assertSame(2, count($this->getRelationsState(self::$deviceId, $folderId)));
+ }
// Make sure we have a new timestamp after the first iteration.
// This way we can potentially catch errors when we end up using the same or a different timestamp.
sleep(1);
@@ -188,9 +191,10 @@
//FIXME this currently fails because we omit the empty categories element
// $this->assertSame("", $xpath->query("{$root}/ns:ApplicationData/Email:Categories")->item(0)->nodeValue);
-
// Assert the db state
- $this->assertSame(2, count($this->getRelationsState(self::$deviceId, $folderId)));
+ if ($this->isStorageDriver('kolab')) {
+ $this->assertSame(2, count($this->getRelationsState(self::$deviceId, $folderId)));
+ }
$response = $this->syncRequest($syncKey, $folderId, 10);
$this->assertEquals(200, $response->getStatusCode());
@@ -216,7 +220,9 @@
$response = $this->syncRequest(1, $folderId, 10);
$this->assertEquals(200, $response->getStatusCode());
- $this->assertSame(2, count($this->getRelationsState(self::$deviceId, $folderId)));
+ if ($this->isStorageDriver('kolab')) {
+ $this->assertSame(2, count($this->getRelationsState(self::$deviceId, $folderId)));
+ }
// Make sure the timestamp changes
sleep(1);
@@ -240,7 +246,9 @@
$response = $this->request($request, 'Ping');
$this->assertEquals(200, $response->getStatusCode());
- $this->assertSame(1, count($this->getRelationsState(self::$deviceId, $folderId)));
+ if ($this->isStorageDriver('kolab')) {
+ $this->assertSame(1, count($this->getRelationsState(self::$deviceId, $folderId)));
+ }
}
// This simulates a specific case where we had:
@@ -269,6 +277,8 @@
$response = $this->request($request, 'Ping');
$this->assertEquals(200, $response->getStatusCode());
- $this->assertSame(1, count($this->getRelationsState(self::$deviceId, $folderId)));
+ if ($this->isStorageDriver('kolab')) {
+ $this->assertSame(1, count($this->getRelationsState(self::$deviceId, $folderId)));
+ }
}
}

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 3, 7:20 PM (16 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18825939
Default Alt Text
D5062.1775244012.diff (13 KB)

Event Timeline