/**
* Import a message change from the wbxml stream
*
* @param string|boolean $id A server message id or
* false if a new message.
* @param Horde_ActiveSync_Message_Base $message A message object
* @param Horde_ActiveSync_Device $device A device descriptor
* @param integer $clientid Client id sent from client.
* on message addition.
* @param string $class The collection class - needed for SMS since the
* actual serverid will be for an email folder.
* @since 2.6.0
* @param string $synckey The synckey currently being processed when
* processing a SYNC_MODIFY command.
* @since 2.31.0
*
* @todo Revisit passing $class for SMS. Probably pass class in the
* const'r.
*
* @return array|boolean A stat array, or an array containing the 'error'
* key on error, or false on duplicate addition.
*/
public function importMessageChange($id, Horde_ActiveSync_Message_Base $message, Horde_ActiveSync_Device $device, $clientid, $class = false, $synckey = false)
{
// Don't support SMS, but can't tell client that. Send back a phoney
// UID for any imported SMS objects.
if ($class == Horde_ActiveSync::CLASS_SMS || strpos($id, 'IGNORESMS_') === 0) {
return 'IGNORESMS_' . $clientid;
}
// Changing an existing object
if ($id && $this->_flags == Horde_ActiveSync::CONFLICT_OVERWRITE_PIM) {
// This is complicated by the fact that in EAS 16.0, clients
// will send a CHANGE for adding/editing an exception along with
// a seperate change with the entire appointment - even if nothing
// else has changed. This leads to conficts (since the appointment
// is marked as changed after the first edit). Sniff that out here
// and prevent the conflict check for those messages.
if (!$message instanceof Horde_ActiveSync_Message_Appointment && $this->_state->isDuplicatePIMChange($id, $synckey)) {
$conflict = $this->_isConflict(Horde_ActiveSync::CHANGE_TYPE_CHANGE, $this->_folderId, $id);
if ($conflict) {
$this->_logger->notice(sprintf('[%s] Conflict when updating %s, will overwrite client version on next sync.', $this->_procid, $id));
return array($id, 'error' => array(Horde_ActiveSync_Request_Sync::STATUS_CONFLICT));
}
}
} elseif (!$id && ($uid = $this->_state->isDuplicatePIMAddition($clientid))) {
// Already saw this addition, but client never received UID
$this->_logger->notice(sprintf('[%s] Duplicate addition for %s', $this->_procid, $uid));
return $uid;
}
// Set the supported/ghosted data if this is a SYNC_MODIFY.
if ($id && !empty($device->supported[$class])) {
$message->setSupported($device->supported[$class]);
}
// Tell the backend about the change
if (!($stat = $this->_as->driver->changeMessage($this->_folderId, $id, $message, $device))) {
$this->_logger->err(sprintf('[%s] Change message failed when updating %s', $this->_procid, $id));
return $id ? array(0 => $id, 'error' => Horde_ActiveSync_Request_Sync::STATUS_NOTFOUND) : array(0 => false, 'error' => Horde_ActiveSync_Request_Sync::STATUS_SERVERERROR);
}
$stat['serverid'] = $this->_folderId;
// Record the state of the message.
// Email messages are only changed if they are Drafts or if we are
// updating flags.
// When CHANGING a draft message, we are actually deleting the old one
// and replacing it with a message (since we can't edit an existing
// IMAP message while keeping the UID the same). So, do not call
// updateState() for these messages since we don't want to ignore
// this as a PIM sourced change - the change will be caught during
// normal ping/sync cycle.
if ($message instanceof Horde_ActiveSync_Message_Mail) {
if (!empty($message->airsyncbasebody) && !empty($id)) {
// Changing an existing Draft mail.
return $stat;
}
// Either a flag change, or adding a new Draft mail.
$changeType = !empty($message->airsyncbasebody) ? Horde_ActiveSync::CHANGE_TYPE_DRAFT : Horde_ActiveSync::CHANGE_TYPE_FLAGS;
} else {
$changeType = Horde_ActiveSync::CHANGE_TYPE_CHANGE;
}
$this->_state->updateState($changeType, $stat, Horde_ActiveSync::CHANGE_ORIGIN_PIM, $this->_as->driver->getUser(), $clientid);
return $stat;
}