<?php
/**
+ * Connector class for exporting ActiveSync messages to the wbxml output stream.
+ * Contains code written by the Z-Push project. Original file header preserved
+ * below.
+ *
+ * @copyright 2010 The Horde Project (http://www.horde.org)
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Horde_ActiveSync
+ */
+/**
* File : streamimporter.php
* Project : Z-Push
* Descr : Stream import classes
* This file is distributed under GPL v2.
* Consult LICENSE file for details
*/
-
-/**
- *
- *
- */
class Horde_ActiveSync_Connector_Exporter
{
+ /**
+ * The wbxml encoder
+ *
+ * @var Horde_ActiveSync_Wbxml_Encoder
+ */
protected $_encoder;
- protected $_type;
- protected $_seenObjects;
-
+
+ /**
+ * The collection class for what we are exporting
+ *
+ * @var string
+ */
+ protected $_class;
+
+ /**
+ * Local cache of object ids we have already dealt with.
+ *
+ * @var array
+ */
+ protected $_seenObjects = array();
+
+ /**
+ * Array of object ids that have changed.
+ * Used when exporting folder structure changes since they are not streamed
+ * from this object.
+ *
+ * @var array
+ */
public $changed = array();
+
+ /**
+ * Array of folder ids that have been deleted on the server.
+ *
+ * @var array
+ */
public $deleted = array();
+
+ /**
+ * Tracks the total number of folder changes
+ *
+ * @var integer
+ */
public $count = 0;
/**
* Const'r
*
- * @param Horde_ActiveSync_Wbxml_Encoder $encoder
- * @param string $class The collection class
+ * @param Horde_ActiveSync_Wbxml_Encoder $encoder The encoder
+ * @param string $class The collection class
*
* @return Horde_ActiveSync_Connector_Exporter
*/
public function __construct($encoder = null, $class = null)
{
$this->_encoder = $encoder;
- $this->_type = $class;
- $this->_seenObjects = array();
+ $this->_class = $class;
}
/**
+ * Send a message change over the wbxml stream
*
- * @param $id
- * @param $message
- * @return unknown_type
+ * @param string $id Thenuid of the message
+ * @param Horde_ActiveSync_Message_Base $message The message object
+ *
+ * @return boolean
*/
public function messageChange($id, $message)
{
- if ($message->getClass() != $this->_type) {
- return true; // ignore other types
+ /* Just ignore any messages that are not from this collection */
+ if ($message->getClass() != $this->_class) {
+ return true;
}
- // prevent sending the same object twice in one request
+ /* Prevent sending the same object twice in one request */
if (in_array($id, $this->_seenObjects)) {
return true;
}
+ /* Remember this message */
$this->_seenObjects[] = $id;
+
+ /* Specify if this is an ADD or a MODIFY change? */
if ($message->flags === false || $message->flags === SYNC_NEWMESSAGE) {
$this->_encoder->startTag(SYNC_ADD);
} else {
$this->_encoder->startTag(SYNC_MODIFY);
}
+ /* Send the message */
$this->_encoder->startTag(SYNC_SERVERENTRYID);
$this->_encoder->content($id);
$this->_encoder->endTag();
}
/**
+ * Stream a message deletion to the PIM
*
- * @param $id
- * @return unknown_type
+ * @param string $id The uid of the message we are deleting.
+ *
+ * @return boolean
*/
public function messageDeletion($id)
{
}
/**
+ * Change a message's READ flag.
+ *
+ * @param string $id The uid
+ * @param integer $flags The flag
*
- * @param $id
- * @param $flags
- * @return unknown_type
+ * @return boolean
*/
public function messageReadFlag($id, $flags)
{
- if ($this->_type != "syncmail") {
+ /* This only applies to mail folders */
+ if ($this->_class != "syncmail") {
return true;
}
+
+ /* Encode and stream */
$this->_encoder->startTag(SYNC_MODIFY);
$this->_encoder->startTag(SYNC_SERVERENTRYID);
$this->_encoder->content($id);
}
/**
+ * Move a message to a different folder.
+ * @TODO
+ * @param Horde_ActiveSync_Message_Base $message The message
*
- * @param $message
- * @return unknown_type
+ * @return boolean
*/
function messageMove($message)
{
}
/**
+ * Add a folder change to the cache. (used during FolderSync Requests).
+ *
+ * @param Horde_ActiveSync_Message_Folder $folder
*
- * @param <type> $folder
- * @return <type>
+ * @return boolean
*/
public function FolderChange($folder)
{
}
/**
+ * Add a folder deletion to the cache (used during FolderSync Requests).
*
- * @param <type> $id
- * @return <type>
+ * @param string $id The folder id
+ *
+ * @return boolean
*/
public function FolderDeletion($id)
{
<?php
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
+/**
+ * Connector class for importing ActiveSync messages from the wbxml input stream
+ * Contains code written by the Z-Push project. Original file header preserved
+ * below.
+ *
+ * @copyright 2010 The Horde Project (http://www.horde.org)
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Horde_ActiveSync
+ */
+/**
+ * File : streamimporter.php
+ * Project : Z-Push
+ * Descr : Stream import classes
+ *
+ * Created : 01.10.2007
+ *
+ * � Zarafa Deutschland GmbH, www.zarafaserver.de
+ * This file is distributed under GPL v2.
+ * Consult LICENSE file for details
*/
class Horde_ActiveSync_Connector_Importer
{
/**
+ * State machine
*
- * @var Horde_ActiveSync_StateMachine_Base
+ * @var Horde_ActiveSync_State_Base
*/
- protected $_stateMachine;
+ protected $_state;
/**
+ * The backend driver for communicating with the server we are syncing with.
*
* @var Horde_ActiveSync_Driver_Base
*/
protected $_backend;
/**
- * Sync key for current request
*
- * @var string
- */
- protected $_syncKey;
-
- /**
* @TODO
* @var <type>
*/
* Const'r
*
* @param Horde_ActiveSync_Driver_Base $backend
- * @param Horde_ActiveSync_StateMachine_Base $stateMachine
- * @param <type> $syncKey
- * @param <type> $flags
*/
public function __construct(Horde_ActiveSync_Driver_Base $backend)
{
$this->_backend = $backend;
}
- public function init(Horde_ActiveSync_State_Base &$stateMachine,
- $folderId, $syncKey, $flags = 0)
+ /**
+ * Initialize the exporter for this collection
+ *
+ * @param Horde_ActiveSync_State_Base $state The state machine
+ * @param string $folderId The collection's id
+ * @param integer $flags Any flags
+ */
+ public function init(Horde_ActiveSync_State_Base &$state, $folderId, $flags = 0)
{
- $this->_stateMachine = &$stateMachine;
- $this->_syncKey = $syncKey;
+ $this->_state = &$state;
$this->_flags = $flags;
$this->_folderId = $folderId;
}
+ /**
+ * Setter for a logger instance
+ *
+ * @param Horde_Log_Logger $logger The logger
+ */
public function setLogger($logger)
{
$this->_logger = $logger;
}
/**
+ * Import a message change from the wbxml stream
*
* @param mixed $id A server message id or
* false if a new message
*/
public function ImportMessageChange($id, $message)
{
- //do nothing if it is in a dummy folder
+ /* do nothing if it is in a dummy folder */
if ($this->_folderId == SYNC_FOLDER_TYPE_DUMMY) {
return false;
}
+ /* Changing an existing object */
if ($id) {
- // See if there's a conflict
+ /* Check for conflicts */
$conflict = $this->_isConflict('change', $this->_folderId, $id);
- // Update client state if this is an update
+ /* Update client state */
$change = array();
$change['id'] = $id;
$change['mod'] = 0; // dummy, will be updated later if the change succeeds
$change['parent'] = $this->_folderId;
$change['flags'] = (isset($message->read)) ? $message->read : 0;
- $this->_stateMachine->updateState('change', $change);
+ $this->_state->updateState('change', $change);
- if ($conflict && $this->_flags == SYNC_CONFLICT_OVERWRITE_PIM) {
+ /* If this is a conflict, see if the server wins */
+ if ($conflict && $this->_flags == Horde_ActiveSync::CONFLICT_OVERWRITE_PIM) {
return true;
}
}
+ /* Tell the backend about the change */
$stat = $this->_backend->ChangeMessage($this->_folderId, $id, $message);
- // @TODO: Isn't this an error?
if (!is_array($stat)) {
return $stat;
}
- // Record the state of the message
- $this->_stateMachine->updateState('change', $stat);
+ /* Record the state of the message */
+ $this->_state->updateState('change', $stat);
return $stat['id'];
}
/**
- * Import a deletion. This may conflict if the local object has been
+ * Import a message deletion. This may conflict if the local object has been
* modified.
*
- * @param string $id Server message id
+ * @param string $id Server message uid
+ *
+ * @return boolean
*/
public function ImportMessageDeletion($id)
{
- //do nothing if it is in a dummy folder
+ /* Do nothing if it is in a dummy folder */
if ($this->_folderId == SYNC_FOLDER_TYPE_DUMMY) {
return true;
}
- // See if there's a conflict
+ /* Check for conflict */
$conflict = $this->_isConflict('delete', $this->_folderId, $id);
- // Update client state
+ /* Update client state */
$change = array();
$change['id'] = $id;
- $this->_stateMachine->updateState('delete', $change);
+ $this->_state->updateState('delete', $change);
- // If there is a conflict, and the server 'wins', then return OK without
- // performing the change this will cause the exporter to 'see' the
- // overriding item as a change, and send it back to the PIM
- if ($conflict && $this->_flags == SYNC_CONFLICT_OVERWRITE_PIM) {
+ /* If server wins the conflict, don't import change - it will be
+ * detected on next sync and sent back to PIM (since we updated the PIM
+ * state). */
+ if ($conflict && $this->_flags == Horde_ActiveSync::CONFLICT_OVERWRITE_PIM) {
return true;
}
+ /* Tell backend about the deletion */
$this->_backend->DeleteMessage($this->_folderId, $id);
return true;
*/
public function ImportMessageReadFlag($id, $flags)
{
- //do nothing if it is a dummy folder
+ /* Do nothing if it is a dummy folder */
if ($this->_folderId == SYNC_FOLDER_TYPE_DUMMY) {
return true;
}
- // Update client state
+ /* Update client state */
$change = array();
$change['id'] = $id;
$change['flags'] = $flags;
- $this->_stateMachine->updateState('flags', $change);
+ $this->_state->updateState('flags', $change);
+
+ /* Tell backend */
$this->_backend->SetReadFlag($this->_folderId, $id, $flags);
return true;
}
/**
- * Not supported/todo?
+ * Perform a message move initiated on the PIM.
+ *
+ * @TODO
*
- * @param <type> $id
- * @param <type> $newfolder
- * @return <type>
+ * @param string $id The message id
+ * @param $newfolder
+ *
+ * @return boolean
*/
public function ImportMessageMove($id, $newfolder)
{
}
/**
+ * Import a folder change from the wbxml stream
+ *
+ * @param string $id The folder id
+ * @param string $parent The parent folder id?
+ * @param string $displayname The folder display name
+ * @param <unknown_type> $type The collection type?
*
- * @param $id
- * @param $parent
- * @param $displayname
- * @param $type
- * @return unknown_type
+ * @return boolean
*/
public function ImportFolderChange($id, $parent, $displayname, $type)
{
- //do nothing if it is a dummy folder
+ /* do nothing if it is a dummy folder */
if ($parent == SYNC_FOLDER_TYPE_DUMMY) {
return false;
}
$change['mod'] = $displayname;
$change['parent'] = $parent;
$change['flags'] = 0;
- $this->_stateMachine->updateState('change', $change);
+ $this->_state->updateState('change', $change);
}
- // @TODO: ChangeFolder did not exist in ZPush's code??
+ /* Tell the backend */
$stat = $this->_backend->ChangeFolder($parent, $id, $displayname, $type);
if ($stat) {
- $this->_stateMachine->updateState('change', $stat);
+ $this->_state->updateState('change', $stat);
}
return $stat['id'];
}
/**
+ * Imports a folder deletion from the PIM
+ *
+ * @param string $id The folder id
+ * @param string $parent The folder id of the parent folder
*
- * @param $id
- * @param $parent
- * @return unknown_type
+ * @return boolean
*/
public function ImportFolderDeletion($id, $parent)
{
- //do nothing if it is a dummy folder
+ /* Do nothing if it is a dummy folder */
if ($parent == SYNC_FOLDER_TYPE_DUMMY) {
return false;
}
$change = array();
$change['id'] = $id;
- $this->_stateMachine->updateState('delete', $change);
+ $this->_state->updateState('delete', $change);
$this->_backend->DeleteFolder($parent, $id);
return true;
}
/**
- * Returns TRUE if the given ID conflicts with the given operation.
+ * Check if this change conflicts with server changes
* This is only true in the following situations:
*
* Changed here and changed there
*
* Any other combination of operations can be done
* (e.g. change flags & move or move & delete)
+ *
+ * @param string $type The type of change('change', 'delete' etc...)
+ * @param string $folderid The id of the folder this change is from.
+ * @param string $id The uid for the changed message.
+ *
+ * @return boolean
*/
protected function _isConflict($type, $folderid, $id)
{
$stat = $this->_backend->StatMessage($folderid, $id);
if (!$stat) {
- // Message is gone
+ /* Message is gone, if type is change, this is a conflict */
if ($type == 'change') {
return true;
} else {
- return false; // all other remote changes still result in a delete (no conflict)
+ return false;
}
}
- return $this->_stateMachine->isConflict($stat, $type);
+ return $this->_state->isConflict($stat, $type);
}
}