lib/ext lib/kolab lib/kolab_sync_data_email.php lib/kolab_sync_data.php
Aleksander Machniak
machniak at kolabsys.com
Mon Aug 20 20:16:41 CEST 2012
lib/ext/Syncroton/Model/Email.php | 7 +-
lib/ext/Syncroton/Model/EmailFlag.php | 106 ++++++++++++++++++++++++++++++++++
lib/kolab/kolab_storage_folder.php | 5 +
lib/kolab_sync_data.php | 2
lib/kolab_sync_data_email.php | 50 ++++++----------
5 files changed, 136 insertions(+), 34 deletions(-)
New commits:
commit bfda2ae15b2cb494ba8ef49ab79e0ea2253c9c77
Author: Aleksander Machniak <alec at alec.pl>
Date: Mon Aug 20 20:16:20 2012 +0200
Implemented email message flag (followup) handling
Fixed bug in imap search result usage with big performance impact and errors
when checking for changes in more than one data backend (Ping request).
diff --git a/lib/ext/Syncroton/Model/Email.php b/lib/ext/Syncroton/Model/Email.php
index e3aa3ce..ba78525 100644
--- a/lib/ext/Syncroton/Model/Email.php
+++ b/lib/ext/Syncroton/Model/Email.php
@@ -45,7 +45,6 @@ class Syncroton_Model_Email extends Syncroton_Model_AEntry
'DTStamp' => array('type' => 'datetime'),
'EndTime' => array('type' => 'datetime'),
'Flag' => array('type' => 'container'),
- 'FlagType' => array('type' => 'string'),
'From' => array('type' => 'string'),
'GlobalObjId' => array('type' => 'string'),
'Importance' => array('type' => 'number'),
@@ -140,7 +139,11 @@ class Syncroton_Model_Email extends Syncroton_Model_AEntry
$this->$elementName = new Syncroton_Model_EmailBody($xmlElement);
break;
-
+
+ case 'Flag':
+ $this->$elementName = new Syncroton_Model_EmailFlag($xmlElement);
+ break;
+
default:
list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
diff --git a/lib/ext/Syncroton/Model/EmailFlag.php b/lib/ext/Syncroton/Model/EmailFlag.php
new file mode 100644
index 0000000..18fe815
--- /dev/null
+++ b/lib/ext/Syncroton/Model/EmailFlag.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Model
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright Copyright (c) 2012-2012 Kolab Systems AG (http://www.kolabsys.com)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ * @author Aleksander Machniak <machniak at kolabsys.com>
+ */
+
+/**
+ * class to handle ActiveSync Flag element
+ *
+ * @package Model
+ * @property int Status
+ * @property string FlagType
+ * @property datetime CompleteTime
+ */
+class Syncroton_Model_EmailFlag extends Syncroton_Model_AEntry
+{
+ const STATUS_CLEARED = 0;
+ const STATUS_COMPLETE = 1;
+ const STATUS_ACTIVE = 2;
+
+ protected $_xmlBaseElement = 'Flag';
+
+ protected $_properties = array(
+ 'Email' => array(
+ 'CompleteTime' => array('type' => 'datetime'),
+ 'FlagType' => array('type' => 'string'),
+ 'Status' => array('type' => 'number'),
+ ),
+ 'Tasks' => array(
+ 'DateCompleted' => array('type' => 'datetime'),
+ 'DueDate' => array('type' => 'datetime'),
+ 'OrdinalDate' => array('type' => 'datetime'),
+ 'ReminderSet' => array('type' => 'number'),
+ 'ReminderTime' => array('type' => 'datetime'),
+ 'StartDate' => array('type' => 'datetime'),
+ 'Subject' => array('type' => 'string'),
+ 'SubOrdinalDate' => array('type' => 'string'),
+ 'UtcStartDate' => array('type' => 'datetime'),
+ 'UtcDueDate' => array('type' => 'datetime'),
+ ),
+ );
+
+ protected function _parseEmailNamespace(SimpleXMLElement $properties)
+ {
+ // fetch data from AirSyncBase namespace
+ $children = $properties->children('uri:Email');
+
+ foreach ($children as $elementName => $xmlElement) {
+ switch ($elementName) {
+ case 'FlagStatus':
+ // Android bug http://code.google.com/p/android/issues/detail?id=36113
+ $elementName = 'Status';
+
+ default:
+ list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
+
+ switch ($elementProperties['type']) {
+ case 'datetime':
+ $this->$elementName = new DateTime((string) $xmlElement, new DateTimeZone('UTC'));
+ break;
+
+ case 'number':
+ $this->$elementName = (int) $xmlElement;
+ break;
+
+ default:
+ $this->$elementName = (string) $xmlElement;
+ break;
+ }
+ }
+ }
+ }
+
+ protected function _parseTasksNamespace(SimpleXMLElement $properties)
+ {
+ // fetch data from AirSyncBase namespace
+ $children = $properties->children('uri:Tasks');
+
+ foreach ($children as $elementName => $xmlElement) {
+ switch ($elementName) {
+ default:
+ list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
+
+ switch ($elementProperties['type']) {
+ case 'datetime':
+ $this->$elementName = new DateTime((string) $xmlElement, new DateTimeZone('UTC'));
+ break;
+
+ case 'number':
+ $this->$elementName = (int) $xmlElement;
+ break;
+
+ default:
+ $this->$elementName = (string) $xmlElement;
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/lib/kolab/kolab_storage_folder.php b/lib/kolab/kolab_storage_folder.php
index e0f0deb..6dc0e05 100644
--- a/lib/kolab/kolab_storage_folder.php
+++ b/lib/kolab/kolab_storage_folder.php
@@ -429,6 +429,11 @@ class kolab_storage_folder
$this->imap->set_folder($folder);
$headers = $this->imap->get_message_headers($msguid);
+
+ if (empty($headers)) {
+ return false;
+ }
+
$object_type = kolab_format::mime2object_type($headers->others['x-kolab-type']);
$content_type = kolab_format::KTYPE_PREFIX . $object_type;
diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
index 3820c24..b589714 100644
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -592,7 +592,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
$allClientEntries = $contentBackend->getFolderState($this->device, $folder);
// @TODO: Consider looping over all folders here, not in getServerEntries() and
- // getChangesEntriesCount(). This way we could break the loop and not check all folders (see @TODO below)
+ // getChangedEntriesCount(). This way we could break the loop and not check all folders (see @TODO below)
// or at least skip redundant cache sync of the same folder
$allServerEntries = $this->getServerEntries($folder->serverId, $folder->lastfiltertype);
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index fa4d82f..8804cd6 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -174,13 +174,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
// Flagged message
if (!empty($headers->flags['FLAGGED'])) {
// Use FollowUp flag which is used in Android when message is marked with a star
-/*
- at TODO:
- $result['Flag'] = array(
+ $result['Flag'] = new Syncroton_Model_EmailFlag(array(
'FlagType' => 'FollowUp',
- 'Status' => 1,
- );
-*/
+ 'Status' => Syncroton_Model_EmailFlag::STATUS_ACTIVE,
+ ));
}
// Importance/Priority
@@ -491,29 +488,27 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
*/
public function updateEntry($folderId, $serverId, Syncroton_Model_IEntry $entry)
{
- $msg = $this->parseMessageId($serverId);
- $message = $this->getObject($serverId);
+ $msg = $this->parseMessageId($serverId);
+ $message = $this->getObject($serverId);
+ $is_flagged = !empty($message->headers->flags['FLAGGED']);
+ // Read status change
if (isset($entry->Read)) {
// here we update only Read flag
$flag = (((int)$entry->Read != 1) ? 'UN' : '') . 'SEEN';
$this->storage->set_flag($msg['uid'], $flag, $msg['foldername']);
}
- $is_flagged = !empty($message->headers->flags['FLAGGED']);
-
- // @TODO: Flag change
+ // Flag change
if (empty($entry->Flag)) {
if ($is_flagged) {
$this->storage->set_flag($msg['uid'], 'UNFLAGGED', $msg['foldername']);
}
}
- else if (!$is_flagged) {
-/*
+ else if (!$is_flagged && !empty($entry->Flag)) {
if ($entry->Flag->FlagType && preg_match('/^follow\s*up/i', $entry->Flag->FlagType)) {
$this->storage->set_flag($msg['uid'], 'FLAGGED', $msg['foldername']);
}
-*/
}
}
@@ -705,10 +700,7 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
// $this->storage->set_folder($foldername);
$this->storage->folder_sync($foldername);
- $this->storage->search($foldername, $filter_str, RCMAIL_CHARSET, $sort_by);
-
- $search = $this->storage->get_search_set();
- $search = $search[1];
+ $search = $this->storage->search_once($foldername, $filter_str);
if (!($search instanceof rcube_result_index)) {
continue;
@@ -772,25 +764,21 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
// $this->storage->set_folder($foldername);
$this->storage->folder_sync($foldername);
- $this->storage->search($foldername, $search_str, RCMAIL_CHARSET, $sort_by);
-
- $search = $this->storage->get_search_set();
- $search = $search[1];
+ $search = $this->storage->search_once($foldername, $search_str);
if (!($search instanceof rcube_result_index)) {
continue;
}
- if ($uids = $search->get()) {
- foreach ($uids as $idx => $uid) {
- $uids[$idx] = new Syncroton_Model_StoreResponseResult(array(
- 'LongId' => $this->createMessageId($folderid, $uid),
- 'CollectionId' => $folderid,
- 'Class' => 'Email',
- ));
- }
- $result = array_merge($result, $uids);
+ $uids = $search->get();
+ foreach ($uids as $idx => $uid) {
+ $uids[$idx] = new Syncroton_Model_StoreResponseResult(array(
+ 'LongId' => $this->createMessageId($folderid, $uid),
+ 'CollectionId' => $folderid,
+ 'Class' => 'Email',
+ ));
}
+ $result = array_merge($result, $uids);
// We don't want to search all folders if we've got already a lot messages
if (count($result) >= self::MAX_SEARCH_RESULT) {
More information about the commits
mailing list