* @category Horde * @copyright 2012-2017 Horde LLC * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 * @package Imap_Client * @since 2.2.0 * * @property-read Horde_Imap_Client_Ids $flagsuids List of messages with flag * changes. * @property-read Horde_Imap_Client_Ids $newmsgsuids List of new messages. * @property-read Horde_Imap_Client_Ids $vanisheduids List of messages that * have vanished. */ class Horde_Imap_Client_Data_Sync { /** * Mappings of status() values to sync keys. * * @since 2.8.0 * * @var array */ public static $map = array( 'H' => 'highestmodseq', 'M' => 'messages', 'U' => 'uidnext', 'V' => 'uidvalidity' ); /** * Are there messages that have had flag changes? * * @var boolean */ public $flags = null; /** * The previous value of HIGHESTMODSEQ. * * @since 2.8.0 * * @var integer */ public $highestmodseq = null; /** * The synchronized mailbox. * * @var Horde_Imap_Client_Mailbox */ public $mailbox; /** * The previous number of messages in the mailbox. * * @since 2.8.0 * * @var integer */ public $messages = null; /** * Are there new messages? * * @var boolean */ public $newmsgs = null; /** * The previous value of UIDNEXT. * * @since 2.8.0 * * @var integer */ public $uidnext = null; /** * The previous value of UIDVALIDITY. * * @since 2.8.0 * * @var integer */ public $uidvalidity = null; /** * The UIDs of messages that are guaranteed to have vanished. This list is * only guaranteed to be available if the server supports QRESYNC or a * list of known UIDs is passed to the sync() method. * * @var Horde_Imap_Client_Ids */ public $vanished = null; /** * UIDs of messages that have had flag changes. * * @var Horde_Imap_Client_Ids */ protected $_flagsuids; /** * UIDs of new messages. * * @var Horde_Imap_Client_Ids */ protected $_newmsgsuids; /** * UIDs of messages that have vanished. * * @var Horde_Imap_Client_Ids */ protected $_vanisheduids; /** * Constructor. * * @param Horde_Imap_Client_Base $base_ob Base driver object. * @param mixed $mailbox Mailbox to sync. * @param array $sync Token sync data. * @param array $curr Current sync data. * @param integer $criteria Mask of criteria to return. * @param Horde_Imap_Client_Ids $ids List of known UIDs. * * @throws Horde_Imap_Client_Exception * @throws Horde_Imap_Client_Exception_Sync */ public function __construct(Horde_Imap_Client_Base $base_ob, $mailbox, $sync, $curr, $criteria, $ids) { foreach (self::$map as $key => $val) { if (isset($sync[$key])) { $this->$val = $sync[$key]; } } /* Check uidvalidity. */ if (!$this->uidvalidity || ($curr['V'] != $this->uidvalidity)) { throw new Horde_Imap_Client_Exception_Sync('UIDs in cached mailbox have changed.', Horde_Imap_Client_Exception_Sync::UIDVALIDITY_CHANGED); } $this->mailbox = $mailbox; /* This was a UIDVALIDITY check only. */ if (!$criteria) { return; } $sync_all = ($criteria & Horde_Imap_Client::SYNC_ALL); /* New messages. */ if ($sync_all || ($criteria & Horde_Imap_Client::SYNC_NEWMSGS) || ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) { $this->newmsgs = empty($this->uidnext) ? !empty($curr['U']) : (!empty($curr['U']) && ($curr['U'] > $this->uidnext)); if ($this->newmsgs && ($sync_all || ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS))) { $new_ids = empty($this->uidnext) ? Horde_Imap_Client_Ids::ALL : ($this->uidnext . ':' . $curr['U']); $squery = new Horde_Imap_Client_Search_Query(); $squery->ids(new Horde_Imap_Client_Ids($new_ids)); $sres = $base_ob->search($mailbox, $squery); $this->_newmsgsuids = $sres['match']; } } /* Do single status call to get all necessary data. */ if ($this->highestmodseq && ($sync_all || ($criteria & Horde_Imap_Client::SYNC_FLAGS) || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS) || ($criteria & Horde_Imap_Client::SYNC_VANISHED) || ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS))) { $status_sync = $base_ob->status($mailbox, Horde_Imap_Client::STATUS_SYNCMODSEQ | Horde_Imap_Client::STATUS_SYNCFLAGUIDS | Horde_Imap_Client::STATUS_SYNCVANISHED); if (!is_null($ids)) { $ids = $base_ob->resolveIds($mailbox, $ids); } } /* Flag changes. */ if ($sync_all || ($criteria & Horde_Imap_Client::SYNC_FLAGS)) { $this->flags = $this->highestmodseq ? ($this->highestmodseq != $curr['H']) : true; } if ($sync_all || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS)) { if ($this->highestmodseq) { if ($this->highestmodseq == $status_sync['syncmodseq']) { $this->_flagsuids = is_null($ids) ? $status_sync['syncflaguids'] : $base_ob->getIdsOb(array_intersect($ids->ids, $status_sync['syncflaguids']->ids)); } else { $squery = new Horde_Imap_Client_Search_Query(); $squery->modseq($this->highestmodseq + 1); $sres = $base_ob->search($mailbox, $squery, array( 'ids' => $ids )); $this->_flagsuids = $sres['match']; } } else { /* Without MODSEQ, need to mark all FLAGS as changed. */ $this->_flagsuids = $base_ob->resolveIds($mailbox, is_null($ids) ? $base_ob->getIdsOb(Horde_Imap_Client_Ids::ALL) : $ids); } } /* Vanished messages. */ if ($sync_all || ($criteria & Horde_Imap_Client::SYNC_VANISHED) || ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) { if ($this->highestmodseq && ($this->highestmodseq == $status_sync['syncmodseq'])) { $vanished = is_null($ids) ? $status_sync['syncvanished'] : $base_ob->getIdsOb(array_intersect($ids->ids, $status_sync['syncvanished']->ids)); } else { $vanished = $base_ob->vanished($mailbox, $this->highestmodseq ? $this->highestmodseq : 1, array( 'ids' => $ids )); } $this->vanished = (bool)count($vanished); $this->_vanisheduids = $vanished; } } /** */ public function __get($name) { switch ($name) { case 'flagsuids': case 'newmsgsuids': case 'vanisheduids': return empty($this->{'_' . $name}) ? new Horde_Imap_Client_Ids() : $this->{'_' . $name}; } } }