lib/ext lib/kolab_sync_data.php
Aleksander Machniak
machniak at kolabsys.com
Tue Jan 15 09:32:10 CET 2013
lib/ext/Syncroton/Command/Ping.php | 25 --
lib/ext/Syncroton/Command/Sync.php | 17 -
lib/ext/Syncroton/Data/AData.php | 9
lib/ext/Syncroton/Data/IData.php | 10
lib/ext/Syncroton/Model/AEntry.php | 245 +-------------------
lib/ext/Syncroton/Model/AXMLEntry.php | 286 ++++++++++++++++++++++++
lib/ext/Syncroton/Model/Contact.php | 2
lib/ext/Syncroton/Model/Device.php | 14 -
lib/ext/Syncroton/Model/DeviceInformation.php | 2
lib/ext/Syncroton/Model/Email.php | 2
lib/ext/Syncroton/Model/EmailAttachment.php | 2
lib/ext/Syncroton/Model/EmailBody.php | 2
lib/ext/Syncroton/Model/EmailFlag.php | 2
lib/ext/Syncroton/Model/Event.php | 2
lib/ext/Syncroton/Model/EventAttendee.php | 2
lib/ext/Syncroton/Model/EventException.php | 2
lib/ext/Syncroton/Model/EventRecurrence.php | 2
lib/ext/Syncroton/Model/FileReference.php | 2
lib/ext/Syncroton/Model/Folder.php | 2
lib/ext/Syncroton/Model/GAL.php | 2
lib/ext/Syncroton/Model/GALPicture.php | 2
lib/ext/Syncroton/Model/IDevice.php | 2
lib/ext/Syncroton/Model/IEntry.php | 26 --
lib/ext/Syncroton/Model/IXMLEntry.php | 39 +++
lib/ext/Syncroton/Model/MeetingResponse.php | 2
lib/ext/Syncroton/Model/Policy.php | 2
lib/ext/Syncroton/Model/SendMail.php | 2
lib/ext/Syncroton/Model/SmartForward.php | 2
lib/ext/Syncroton/Model/SmartReply.php | 2
lib/ext/Syncroton/Model/StoreResponse.php | 4
lib/ext/Syncroton/Model/StoreResponseResult.php | 2
lib/ext/Syncroton/Model/SyncCollection.php | 2
lib/ext/Syncroton/Model/Task.php | 2
lib/ext/Syncroton/Model/TaskRecurrence.php | 2
lib/ext/Syncroton/Server.php | 17 -
lib/kolab_sync_data.php | 6
36 files changed, 414 insertions(+), 332 deletions(-)
New commits:
commit 09e7b779972c5640192a50ed163c7de815ed889e
Author: Aleksander Machniak <alec at alec.pl>
Date: Tue Jan 15 09:30:54 2013 +0100
Update Syncroton (with some performance improvements)
diff --git a/lib/ext/Syncroton/Command/Ping.php b/lib/ext/Syncroton/Command/Ping.php
index 9a056e1..9ac1b35 100644
--- a/lib/ext/Syncroton/Command/Ping.php
+++ b/lib/ext/Syncroton/Command/Ping.php
@@ -51,27 +51,23 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
{
$intervalStart = time();
$status = self::STATUS_NO_CHANGES_FOUND;
-
+
// the client does not send a wbxml document, if the Ping parameters did not change compared with the last request
if ($this->_requestBody instanceof DOMDocument) {
$xml = simplexml_import_dom($this->_requestBody);
$xml->registerXPathNamespace('Ping', 'Ping');
- if (isset($xml->HeartBeatInterval)) {
- $lifeTime = (int)$xml->HeartBeatInterval;
- if ($this->_device->pinglifetime != $lifeTime) {
- $this->_device->pinglifetime = $lifeTime;
- $need_update = true;
- }
+ if(isset($xml->HeartBeatInterval)) {
+ $this->_device->pinglifetime = (int)$xml->HeartBeatInterval;
}
-
+
if (isset($xml->Folders->Folder)) {
$folders = array();
foreach ($xml->Folders->Folder as $folderXml) {
try {
// does the folder exist?
$folder = $this->_folderBackend->getFolder($this->_device, (string)$folderXml->Id);
-
+
$folders[$folder->id] = $folder;
} catch (Syncroton_Exception_NotFound $senf) {
if ($this->_logger instanceof Zend_Log)
@@ -80,15 +76,10 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
break;
}
}
-
- $pingFolders = serialize(array_keys($folders));
- if ($this->_device->pingfolder != $pingFolders) {
- $this->_device->pingfolder = $pingFolders;
- $need_update = true;
- }
+ $this->_device->pingfolder = serialize(array_keys($folders));
}
- if ($need_update && $status == self::STATUS_NO_CHANGES_FOUND) {
+ if ($this->_device->isDirty() && $status == self::STATUS_NO_CHANGES_FOUND) {
$this->_device = $this->_deviceBackend->update($this->_device);
}
}
@@ -142,7 +133,7 @@ class Syncroton_Command_Ping extends Syncroton_Command_Wbxml
continue;
}
- $foundChanges = !!$dataController->getCountOfChanges($this->_contentStateBackend, $folder, $syncState);
+ $foundChanges = $dataController->hasChanges($this->_contentStateBackend, $folder, $syncState);
} catch (Syncroton_Exception_NotFound $e) {
// folder got never synchronized to client
diff --git a/lib/ext/Syncroton/Command/Sync.php b/lib/ext/Syncroton/Command/Sync.php
index ba28d37..b59bae6 100644
--- a/lib/ext/Syncroton/Command/Sync.php
+++ b/lib/ext/Syncroton/Command/Sync.php
@@ -161,11 +161,10 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
foreach ($collections as $collection) {
$collectionsToSave[$collection->collectionId] = $collection->toArray();
}
-
- $lastSyncCollection = Zend_Json::encode($collectionsToSave);
- if ($this->_device->lastsynccollection != $lastSyncCollection) {
- $this->_device->lastsynccollection = $lastSyncCollection;
-
+
+ $this->_device->lastsynccollection = Zend_Json::encode($collectionsToSave);
+
+ if ($this->_device->isDirty()) {
Syncroton_Registry::getDeviceBackend()->update($this->_device);
}
}
@@ -492,13 +491,13 @@ class Syncroton_Command_Sync extends Syncroton_Command_Wbxml
if (($now->getTimestamp() - $collectionData->syncState->lastsync->getTimestamp()) < Syncroton_Registry::getQuietTime()) {
continue;
}
-
+
$dataController = Syncroton_Data_Factory::factory($collectionData->folder->class , $this->_device, $this->_syncTimeStamp);
- $estimate = $dataController->getCountOfChanges($this->_contentStateBackend, $collectionData->folder, $collectionData->syncState);
+ $hasChanges = $dataController->hasChanges($this->_contentStateBackend, $collectionData->folder, $collectionData->syncState);
- // countinue immediately if there are changes available
- if ($estimate > 0) {
+ // countinue immediately if there are any changes available
+ if ($hasChanges) {
break 2;
}
}
diff --git a/lib/ext/Syncroton/Data/AData.php b/lib/ext/Syncroton/Data/AData.php
index 1382f68..97a821d 100644
--- a/lib/ext/Syncroton/Data/AData.php
+++ b/lib/ext/Syncroton/Data/AData.php
@@ -200,6 +200,15 @@ abstract class Syncroton_Data_AData implements Syncroton_Data_IData
return unserialize($entry);
}
+
+ /**
+ * (non-PHPdoc)
+ * @see Syncroton_Data_IData::hasChanges()
+ */
+ public function hasChanges(Syncroton_Backend_IContent $contentBackend, Syncroton_Model_IFolder $folder, Syncroton_Model_ISyncState $syncState)
+ {
+ return !!$this->getCountOfChanges($contentBackend, $folder, $syncState);
+ }
public function moveItem($_srcFolderId, $_serverId, $_dstFolderId)
{
diff --git a/lib/ext/Syncroton/Data/IData.php b/lib/ext/Syncroton/Data/IData.php
index 41aba4b..db286d3 100644
--- a/lib/ext/Syncroton/Data/IData.php
+++ b/lib/ext/Syncroton/Data/IData.php
@@ -78,6 +78,16 @@ interface Syncroton_Data_IData
* @return array
*/
public function getServerEntries($folderId, $filter);
+
+ /**
+ * return true if any data got modified in the backend
+ *
+ * @param Syncroton_Backend_IContent $contentBackend
+ * @param Syncroton_Model_IFolder $folder
+ * @param Syncroton_Model_ISyncState $syncState
+ * @return bool
+ */
+ public function hasChanges(Syncroton_Backend_IContent $contentBackend, Syncroton_Model_IFolder $folder, Syncroton_Model_ISyncState $syncState);
public function moveItem($srcFolderId, $serverId, $dstFolderId);
diff --git a/lib/ext/Syncroton/Model/AEntry.php b/lib/ext/Syncroton/Model/AEntry.php
index 1a58827..d2ad8be 100644
--- a/lib/ext/Syncroton/Model/AEntry.php
+++ b/lib/ext/Syncroton/Model/AEntry.php
@@ -18,13 +18,9 @@
abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, IteratorAggregate, Countable
{
- protected $_xmlBaseElement;
-
protected $_elements = array();
- protected $_properties = array();
-
- protected $_dateTimeFormat = "Y-m-d\TH:i:s.000\Z";
+ protected $_isDirty;
/**
* (non-PHPdoc)
@@ -32,63 +28,14 @@ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, Iterato
*/
public function __construct($properties = null)
{
- if ($properties instanceof SimpleXMLElement) {
- $this->setFromSimpleXMLElement($properties);
- } elseif (is_array($properties)) {
+ if (is_array($properties)) {
$this->setFromArray($properties);
}
- }
-
- /**
- * (non-PHPdoc)
- * @see Syncroton_Model_IEntry::appendXML()
- */
- public function appendXML(DOMElement $domParrent, Syncroton_Model_IDevice $device)
- {
- $this->_addXMLNamespaces($domParrent);
- foreach($this->_elements as $elementName => $value) {
- // skip empty values
- if($value === null || $value === '' || (is_array($value) && empty($value))) {
- continue;
- }
-
- list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
-
- if ($nameSpace == 'Internal') {
- continue;
- }
-
- $elementVersion = isset($elementProperties['supportedSince']) ? $elementProperties['supportedSince'] : '12.0';
-
- if (version_compare($device->acsversion, $elementVersion, '<')) {
- continue;
- }
-
- $nameSpace = 'uri:' . $nameSpace;
-
- if (isset($elementProperties['childElement'])) {
- $element = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName));
- foreach($value as $subValue) {
- $subElement = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementProperties['childElement']));
-
- $this->_appendXMLElement($device, $subElement, $elementProperties, $subValue);
-
- $element->appendChild($subElement);
-
- }
- $domParrent->appendChild($element);
- } else {
- $element = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName));
-
- $this->_appendXMLElement($device, $element, $elementProperties, $value);
-
- $domParrent->appendChild($element);
- }
-
- }
+ $this->_isDirty = false;
}
+
/**
* (non-PHPdoc)
* @see Countable::count()
@@ -109,18 +56,11 @@ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, Iterato
/**
* (non-PHPdoc)
- * @see Syncroton_Model_IEntry::getProperties()
+ * @see Syncroton_Model_IEntry::isDirty()
*/
- public function getProperties()
+ public function isDirty()
{
- $properties = array();
-
- foreach($this->_properties as $namespace => $namespaceProperties) {
- $properties = array_merge($properties, array_keys($namespaceProperties));
- }
-
- return $properties;
-
+ return $this->_isDirty;
}
/**
@@ -138,180 +78,19 @@ abstract class Syncroton_Model_AEntry implements Syncroton_Model_IEntry, Iterato
}
}
}
-
- /**
- * set properties from SimpleXMLElement object
- *
- * @param SimpleXMLElement $xmlCollection
- * @throws InvalidArgumentException
- */
- public function setFromSimpleXMLElement(SimpleXMLElement $properties)
- {
- if (!in_array($properties->getName(), (array) $this->_xmlBaseElement)) {
- throw new InvalidArgumentException('Unexpected element name: ' . $properties->getName());
- }
-
- foreach (array_keys($this->_properties) as $namespace) {
- if ($namespace == 'Internal') {
- continue;
- }
-
- $this->_parseNamespace($namespace, $properties);
- }
-
- return;
- }
-
- /**
- * add needed xml namespaces to DomDocument
- *
- * @param unknown_type $domParrent
- */
- protected function _addXMLNamespaces(DOMElement $domParrent)
- {
- foreach($this->_properties as $namespace => $namespaceProperties) {
- // don't add default namespace again
- if($domParrent->ownerDocument->documentElement->namespaceURI != 'uri:'.$namespace) {
- $domParrent->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:'.$namespace, 'uri:'.$namespace);
- }
- }
- }
-
- protected function _appendXMLElement(Syncroton_Model_IDevice $device, DOMElement $element, $elementProperties, $value)
- {
- if ($value instanceof Syncroton_Model_IEntry) {
- $value->appendXML($element, $device);
- } else {
- if ($value instanceof DateTime) {
- $value = $value->format($this->_dateTimeFormat);
-
- } elseif (isset($elementProperties['encoding']) && $elementProperties['encoding'] == 'base64') {
- if (is_resource($value)) {
- rewind($value);
- $value = stream_get_contents($value);
- }
- $value = base64_encode($value);
- }
-
- if ($elementProperties['type'] == 'byteArray') {
- $element->setAttributeNS('uri:Syncroton', 'Syncroton:encoding', 'opaque');
- // encode to base64; the wbxml encoder will base64_decode it again
- // this way we can also transport data, which would break the xmlparser otherwise
- $element->appendChild($element->ownerDocument->createCDATASection(base64_encode($value)));
- } else {
- // strip off any non printable control characters
- if (!ctype_print($value)) {
- $value = $this->_removeControlChars($value);
- }
- $element->appendChild($element->ownerDocument->createTextNode($value));
- }
- }
- }
-
- /**
- * removed control chars from string which are not allowd in XML values
- *
- * @param string|array $_dirty
- * @return string
- */
- protected function _removeControlChars($dirty)
- {
- return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', null, $dirty);
- }
-
- /**
- *
- * @param unknown_type $element
- * @throws InvalidArgumentException
- * @return multitype:unknown
- */
- protected function _getElementProperties($element)
- {
- foreach($this->_properties as $namespace => $namespaceProperties) {
- if (array_key_exists($element, $namespaceProperties)) {
- return array($namespace, $namespaceProperties[$element]);
- }
- }
-
- throw new InvalidArgumentException("$element is no valid property of " . get_class($this));
- }
-
- protected function _parseNamespace($nameSpace, SimpleXMLElement $properties)
- {
- // fetch data from Contacts namespace
- $children = $properties->children("uri:$nameSpace");
- foreach ($children as $elementName => $xmlElement) {
- $elementName = lcfirst($elementName);
-
- if (!isset($this->_properties[$nameSpace][$elementName])) {
- continue;
- }
-
- list (, $elementProperties) = $this->_getElementProperties($elementName);
-
- switch ($elementProperties['type']) {
- case 'container':
- if (isset($elementProperties['childElement'])) {
- $property = array();
-
- $childElement = ucfirst($elementProperties['childElement']);
-
- foreach ($xmlElement->$childElement as $subXmlElement) {
- if (isset($elementProperties['class'])) {
- $property[] = new $elementProperties['class']($subXmlElement);
- } else {
- $property[] = (string) $subXmlElement;
- }
- }
- } else {
- $subClassName = isset($elementProperties['class']) ? $elementProperties['class'] : get_class($this) . ucfirst($elementName);
-
- $property = new $subClassName($xmlElement);
- }
-
- break;
-
- case 'datetime':
- $property = new DateTime((string) $xmlElement, new DateTimeZone('UTC'));
-
- break;
-
- case 'number':
- $property = (int) $xmlElement;
-
- break;
-
- default:
- $property = (string) $xmlElement;
-
- break;
- }
-
- if (isset($elementProperties['encoding']) && $elementProperties['encoding'] == 'base64') {
- $property = base64_decode($property);
- }
-
- $this->$elementName = $property;
- }
- }
-
public function &__get($name)
{
- $this->_getElementProperties($name);
-
return $this->_elements[$name];
}
public function __set($name, $value)
- {
- list ($nameSpace, $properties) = $this->_getElementProperties($name);
-
- if ($properties['type'] == 'datetime' && !$value instanceof DateTime) {
- throw new InvalidArgumentException("value for $name must be an instance of DateTime");
+ {
+ if (!array_key_exists($name, $this->_elements) || $this->_elements[$name] != $value) {
+ $this->_elements[$name] = $value;
+
+ $this->_isDirty = true;
}
-
- $this->_elements[$name] = $value;
}
public function __isset($name)
diff --git a/lib/ext/Syncroton/Model/AXMLEntry.php b/lib/ext/Syncroton/Model/AXMLEntry.php
new file mode 100644
index 0000000..6dc1e9f
--- /dev/null
+++ b/lib/ext/Syncroton/Model/AXMLEntry.php
@@ -0,0 +1,286 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Syncroton
+ * @subpackage Model
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ */
+
+/**
+ * abstract class to handle ActiveSync entry
+ *
+ * @package Syncroton
+ * @subpackage Model
+ */
+
+abstract class Syncroton_Model_AXMLEntry extends Syncroton_Model_AEntry implements Syncroton_Model_IXMLEntry
+{
+ protected $_xmlBaseElement;
+
+ protected $_properties = array();
+
+ protected $_dateTimeFormat = "Y-m-d\TH:i:s.000\Z";
+
+ /**
+ * (non-PHPdoc)
+ * @see Syncroton_Model_IEntry::__construct()
+ */
+ public function __construct($properties = null)
+ {
+ if ($properties instanceof SimpleXMLElement) {
+ $this->setFromSimpleXMLElement($properties);
+ } elseif (is_array($properties)) {
+ $this->setFromArray($properties);
+ }
+
+ $this->_isDirty = false;
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see Syncroton_Model_IEntry::appendXML()
+ */
+ public function appendXML(DOMElement $domParrent, Syncroton_Model_IDevice $device)
+ {
+ $this->_addXMLNamespaces($domParrent);
+
+ foreach($this->_elements as $elementName => $value) {
+ // skip empty values
+ if($value === null || $value === '' || (is_array($value) && empty($value))) {
+ continue;
+ }
+
+ list ($nameSpace, $elementProperties) = $this->_getElementProperties($elementName);
+
+ if ($nameSpace == 'Internal') {
+ continue;
+ }
+
+ $elementVersion = isset($elementProperties['supportedSince']) ? $elementProperties['supportedSince'] : '12.0';
+
+ if (version_compare($device->acsversion, $elementVersion, '<')) {
+ continue;
+ }
+
+ $nameSpace = 'uri:' . $nameSpace;
+
+ if (isset($elementProperties['childElement'])) {
+ $element = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName));
+ foreach($value as $subValue) {
+ $subElement = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementProperties['childElement']));
+
+ $this->_appendXMLElement($device, $subElement, $elementProperties, $subValue);
+
+ $element->appendChild($subElement);
+
+ }
+ $domParrent->appendChild($element);
+ } else {
+ $element = $domParrent->ownerDocument->createElementNS($nameSpace, ucfirst($elementName));
+
+ $this->_appendXMLElement($device, $element, $elementProperties, $value);
+
+ $domParrent->appendChild($element);
+ }
+
+ }
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see Syncroton_Model_IEntry::getProperties()
+ */
+ public function getProperties()
+ {
+ $properties = array();
+
+ foreach($this->_properties as $namespace => $namespaceProperties) {
+ $properties = array_merge($properties, array_keys($namespaceProperties));
+ }
+
+ return $properties;
+
+ }
+
+ /**
+ * set properties from SimpleXMLElement object
+ *
+ * @param SimpleXMLElement $xmlCollection
+ * @throws InvalidArgumentException
+ */
+ public function setFromSimpleXMLElement(SimpleXMLElement $properties)
+ {
+ if (!in_array($properties->getName(), (array) $this->_xmlBaseElement)) {
+ throw new InvalidArgumentException('Unexpected element name: ' . $properties->getName());
+ }
+
+ foreach (array_keys($this->_properties) as $namespace) {
+ if ($namespace == 'Internal') {
+ continue;
+ }
+
+ $this->_parseNamespace($namespace, $properties);
+ }
+
+ return;
+ }
+
+ /**
+ * add needed xml namespaces to DomDocument
+ *
+ * @param unknown_type $domParrent
+ */
+ protected function _addXMLNamespaces(DOMElement $domParrent)
+ {
+ foreach($this->_properties as $namespace => $namespaceProperties) {
+ // don't add default namespace again
+ if($domParrent->ownerDocument->documentElement->namespaceURI != 'uri:'.$namespace) {
+ $domParrent->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:'.$namespace, 'uri:'.$namespace);
+ }
+ }
+ }
+
+ protected function _appendXMLElement(Syncroton_Model_IDevice $device, DOMElement $element, $elementProperties, $value)
+ {
+ if ($value instanceof Syncroton_Model_IEntry) {
+ $value->appendXML($element, $device);
+ } else {
+ if ($value instanceof DateTime) {
+ $value = $value->format($this->_dateTimeFormat);
+
+ } elseif (isset($elementProperties['encoding']) && $elementProperties['encoding'] == 'base64') {
+ if (is_resource($value)) {
+ rewind($value);
+ $value = stream_get_contents($value);
+ }
+ $value = base64_encode($value);
+ }
+
+ if ($elementProperties['type'] == 'byteArray') {
+ $element->setAttributeNS('uri:Syncroton', 'Syncroton:encoding', 'opaque');
+ // encode to base64; the wbxml encoder will base64_decode it again
+ // this way we can also transport data, which would break the xmlparser otherwise
+ $element->appendChild($element->ownerDocument->createCDATASection(base64_encode($value)));
+ } else {
+ // strip off any non printable control characters
+ if (!ctype_print($value)) {
+ $value = $this->_removeControlChars($value);
+ }
+ $element->appendChild($element->ownerDocument->createTextNode($value));
+ }
+ }
+ }
+
+ /**
+ * removed control chars from string which are not allowd in XML values
+ *
+ * @param string|array $_dirty
+ * @return string
+ */
+ protected function _removeControlChars($dirty)
+ {
+ return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', null, $dirty);
+ }
+
+ /**
+ *
+ * @param unknown_type $element
+ * @throws InvalidArgumentException
+ * @return multitype:unknown
+ */
+ protected function _getElementProperties($element)
+ {
+ foreach($this->_properties as $namespace => $namespaceProperties) {
+ if (array_key_exists($element, $namespaceProperties)) {
+ return array($namespace, $namespaceProperties[$element]);
+ }
+ }
+
+ throw new InvalidArgumentException("$element is no valid property of " . get_class($this));
+ }
+
+ protected function _parseNamespace($nameSpace, SimpleXMLElement $properties)
+ {
+ // fetch data from Contacts namespace
+ $children = $properties->children("uri:$nameSpace");
+
+ foreach ($children as $elementName => $xmlElement) {
+ $elementName = lcfirst($elementName);
+
+ if (!isset($this->_properties[$nameSpace][$elementName])) {
+ continue;
+ }
+
+ list (, $elementProperties) = $this->_getElementProperties($elementName);
+
+ switch ($elementProperties['type']) {
+ case 'container':
+ if (isset($elementProperties['childElement'])) {
+ $property = array();
+
+ $childElement = ucfirst($elementProperties['childElement']);
+
+ foreach ($xmlElement->$childElement as $subXmlElement) {
+ if (isset($elementProperties['class'])) {
+ $property[] = new $elementProperties['class']($subXmlElement);
+ } else {
+ $property[] = (string) $subXmlElement;
+ }
+ }
+ } else {
+ $subClassName = isset($elementProperties['class']) ? $elementProperties['class'] : get_class($this) . ucfirst($elementName);
+
+ $property = new $subClassName($xmlElement);
+ }
+
+ break;
+
+ case 'datetime':
+ $property = new DateTime((string) $xmlElement, new DateTimeZone('UTC'));
+
+ break;
+
+ case 'number':
+ $property = (int) $xmlElement;
+
+ break;
+
+ default:
+ $property = (string) $xmlElement;
+
+ break;
+ }
+
+ if (isset($elementProperties['encoding']) && $elementProperties['encoding'] == 'base64') {
+ $property = base64_decode($property);
+ }
+
+ $this->$elementName = $property;
+ }
+ }
+
+ public function &__get($name)
+ {
+ $this->_getElementProperties($name);
+
+ return $this->_elements[$name];
+ }
+
+ public function __set($name, $value)
+ {
+ list ($nameSpace, $properties) = $this->_getElementProperties($name);
+
+ if ($properties['type'] == 'datetime' && !$value instanceof DateTime) {
+ throw new InvalidArgumentException("value for $name must be an instance of DateTime");
+ }
+
+ if (!array_key_exists($name, $this->_elements) || $this->_elements[$name] != $value) {
+ $this->_elements[$name] = $value;
+
+ $this->_isDirty = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/ext/Syncroton/Model/Contact.php b/lib/ext/Syncroton/Model/Contact.php
index 16485c2..6b90a07 100644
--- a/lib/ext/Syncroton/Model/Contact.php
+++ b/lib/ext/Syncroton/Model/Contact.php
@@ -24,7 +24,7 @@
* @property Syncroton_Model_EmailBody Body
*/
-class Syncroton_Model_Contact extends Syncroton_Model_AEntry
+class Syncroton_Model_Contact extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'ApplicationData';
diff --git a/lib/ext/Syncroton/Model/Device.php b/lib/ext/Syncroton/Model/Device.php
index 3a0fdd6..a46ef2d 100644
--- a/lib/ext/Syncroton/Model/Device.php
+++ b/lib/ext/Syncroton/Model/Device.php
@@ -14,7 +14,7 @@
*
* @package Model
*/
-class Syncroton_Model_Device implements Syncroton_Model_IDevice
+class Syncroton_Model_Device extends Syncroton_Model_AEntry implements Syncroton_Model_IDevice
{
const TYPE_IPHONE = 'iphone';
const TYPE_WEBOS = 'webos';
@@ -22,18 +22,6 @@ class Syncroton_Model_Device implements Syncroton_Model_IDevice
const TYPE_ANDROID_40 = 'android40';
const TYPE_SMASUNGGALAXYS2 = 'samsunggti9100'; // Samsung Galaxy S-3
- public function __construct(array $_data = array())
- {
- $this->setFromArray($_data);
- }
-
- public function setFromArray(array $_data)
- {
- foreach($_data as $key => $value) {
- $this->$key = $value;
- }
- }
-
/**
* Returns major firmware version of this device
*
diff --git a/lib/ext/Syncroton/Model/DeviceInformation.php b/lib/ext/Syncroton/Model/DeviceInformation.php
index adab7b0..0a5c516 100644
--- a/lib/ext/Syncroton/Model/DeviceInformation.php
+++ b/lib/ext/Syncroton/Model/DeviceInformation.php
@@ -21,7 +21,7 @@
* @property string phoneNumber
*/
-class Syncroton_Model_DeviceInformation extends Syncroton_Model_AEntry
+class Syncroton_Model_DeviceInformation extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'Set';
diff --git a/lib/ext/Syncroton/Model/Email.php b/lib/ext/Syncroton/Model/Email.php
index 35f2661..29fd495 100644
--- a/lib/ext/Syncroton/Model/Email.php
+++ b/lib/ext/Syncroton/Model/Email.php
@@ -22,7 +22,7 @@
* @property DateTime lastVerbExecutionTime
* @property int read
*/
-class Syncroton_Model_Email extends Syncroton_Model_AEntry
+class Syncroton_Model_Email extends Syncroton_Model_AXMLEntry
{
const LASTVERB_UNKNOWN = 0;
const LASTVERB_REPLYTOSENDER = 1;
diff --git a/lib/ext/Syncroton/Model/EmailAttachment.php b/lib/ext/Syncroton/Model/EmailAttachment.php
index e415ad4..48d9866 100644
--- a/lib/ext/Syncroton/Model/EmailAttachment.php
+++ b/lib/ext/Syncroton/Model/EmailAttachment.php
@@ -19,7 +19,7 @@
* @property string syncKey
* @property int windowSize
*/
-class Syncroton_Model_EmailAttachment extends Syncroton_Model_AEntry
+class Syncroton_Model_EmailAttachment extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'Attachment';
diff --git a/lib/ext/Syncroton/Model/EmailBody.php b/lib/ext/Syncroton/Model/EmailBody.php
index 3b0f16b..3d465b8 100644
--- a/lib/ext/Syncroton/Model/EmailBody.php
+++ b/lib/ext/Syncroton/Model/EmailBody.php
@@ -20,7 +20,7 @@
* @property string Type
*/
-class Syncroton_Model_EmailBody extends Syncroton_Model_AEntry
+class Syncroton_Model_EmailBody extends Syncroton_Model_AXMLEntry
{
const TYPE_PLAINTEXT = 1;
const TYPE_HTML = 2;
diff --git a/lib/ext/Syncroton/Model/EmailFlag.php b/lib/ext/Syncroton/Model/EmailFlag.php
index c284987..258fd46 100644
--- a/lib/ext/Syncroton/Model/EmailFlag.php
+++ b/lib/ext/Syncroton/Model/EmailFlag.php
@@ -28,7 +28,7 @@
* @property DateTime UtcDueDate
* @property DateTime UtcStartDate
*/
-class Syncroton_Model_EmailFlag extends Syncroton_Model_AEntry
+class Syncroton_Model_EmailFlag extends Syncroton_Model_AXMLEntry
{
const STATUS_CLEARED = 0;
const STATUS_COMPLETE = 1;
diff --git a/lib/ext/Syncroton/Model/Event.php b/lib/ext/Syncroton/Model/Event.php
index cf0de60..84fec18 100644
--- a/lib/ext/Syncroton/Model/Event.php
+++ b/lib/ext/Syncroton/Model/Event.php
@@ -20,7 +20,7 @@
* @property int windowSize
*/
-class Syncroton_Model_Event extends Syncroton_Model_AEntry
+class Syncroton_Model_Event extends Syncroton_Model_AXMLEntry
{
/**
* busy status constants
diff --git a/lib/ext/Syncroton/Model/EventAttendee.php b/lib/ext/Syncroton/Model/EventAttendee.php
index a439650..82257db 100644
--- a/lib/ext/Syncroton/Model/EventAttendee.php
+++ b/lib/ext/Syncroton/Model/EventAttendee.php
@@ -20,7 +20,7 @@
* @property int windowSize
*/
-class Syncroton_Model_EventAttendee extends Syncroton_Model_AEntry
+class Syncroton_Model_EventAttendee extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'Attendee';
diff --git a/lib/ext/Syncroton/Model/EventException.php b/lib/ext/Syncroton/Model/EventException.php
index 7d7224b..0dab808 100644
--- a/lib/ext/Syncroton/Model/EventException.php
+++ b/lib/ext/Syncroton/Model/EventException.php
@@ -20,7 +20,7 @@
* @property int windowSize
*/
-class Syncroton_Model_EventException extends Syncroton_Model_AEntry
+class Syncroton_Model_EventException extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'Exception';
diff --git a/lib/ext/Syncroton/Model/EventRecurrence.php b/lib/ext/Syncroton/Model/EventRecurrence.php
index 367a2bc..3fe0c94 100644
--- a/lib/ext/Syncroton/Model/EventRecurrence.php
+++ b/lib/ext/Syncroton/Model/EventRecurrence.php
@@ -25,7 +25,7 @@
* @property int WeekOfMonth
*/
-class Syncroton_Model_EventRecurrence extends Syncroton_Model_AEntry
+class Syncroton_Model_EventRecurrence extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'Recurrence';
diff --git a/lib/ext/Syncroton/Model/FileReference.php b/lib/ext/Syncroton/Model/FileReference.php
index 9f0bbad..b54bb7d 100644
--- a/lib/ext/Syncroton/Model/FileReference.php
+++ b/lib/ext/Syncroton/Model/FileReference.php
@@ -16,7 +16,7 @@
* @property string Data
*/
-class Syncroton_Model_FileReference extends Syncroton_Model_AEntry
+class Syncroton_Model_FileReference extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'ApplicationData';
diff --git a/lib/ext/Syncroton/Model/Folder.php b/lib/ext/Syncroton/Model/Folder.php
index dfabc34..9655f9a 100644
--- a/lib/ext/Syncroton/Model/Folder.php
+++ b/lib/ext/Syncroton/Model/Folder.php
@@ -15,7 +15,7 @@
* @package Model
*/
-class Syncroton_Model_Folder extends Syncroton_Model_AEntry implements Syncroton_Model_IFolder
+class Syncroton_Model_Folder extends Syncroton_Model_AXMLEntry implements Syncroton_Model_IFolder
{
protected $_xmlBaseElement = array('FolderUpdate', 'FolderCreate');
diff --git a/lib/ext/Syncroton/Model/GAL.php b/lib/ext/Syncroton/Model/GAL.php
index 917c5e5..64765ce 100644
--- a/lib/ext/Syncroton/Model/GAL.php
+++ b/lib/ext/Syncroton/Model/GAL.php
@@ -29,7 +29,7 @@
* @property string Picture
* @property string Title
*/
-class Syncroton_Model_GAL extends Syncroton_Model_AEntry
+class Syncroton_Model_GAL extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'ApplicationData';
diff --git a/lib/ext/Syncroton/Model/GALPicture.php b/lib/ext/Syncroton/Model/GALPicture.php
index d7a208a..8122490 100644
--- a/lib/ext/Syncroton/Model/GALPicture.php
+++ b/lib/ext/Syncroton/Model/GALPicture.php
@@ -20,7 +20,7 @@
* @property string Status
* @property string Data
*/
-class Syncroton_Model_GALPicture extends Syncroton_Model_AEntry
+class Syncroton_Model_GALPicture extends Syncroton_Model_AXMLEntry
{
const STATUS_SUCCESS = 1;
const STATUS_NOPHOTO = 173;
diff --git a/lib/ext/Syncroton/Model/IDevice.php b/lib/ext/Syncroton/Model/IDevice.php
index e0c59ab..944a1f7 100644
--- a/lib/ext/Syncroton/Model/IDevice.php
+++ b/lib/ext/Syncroton/Model/IDevice.php
@@ -38,7 +38,7 @@
* @property string emailfilter_id
* @property string lastsynccollection
*/
-interface Syncroton_Model_IDevice
+interface Syncroton_Model_IDevice extends Syncroton_Model_IEntry
{
/**
* Returns major firmware version of this device
diff --git a/lib/ext/Syncroton/Model/IEntry.php b/lib/ext/Syncroton/Model/IEntry.php
index 34f6d53..c2c9ce7 100644
--- a/lib/ext/Syncroton/Model/IEntry.php
+++ b/lib/ext/Syncroton/Model/IEntry.php
@@ -29,33 +29,13 @@ interface Syncroton_Model_IEntry
public function __construct($properties = null);
/**
- *
- * @param DOMElement $_domParrent
- */
- /**
- *
- * @param DOMElement $_domParrent
- * @param Syncroton_Model_IDevice $device
+ * return true if data have got changed after initial data got loaded via constructor
*/
- public function appendXML(DOMElement $_domParrent, Syncroton_Model_IDevice $device);
-
- /**
- * return array of valid properties
- *
- * @return array
- */
- public function getProperties();
+ public function isDirty();
/**
*
* @param array $properties
*/
- public function setFromArray(array $properties);
-
- /**
- *
- * @param SimpleXMLElement $xmlCollection
- * @throws InvalidArgumentException
- */
- public function setFromSimpleXMLElement(SimpleXMLElement $properties);
+ public function setFromArray(array $properties);
}
\ No newline at end of file
diff --git a/lib/ext/Syncroton/Model/IXMLEntry.php b/lib/ext/Syncroton/Model/IXMLEntry.php
new file mode 100644
index 0000000..7b3ad0f
--- /dev/null
+++ b/lib/ext/Syncroton/Model/IXMLEntry.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Syncroton
+ *
+ * @package Model
+ * @license http://www.tine20.org/licenses/lgpl.html LGPL Version 3
+ * @copyright Copyright (c) 2012-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author Lars Kneschke <l.kneschke at metaways.de>
+ */
+
+/**
+ * class to handle ActiveSync contact
+ *
+ * @package Model
+ */
+
+interface Syncroton_Model_IXMLEntry extends Syncroton_Model_IEntry
+{
+ /**
+ *
+ * @param DOMElement $_domParrent
+ * @param Syncroton_Model_IDevice $device
+ */
+ public function appendXML(DOMElement $_domParrent, Syncroton_Model_IDevice $device);
+
+ /**
+ * return array of valid properties
+ *
+ * @return array
+ */
+ public function getProperties();
+
+ /**
+ *
+ * @param SimpleXMLElement $xmlCollection
+ * @throws InvalidArgumentException
+ */
+ public function setFromSimpleXMLElement(SimpleXMLElement $properties);
+}
\ No newline at end of file
diff --git a/lib/ext/Syncroton/Model/MeetingResponse.php b/lib/ext/Syncroton/Model/MeetingResponse.php
index 4d1e171..fded62d 100644
--- a/lib/ext/Syncroton/Model/MeetingResponse.php
+++ b/lib/ext/Syncroton/Model/MeetingResponse.php
@@ -20,7 +20,7 @@
* @property string longId
*/
-class Syncroton_Model_MeetingResponse extends Syncroton_Model_AEntry
+class Syncroton_Model_MeetingResponse extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'Request';
diff --git a/lib/ext/Syncroton/Model/Policy.php b/lib/ext/Syncroton/Model/Policy.php
index 9b1dcf3..9031d51 100644
--- a/lib/ext/Syncroton/Model/Policy.php
+++ b/lib/ext/Syncroton/Model/Policy.php
@@ -14,7 +14,7 @@
* @package Model
*/
-class Syncroton_Model_Policy extends Syncroton_Model_AEntry implements Syncroton_Model_IPolicy
+class Syncroton_Model_Policy extends Syncroton_Model_AXMLEntry implements Syncroton_Model_IPolicy
{
protected $_xmlBaseElement = 'EASProvisionDoc';
diff --git a/lib/ext/Syncroton/Model/SendMail.php b/lib/ext/Syncroton/Model/SendMail.php
index b11d9b9..f8641fd 100644
--- a/lib/ext/Syncroton/Model/SendMail.php
+++ b/lib/ext/Syncroton/Model/SendMail.php
@@ -16,7 +16,7 @@
* @package Syncroton
* @subpackage Model
*/
-class Syncroton_Model_SendMail extends Syncroton_Model_AEntry
+class Syncroton_Model_SendMail extends Syncroton_Model_AXMLEntry
{
protected $_properties = array(
'ComposeMail' => array(
diff --git a/lib/ext/Syncroton/Model/SmartForward.php b/lib/ext/Syncroton/Model/SmartForward.php
index 40ae481..5d34c9e 100644
--- a/lib/ext/Syncroton/Model/SmartForward.php
+++ b/lib/ext/Syncroton/Model/SmartForward.php
@@ -16,7 +16,7 @@
* @package Syncroton
* @subpackage Model
*/
-class Syncroton_Model_SmartForward extends Syncroton_Model_AEntry
+class Syncroton_Model_SmartForward extends Syncroton_Model_AXMLEntry
{
protected $_properties = array(
'ComposeMail' => array(
diff --git a/lib/ext/Syncroton/Model/SmartReply.php b/lib/ext/Syncroton/Model/SmartReply.php
index b61cbc6..856872c 100644
--- a/lib/ext/Syncroton/Model/SmartReply.php
+++ b/lib/ext/Syncroton/Model/SmartReply.php
@@ -16,7 +16,7 @@
* @package Syncroton
* @subpackage Model
*/
-class Syncroton_Model_SmartReply extends Syncroton_Model_AEntry
+class Syncroton_Model_SmartReply extends Syncroton_Model_AXMLEntry
{
protected $_properties = array(
'ComposeMail' => array(
diff --git a/lib/ext/Syncroton/Model/StoreResponse.php b/lib/ext/Syncroton/Model/StoreResponse.php
index 84fe036..bd8855e 100644
--- a/lib/ext/Syncroton/Model/StoreResponse.php
+++ b/lib/ext/Syncroton/Model/StoreResponse.php
@@ -19,7 +19,7 @@
* @property array range
* @property int total
*/
-class Syncroton_Model_StoreResponse extends Syncroton_Model_AEntry
+class Syncroton_Model_StoreResponse extends Syncroton_Model_AXMLEntry
{
/**
* status constants
@@ -51,7 +51,7 @@ class Syncroton_Model_StoreResponse extends Syncroton_Model_AEntry
/**
* (non-PHPdoc)
- * @see Syncroton_Model_AEntry::appendXML()
+ * @see Syncroton_Model_AXMLEntry::appendXML()
*/
public function appendXML(DOMElement $_domParrent, Syncroton_Model_IDevice $device)
{
diff --git a/lib/ext/Syncroton/Model/StoreResponseResult.php b/lib/ext/Syncroton/Model/StoreResponseResult.php
index b129fa7..e2deb91 100644
--- a/lib/ext/Syncroton/Model/StoreResponseResult.php
+++ b/lib/ext/Syncroton/Model/StoreResponseResult.php
@@ -14,7 +14,7 @@
* @package Syncroton
* @subpackage Model
*/
-class Syncroton_Model_StoreResponseResult extends Syncroton_Model_AEntry
+class Syncroton_Model_StoreResponseResult extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'Result';
diff --git a/lib/ext/Syncroton/Model/SyncCollection.php b/lib/ext/Syncroton/Model/SyncCollection.php
index 220226b..b6370dc 100644
--- a/lib/ext/Syncroton/Model/SyncCollection.php
+++ b/lib/ext/Syncroton/Model/SyncCollection.php
@@ -20,7 +20,7 @@
* @property int windowSize
*/
-class Syncroton_Model_SyncCollection extends Syncroton_Model_AEntry
+class Syncroton_Model_SyncCollection extends Syncroton_Model_AXMLEntry
{
protected $_elements = array(
'syncState' => null,
diff --git a/lib/ext/Syncroton/Model/Task.php b/lib/ext/Syncroton/Model/Task.php
index c4e032f..8ab473f 100644
--- a/lib/ext/Syncroton/Model/Task.php
+++ b/lib/ext/Syncroton/Model/Task.php
@@ -19,7 +19,7 @@
* @property string syncKey
* @property int windowSize
*/
-class Syncroton_Model_Task extends Syncroton_Model_AEntry
+class Syncroton_Model_Task extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'ApplicationData';
diff --git a/lib/ext/Syncroton/Model/TaskRecurrence.php b/lib/ext/Syncroton/Model/TaskRecurrence.php
index eb0b4b0..116ce14 100644
--- a/lib/ext/Syncroton/Model/TaskRecurrence.php
+++ b/lib/ext/Syncroton/Model/TaskRecurrence.php
@@ -20,7 +20,7 @@
* @property int windowSize
*/
-class Syncroton_Model_TaskRecurrence extends Syncroton_Model_AEntry
+class Syncroton_Model_TaskRecurrence extends Syncroton_Model_AXMLEntry
{
protected $_xmlBaseElement = 'Recurrence';
diff --git a/lib/ext/Syncroton/Server.php b/lib/ext/Syncroton/Server.php
index 2ae9a75..a938ffb 100644
--- a/lib/ext/Syncroton/Server.php
+++ b/lib/ext/Syncroton/Server.php
@@ -378,19 +378,14 @@ class Syncroton_Server
{
try {
$device = $this->_deviceBackend->getUserDevice($ownerId, $requestParameters['deviceId']);
-
- if ($device->useragent != $requestParameters['userAgent']) {
- $device->useragent = $requestParameters['userAgent'];
- $need_update = true;
- }
- if ($device->acsversion != $requestParameters['protocolVersion']) {
- $device->acsversion = $requestParameters['protocolVersion'];
- $need_update = true;
- }
-
- if ($need_update) {
+
+ $device->useragent = $requestParameters['userAgent'];
+ $device->acsversion = $requestParameters['protocolVersion'];
+
+ if ($device->isDirty()) {
$device = $this->_deviceBackend->update($device);
}
+
} catch (Syncroton_Exception_NotFound $senf) {
$device = $this->_deviceBackend->create(new Syncroton_Model_Device(array(
'owner_id' => $ownerId,
diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
index ee97657..1f2e384 100644
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -611,6 +611,12 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
}
+ public function hasChanges(Syncroton_Backend_IContent $contentBackend, Syncroton_Model_IFolder $folder, Syncroton_Model_ISyncState $syncState)
+ {
+ return !!$this->getCountOfChanges($contentBackend, $folder, $syncState);
+ }
+
+
/**
* Fetches the entry from the backend
*/
More information about the commits
mailing list