From: Michael M Slusarz Date: Tue, 25 Nov 2008 04:01:04 +0000 (-0700) Subject: Fix mailbox updating so it doesn't break on message actions. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=973ed7eb1d2e51ff781b68b62d6ee7fd796d3918;p=horde.git Fix mailbox updating so it doesn't break on message actions. Still need to think yet more about how (or if) we should reimplement message list caching, but that can be done later. --- diff --git a/imp/lib/Mailbox.php b/imp/lib/Mailbox.php index 0fc3fba52..026ba881c 100644 --- a/imp/lib/Mailbox.php +++ b/imp/lib/Mailbox.php @@ -353,8 +353,8 @@ class IMP_Mailbox */ public function getMessageIndex() { - return is_null($this->_arrayIndex) - ? (is_null($this->_lastArrayIndex) ? 1 : $this->_lastArrayIndex + 1) + return (is_null($this->_arrayIndex) && is_null($this->_lastArrayIndex)) + ? 1 : $this->_arrayIndex + 1; } @@ -365,9 +365,7 @@ class IMP_Mailbox */ public function getMessageCount() { - if (!$GLOBALS['imp_search']->isVFolder($this->_mailbox)) { - $this->_buildMailbox(); - } + $this->_buildMailbox(); return count($this->_sorted); } @@ -379,7 +377,7 @@ class IMP_Mailbox */ public function isValidIndex() { - $this->_sortIfNeeded(); + $this->_rebuild(); return !is_null($this->_arrayIndex); } @@ -488,7 +486,6 @@ class IMP_Mailbox } } - print_r($page_uid); if (empty($page)) { $page = is_null($page_uid) ? 1 @@ -556,7 +553,7 @@ class IMP_Mailbox if (empty($this->_sorted[$this->_arrayIndex])) { $this->_arrayIndex = null; } - $this->_sortIfNeeded(); + $this->_rebuild(); } break; @@ -586,78 +583,23 @@ class IMP_Mailbox } /** - * Determines if a resort is needed, and, if necessary, performs - * the resort. + * Determines if a rebuild is needed, and, if necessary, performs + * the rebuild. + * + * @param boolean $force Force a rebuild? */ - protected function _sortIfNeeded() + protected function _rebuild($force = false) { - if (!is_null($this->_arrayIndex) && - !$this->_searchmbox && - !$this->getIMAPIndex(1)) { + if ($force || + (!is_null($this->_arrayIndex) && + !$this->_searchmbox && + !$this->getIMAPIndex(1))) { $this->_build = false; $this->_buildMailbox(); } } /** - * Returns the current sorted array without the given messages. - * - * @param array $msgs The indices to remove. - * - * @return boolean True if sorted array was updated without a call to - * _buildMailbox(). - */ - protected function _removeMsgs($msgs) - { - if (empty($msgs)) { - return; - } - - if (!($msgList = IMP::parseIndicesList($msgs))) { - $msgList = array($this->_mailbox => $msgs); - } - - $msgcount = 0; - $sortcount = count($this->_sorted); - - /* Remove the current entry and recalculate the range. */ - foreach ($msgList as $key => $val) { - // @todo $arrival is false here - foreach ($val as $index) { - $val = $this->getArrayIndex($index, $key); - if ($arrival !== false && isset($this->_sorted[$val])) { - unset($arrival[$this->_sorted[$val]]); - } - unset($this->_sorted[$val]); - if ($this->_searchmbox) { - unset($this->_sortedInfo[$val]); - } - ++$msgcount; - } - } - - $this->_sorted = array_values($this->_sorted); - if ($this->_searchmbox) { - $this->_sortedInfo = array_values($this->_sortedInfo); - } - - /* Update the current array index to its new position in the message - * array. */ - $this->setIndex(0, 'offset'); - - /* If we have a sortlimit, it is possible the sort prefs will have - * changed after messages are expunged. */ - if (!empty($GLOBALS['conf']['server']['sort_limit']) && - ($sortcount > $GLOBALS['conf']['server']['sort_limit']) && - (($sortcount - $msgcount) <= $GLOBALS['conf']['server']['sort_limit'])) { - $this->updateMailbox(self::UPDATE); - return false; - } - - return true; - } - - /** * Returns the array index of the given message UID. * * @param integer $uid The message UID. @@ -718,19 +660,54 @@ class IMP_Mailbox } /** - * Returns a unique identifier for the current mailbox status. + * Returns the current sorted array without the given messages. * - * @return string The cache ID string, which will change when the status - * of the mailbox changes. + * @param mixed $msgs The list of indices to remove (see + * IMP::parseIndicesList()) or true to remove all + * messages in the mailbox. */ - public function getCacheID() + public function removeMsgs($msgs) { - try { - $sortpref = IMP::getSort($this->_mailbox); - $ret = $GLOBALS['imp_imap']->ob->status($this->_mailbox, Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_UIDNEXT | Horde_Imap_Client::STATUS_UIDVALIDITY); - return implode('|', array($ret['messages'], $ret['uidnext'], $ret['uidvalidity'], $sortpref['by'], $sortpref['dir'])); - } catch (Horde_Imap_Client_Exception $e) { - return ''; + if ($msgs === true) { + $this->_rebuild(true); + return; + } + + if (empty($msgs)) { + return; + } + + $msgcount = 0; + $sortcount = count($this->_sorted); + + /* Remove the current entry and recalculate the range. */ + foreach (IMP::parseIndicesList($msgs) as $key => $val) { + foreach ($val as $index) { + $val = $this->getArrayIndex($index, $key); + unset($this->_sorted[$val]); + if ($this->_searchmbox) { + unset($this->_sortedInfo[$val]); + } + ++$msgcount; + } + } + + $this->_sorted = array_values($this->_sorted); + if ($this->_searchmbox) { + $this->_sortedInfo = array_values($this->_sortedInfo); + } + + /* Update the current array index to its new position in the message + * array. */ + $this->setIndex(0, 'offset'); + + /* If we have a sortlimit, it is possible the sort prefs will have + * changed after messages are expunged. */ + if (!empty($GLOBALS['conf']['server']['sort_limit']) && + ($sortcount > $GLOBALS['conf']['server']['sort_limit']) && + (($sortcount - $msgcount) <= $GLOBALS['conf']['server']['sort_limit'])) { + $this->_rebuild(true); } } + } diff --git a/imp/lib/Message.php b/imp/lib/Message.php index 914839ea9..1875ed835 100644 --- a/imp/lib/Message.php +++ b/imp/lib/Message.php @@ -5,11 +5,6 @@ * handled in here so that code need not be repeated between mailbox, message, * and other pages. * - * Indices format: - * =============== - * For any function below that requires an $indices parameter, see - * IMP::parseIndicesList() for the list of allowable inputs. - * * Copyright 2000-2001 Chris Hyde * Copyright 2000-2008 The Horde Project (http://www.horde.org/) * @@ -35,6 +30,13 @@ class IMP_Message protected $_usepop = false; /** + * An IMP_Mailbox object to update on message actions. + * + * @var IMP_Mailbox + */ + protected $_mailboxOb = null; + + /** * Returns a reference to the global IMP_Message object, only creating it * if it doesn't already exist. This ensures that only one IMP_Message * instance is instantiated for any given session. @@ -67,14 +69,24 @@ class IMP_Message } /** - * Copies or moves a list of messages to a new folder. - * Handles use of the IMP::SEARCH_MBOX mailbox and the Trash folder. + * Set the IMP_Mailbox object to update on message actions. + * + * @param IMP_Mailbox &$ob An IMP_Mailbox object. + */ + public function updateMailboxOb(&$ob) + { + $this->_mailboxOb = $ob; + } + + /** + * Copies or moves a list of messages to a new mailbox. + * Handles use of the IMP::SEARCH_MBOX mailbox and the Trash mailbox. * * @param string $targetMbox The mailbox to move/copy messages to * (UTF7-IMAP). * @param integer $action Either IMP_Message::MOVE or * IMP_Message::COPY. - * @param mixed $indices See above. + * @param mixed $indices See IMP::parseIndicesList(). * @param boolean $new Whether the target mailbox has to be created. * * @return boolean True if successful, false if not. @@ -126,18 +138,21 @@ class IMP_Message break; } - foreach ($msgList as $folder => $msgIndices) { - if (($action == self::MOVE) && $imp_imap->isReadOnly($folder)) { - $notification->push(sprintf($message, IMP::displayFolder($folder), IMP::displayFolder($targetMbox)) . ': ' . _("The target directory is read-only."), 'horde.error'); + foreach ($msgList as $mbox => $msgIndices) { + if (($action == self::MOVE) && $imp_imap->isReadOnly($mbox)) { + $notification->push(sprintf($message, IMP::displayFolder($mbox), IMP::displayFolder($targetMbox)) . ': ' . _("The target directory is read-only."), 'horde.error'); $return_value = false; continue; } /* Attempt to copy/move messages to new mailbox. */ try { - $imp_imap->ob->copy($folder, $targetMbox, array('ids' => $msgIndices, 'move' => $imap_move)); + $imp_imap->ob->copy($mbox, $targetMbox, array('ids' => $msgIndices, 'move' => $imap_move)); + if (!is_null($this->_mailboxOb)) { + $this->_mailboxOb->removeMsgs(array($mbox => $msgIndices)); + } } catch (Horde_Imap_Client_Exception $e) { - //$notification->push(sprintf($message, IMP::displayFolder($folder), IMP::displayFolder($targetMbox)) . ': ' . imap_last_error(), 'horde.error'); + $notification->push(sprintf($message, IMP::displayFolder($mbox), IMP::displayFolder($targetMbox)) . ': ' . imap_last_error(), 'horde.error'); $return_value = false; } } @@ -150,7 +165,7 @@ class IMP_Message * Trash folder is being used. * Handles use of the IMP::SEARCH_MBOX mailbox and the Trash folder. * - * @param mixed $indices See above. + * @param mixed $indices See IMP::parseIndicesList(). * @param boolean $nuke Override user preferences and nuke (i.e. * permanently delete) the messages instead? * @param boolean $keeplog Should any history information of the @@ -204,6 +219,9 @@ class IMP_Message if ($use_trash_folder && ($mbox != $trash)) { try { $imp_imap->ob->copy($mbox, $trash, array('ids' => $msgIndices, 'move' => true)); + if (!is_null($this->_mailboxOb)) { + $this->_mailboxOb->removeMsgs(array($mbox => $msgIndices)); + } } catch (Horde_Imap_Client_Exception $e) { // @todo Check for overquota error. return false; @@ -268,7 +286,7 @@ class IMP_Message * Handles the IMP::SEARCH_MBOX mailbox. * This function works with IMAP only, not POP3. * - * @param mixed $indices See above. + * @param mixed $indices See IMP::parseIndicesList(). * * @return boolean True if successful, false if not. */ @@ -284,7 +302,7 @@ class IMP_Message * @param string $list The list in which the task or note will be * created. * @param integer $action Either IMP_Message::MOVE or IMP_Message::COPY. - * @param mixed $indices See above. + * @param mixed $indices See IMP::parseIndicesList(). * @param string $type The object type to create, defaults to task. * * @return boolean True if successful, false if not. @@ -518,7 +536,7 @@ class IMP_Message * This function works with IMAP only, not POP3. * * @param array $flags The IMAP flag(s) to set or clear. - * @param mixed $indices See above. + * @param mixed $indices See IMP::parseIndicesList(). * @param boolean $action If true, set the flag(s), otherwise clear the * flag(s). * @@ -629,6 +647,9 @@ class IMP_Message foreach ($process_list as $key => $val) { try { $imp_imap->ob->expunge($key, array('ids' => is_array($val) ? $val : array())); + if (!is_null($this->_mailboxOb)) { + $this->_mailboxOb->removeMsgs(is_array($val) ? array($key => $val) : true); + } $update_list[$key] = $val; } catch (Horde_Imap_Client_Exception $e) {} } diff --git a/imp/message.php b/imp/message.php index cd516ea17..2a23f837c 100644 --- a/imp/message.php +++ b/imp/message.php @@ -44,6 +44,10 @@ if (!$imp_mailbox->isValidIndex()) { exit; } +/* Update IMP_Mailbox on message actions. */ +$imp_message = &IMP_Message::singleton(); +$imp_message->updateMailboxOb($imp_mailbox); + /* Set the current time zone. */ NLS::setTimeZone();