From: Michael M Slusarz Date: Mon, 1 Feb 2010 04:15:02 +0000 (-0700) Subject: Add Horde_Imap_Client_Base::parseCacheId(). X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=19e297b60a4724b53866b555fd021c5f6f7e501f;p=horde.git Add Horde_Imap_Client_Base::parseCacheId(). This makes all cache ID generation internal to Horde_Imap_Client, which is desirable. Additionally, for CONDSTORE hosts, we should use the last modseq seen with respect to the *browser*, not the server. This ensures that all changes are caught when the browser does a request - if a browser misses a request, for example, it may not catch the changes. --- diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Base.php b/framework/Imap_Client/lib/Horde/Imap/Client/Base.php index e3fb75996..5e566f088 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client/Base.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Base.php @@ -2701,6 +2701,8 @@ abstract class Horde_Imap_Client_Base * Returns a unique identifier for the current mailbox status. * * @param string $mailbox A mailbox. Either in UTF7-IMAP or UTF-8. + * @param array $addl Additional cache info to add to the cache ID + * string. * * @return string The cache ID string, which will change when the * composition of the mailbox changes. The uidvalidity @@ -2708,35 +2710,74 @@ abstract class Horde_Imap_Client_Base * by the '|' character. * @throws Horde_Imap_Client_Exception */ - public function getCacheId($mailbox) + public function getCacheId($mailbox, $addl = array()) { $query = Horde_Imap_Client::STATUS_UIDVALIDITY; /* Use MODSEQ as cache ID if CONDSTORE extension is available. */ if (isset($this->_init['enabled']['CONDSTORE'])) { - $condstore = true; $query |= Horde_Imap_Client::STATUS_HIGHESTMODSEQ; } else { - $condstore = false; $query |= Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_UIDNEXT; } $status = $this->status($mailbox, $query); - if ($condstore) { - return implode('|', array($status['uidvalidity'], $status['highestmodseq'])); + if ($query & Horde_Imap_Client::STATUS_HIGHESTMODSEQ) { + $parts = array( + 'V' . $status['uidvalidity'], + 'H' . $status['highestmodseq'] + ); + } else { + if (empty($status['uidnext'])) { + /* UIDNEXT is not strictly required on mailbox open. If it is + * not available, use the last UID in the mailbox instead. */ + $this->_temp['nocache'] = true; + $search_res = $this->_getSeqUIDLookup(array($status['messages']), true); + unset($this->_temp['nocache']); + $status['uidnext'] = reset($search_res['uids']); + } + + $parts = array( + 'V' . $status['uidvalidity'], + 'U' . $status['uidnext'], + 'M' . $status['messages'] + ); } - if (empty($status['uidnext'])) { - /* UIDNEXT is not strictly required on mailbox open. If it is - * not available, use the last UID in the mailbox instead. */ - $this->_temp['nocache'] = true; - $search_res = $this->_getSeqUIDLookup(array($status['messages']), true); - unset($this->_temp['nocache']); - $status['uidnext'] = reset($search_res['uids']); + return implode('|', array_merge($parts, $addl)); + } + + /** + * Parses a cacheID created by getCacheId(). + * + * @param string $id The cache ID. + * + * @return array An array with the following information: + *
+     * 'highestmodseq' - (integer)
+     * 'messages' - (integer)
+     * 'uidnext' - (integer)
+     * 'uidvalidity' - (integer) Always present
+     * 
+ */ + public function parseCacheId($id) + { + $data = array( + 'H' => 'highestmodseq', + 'M' => 'messages', + 'U' => 'uidnext', + 'V' => 'uidvalidity' + ); + $info = array(); + + foreach (explode('|', $id) as $part) { + if (isset($data[$part[0]])) { + $info[$data[$part[0]]] = intval(substr($part, 1)); + } } - return implode('|', array($status['uidvalidity'], $status['uidnext'], $status['messages'])); + return $info; } /** diff --git a/framework/Imap_Client/package.xml b/framework/Imap_Client/package.xml index 0bd4ef2a9..e45d3ece6 100644 --- a/framework/Imap_Client/package.xml +++ b/framework/Imap_Client/package.xml @@ -31,7 +31,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> alpha LGPL - * Added STATUS_LASTMODSEQ and STATUS_LASTMODSEQUIDS status() entries. + * Add Horde_Imap_Client_Base::parseCacheId(). + * Added STATUS_LASTMODSEQ and STATUS_LASTMODSEQUIDS status() entries. * Add support for LIST-STATUS (draft-ietf-morg-status-in-list-01). * Add support for THREAD=REFS (draft-ietf-morg-inthread-00). * Add support for RFC 5258 (LIST-EXTENDED). diff --git a/imp/lib/Mailbox.php b/imp/lib/Mailbox.php index 032cf49a3..9ad758b91 100644 --- a/imp/lib/Mailbox.php +++ b/imp/lib/Mailbox.php @@ -833,8 +833,7 @@ class IMP_Mailbox if (!$this->_searchmbox) { $sortpref = IMP::getSort($this->_mailbox); try { - $id = $GLOBALS['imp_imap']->ob()->getCacheId($this->_mailbox); - return $id . '|' . $sortpref['by'] . '|' . $sortpref['dir']; + return $GLOBALS['imp_imap']->ob()->getCacheId($this->_mailbox, array($sortpref['by'], $sortpref['dir'])); } catch (Horde_Imap_Client_Exception $e) {} } diff --git a/imp/lib/Views/ListMessages.php b/imp/lib/Views/ListMessages.php index 2783d6309..58a92f059 100644 --- a/imp/lib/Views/ListMessages.php +++ b/imp/lib/Views/ListMessages.php @@ -150,8 +150,8 @@ class IMP_Views_ListMessages $uid_expire = false; try { $status = $GLOBALS['imp_imap']->ob()->status($mbox, Horde_Imap_Client::STATUS_UIDVALIDITY); - list($old_uidvalid,) = explode('|', $args['cacheid']); - $uid_expire = ($old_uidvalid != $status['uidvalidity']); + $parsed = $GLOBALS['imp_imap']->ob()->parseCacheId($args['cacheid']); + $uid_expire = ($parsed['uidvalidity'] != $status['uidvalidity']); } catch (Horde_Imap_Cache_Exception $e) { $uid_expire = true; } @@ -181,10 +181,17 @@ class IMP_Views_ListMessages /* Check for cached entries marked as changed via CONDSTORE * IMAP extension. If changed, resend the entire entry to * update the browser cache (done below). */ - if ($args['change']) { - $status = $GLOBALS['imp_imap']->ob()->status($mbox, Horde_Imap_Client::STATUS_LASTMODSEQUIDS); - if (!empty($status['lastmodsequids'])) { - $changed = array_flip($status['lastmodsequids']); + if ($args['change'] && $args['cacheid']) { + if (!isset($parsed)) { + $parsed = $GLOBALS['imp_imap']->ob()->parseCacheId($args['cacheid']); + } + if (!empty($parsed['highestmodseq'])) { + try { + $res = $GLOBALS['imp_imap']->ob()->fetch($mbox, array(Horde_Imap_Client::FETCH_UID => 1), array('changedsince' => $parsed['highestmodseq'])); + if (!empty($res)) { + $changed = array_flip(array_keys($res)); + } + } catch (Horde_Imap_Client_Exception $e) {} } } }