Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions lib/Ajax/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,6 @@ public function changed($rw = null)
return true;
}

/* Only update search mailboxes on forced refreshes. */
if ($this->indices->mailbox->search) {
return !empty($this->_vars->forceUpdate);
}

if (!$this->_vars->viewport->cacheid) {
return false;
}
Expand Down Expand Up @@ -414,6 +409,11 @@ public function getAddrFields()
*/
public function deleteMsgs(IMP_Indices $indices, $changed, $force = false)
{
/* Search results may have been invalidated during deletion. */
if (!$changed) {
$changed = $this->changed(true);
}

/* Check if we need to update thread information. */
if (!$changed) {
$changed = ($this->indices->mailbox->getSort()->sortby == Horde_Imap_Client::SORT_THREAD);
Expand Down
8 changes: 7 additions & 1 deletion lib/Contents.php
Original file line number Diff line number Diff line change
Expand Up @@ -1322,8 +1322,14 @@ public function getPartName(Horde_Mime_Part $part, $use_descrip = false)
*/
protected function _fetchData(Horde_Imap_Client_Fetch_Query $query)
{
$mbox = $this->getMailbox();
if (!$mbox) {
$e = new IMP_Exception(_('Error displaying message: message does not exist on server.'));
$e->setLogLevel('NOTICE');
throw $e;
}

try {
$mbox = $this->getMailbox();
$imp_imap = $mbox->imp_imap;
return $imp_imap->fetch($mbox, $query, [
'ids' => $imp_imap->getIdsOb($this->getUid()),
Expand Down
34 changes: 30 additions & 4 deletions lib/Indices.php
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ public function copy($targetMbox, $action, array $opts = [])
}
$imap_move = false;
$return_value = true;
$affected_mailboxes = [];

switch ($action) {
case 'move':
Expand Down Expand Up @@ -326,6 +327,11 @@ public function copy($targetMbox, $action, array $opts = [])
'ids' => $imp_imap->getIdsOb($ob->uids),
'move' => $imap_move,
]);

if ($imap_move) {
$affected_mailboxes[strval($ob->mbox)] = $ob->mbox;
$affected_mailboxes[strval($targetMbox)] = $targetMbox;
}
} catch (Exception $e) {
$error_msg = sprintf(
$message,
Expand All @@ -343,6 +349,12 @@ public function copy($targetMbox, $action, array $opts = [])
}
}

if ($return_value && $imap_move && !empty($affected_mailboxes)) {
$GLOBALS['injector']->getInstance('IMP_Search')->invalidateMailboxes(
array_values($affected_mailboxes)
);
}

return $return_value;
}

Expand Down Expand Up @@ -385,6 +397,7 @@ public function delete(array $opts = [])
? $injector->getInstance('IMP_Maillog')
: null;
$return_value = 0;
$affected_mailboxes = [];

/* Check for Trash mailbox. */
$no_expunge = $use_trash_mbox = $use_vtrash = false;
Expand Down Expand Up @@ -428,12 +441,9 @@ public function delete(array $opts = [])
continue;
}

if ($return_value !== false) {
$return_value += count($ob->uids);
}

$imp_imap = $ob->mbox->imp_imap;
$ids_ob = $imp_imap->getIdsOb($ob->uids);
$processed = false;

/* Trash is only valid for IMAP mailboxes. */
if ($use_trash_mbox
Expand All @@ -453,6 +463,9 @@ public function delete(array $opts = [])
'ids' => $ids_ob,
'move' => true,
]);
$affected_mailboxes[strval($ob->mbox)] = $ob->mbox;
$affected_mailboxes[strval($trash)] = $trash;
$processed = true;
} catch (IMP_Imap_Exception $e) {
if ($e->getCode() == $e::OVERQUOTA) {
$notification->push(
Expand Down Expand Up @@ -510,9 +523,22 @@ public function delete(array $opts = [])
new IMP_Indices($ob->mbox, $ids_ob)
);
}

$affected_mailboxes[strval($ob->mbox)] = $ob->mbox;
$processed = true;
} catch (IMP_Imap_Exception $e) {
}
}

if ($processed && ($return_value !== false)) {
$return_value += count($ob->uids);
}
}

if ($return_value !== false && !empty($affected_mailboxes)) {
$injector->getInstance('IMP_Search')->invalidateMailboxes(
array_values($affected_mailboxes)
);
}

return $return_value;
Expand Down
29 changes: 22 additions & 7 deletions lib/Mailbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -1363,6 +1363,15 @@ public function expunge($to_expunge = [], array $opts = [])
}
}

if (!empty($update_list)) {
$GLOBALS['injector']->getInstance('IMP_Search')->invalidateMailboxes(
array_filter(array_map(
[IMP_Mailbox::class, 'get'],
array_keys($update_list)
))
);
}

if ($msg_list) {
return new IMP_Indices($update_list);
}
Expand Down Expand Up @@ -1591,8 +1600,8 @@ public static function prefTo($mbox)
* from the mailbox. Additionally, if CONDSTORE is available on the remote
* IMAP server, this ID will change if flag information changes.
*
* For search mailboxes, this value never changes (search mailboxes must
* be forcibly refreshed).
* For search mailboxes, this value changes when underlying mailbox
* contents change or when search display preferences change.
*
* @param boolean $date If true, adds date information to ID.
*
Expand All @@ -1601,16 +1610,12 @@ public static function prefTo($mbox)
*/
protected function _getCacheID($date = false)
{
global $prefs;
global $injector, $prefs;

$date = $date
? 'D' . date('z')
: '';

if ($this->search) {
return '1' . ($date ? '|' . $date : '');
}

$sortpref = $this->getSort(true);
$addl = [
$sortpref->sortby,
Expand All @@ -1621,6 +1626,16 @@ protected function _getCacheID($date = false)
$addl[] = $date;
}

if ($this->search) {
$cache_gen = 0;
$imp_search = $injector->getInstance('IMP_Search');
if ($imp_search->offsetExists($this->_mbox)) {
$cache_gen = $imp_search[$this->_mbox]->cacheGeneration();
}

return $cache_gen . '|' . implode('|', $addl);
}

try {
return $this->imp_imap->getCacheId($this->_mbox, $addl);
} catch (IMP_Imap_Exception $e) {
Expand Down
59 changes: 59 additions & 0 deletions lib/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,65 @@ public function isSearchMbox($id)
return (strpos($id, self::MBOX_PREFIX) === 0);
}

/**
* Invalidate cached search results for queries that include the given
* mailboxes.
*
* @param array $mboxes List of IMP_Mailbox objects and/or mailbox names.
*/
public function invalidateMailboxes(array $mboxes)
{
global $injector;

if (empty($mboxes)) {
return;
}

$mboxes = array_unique(array_filter(array_map(
'strval',
array_map([IMP_Mailbox::class, 'get'], $mboxes)
)));

$list_factory = $injector->getInstance('IMP_Factory_MailboxList');

foreach (['query', 'vfolders'] as $type) {
foreach ($this->_search[$type] as $query) {
if (!$this->_queryAffected($query, $mboxes)) {
continue;
}

$query->invalidateCache();
$list_factory->create($query->mid)->rebuild(true);
$this->changed = true;
}
}
}

/**
* Does a search query include any of the given mailboxes?
*
* @param IMP_Search_Query $query Search query object.
* @param array $mboxes List of mailbox names.
*
* @return boolean
*/
protected function _queryAffected(IMP_Search_Query $query, array $mboxes)
{
if ($query->all) {
return true;
}

$mboxes = array_flip($mboxes);

foreach ($query->mboxes as $mbox) {
if (isset($mboxes[strval($mbox)])) {
return true;
}
}

return false;
}

/**
* Strip the identifying label from a mailbox ID.
*
Expand Down
34 changes: 34 additions & 0 deletions lib/Search/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ class IMP_Search_Query implements Serializable
*/
protected $_cache = [];

/**
* Cache generation. Incremented when underlying mailbox contents change.
*
* @var integer
*/
protected $_cacheGen = 0;

/**
* Can this query be edited?
*
Expand Down Expand Up @@ -326,6 +333,25 @@ public function replace(array $criteria = [])
}
}

/**
* Return the cache generation for this query.
*
* @return integer
*/
public function cacheGeneration()
{
return $this->_cacheGen;
}

/**
* Invalidate cached search results for this query.
*/
public function invalidateCache()
{
++$this->_cacheGen;
$this->_cache = [];
}

/**
* Reduce the sorted return ID list by running search element callbacks..
*
Expand Down Expand Up @@ -366,6 +392,7 @@ public function serialize()
'm' => $this->_mboxes,
'v' => self::VERSION,
]);
$data['g'] = $this->_cacheGen;

foreach ($this->_nosave as $val) {
unset($data[$val]);
Expand All @@ -383,6 +410,7 @@ public function __serialize(): array
'm' => $this->_mboxes,
'v' => self::VERSION,
]);
$data['g'] = $this->_cacheGen;

foreach ($this->_nosave as $val) {
unset($data[$val]);
Expand Down Expand Up @@ -420,6 +448,9 @@ public function unserialize($data)
if (isset($data['m'])) {
$this->_mboxes = $data['m'];
}
if (isset($data['g'])) {
$this->_cacheGen = $data['g'];
}
}
public function __unserialize(array $data): void
{
Expand All @@ -441,5 +472,8 @@ public function __unserialize(array $data): void
if (isset($data['m'])) {
$this->_mboxes = $data['m'];
}
if (isset($data['g'])) {
$this->_cacheGen = $data['g'];
}
}
}
Loading