mirror of
https://github.com/nextcloud/mail.git
synced 2026-01-13 20:23:59 +00:00
162 lines
4.2 KiB
PHP
162 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
|
* SPDX-FileCopyrightText: 2016 owncloud, Inc.
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
namespace OCA\Mail\Cache;
|
|
|
|
use Horde_Imap_Client_Cache_Backend;
|
|
use OCA\Mail\Account;
|
|
use OCA\Mail\Db\MailboxMapper;
|
|
use OCA\Mail\Db\MessageMapper;
|
|
|
|
/**
|
|
* This class passes the minimum amount of data from the db cache to Horde to make QRESYNC work
|
|
* reliably.
|
|
*/
|
|
class Cache extends Horde_Imap_Client_Cache_Backend {
|
|
/** @var CachedMailbox[] */
|
|
private array $cachedMailboxes = [];
|
|
|
|
public function __construct(
|
|
private MessageMapper $dbMessageMapper,
|
|
private MailboxMapper $mailboxMapper,
|
|
private HordeSyncTokenParser $syncTokenParser,
|
|
private Account $account,
|
|
) {
|
|
parent::__construct();
|
|
}
|
|
|
|
#[\Override]
|
|
public function get($mailbox, $uids, $fields, $uidvalid) {
|
|
// Don't forward any data related to individual messages
|
|
return [];
|
|
}
|
|
|
|
private function getOrInsertCachedMailbox(string $mailbox): CachedMailbox {
|
|
if (!isset($this->cachedMailboxes[$mailbox])) {
|
|
$this->cachedMailboxes[$mailbox] = new CachedMailbox();
|
|
}
|
|
|
|
return $this->cachedMailboxes[$mailbox];
|
|
}
|
|
|
|
#[\Override]
|
|
public function getCachedUids($mailbox, $uidvalid) {
|
|
$cachedMailbox = $this->getOrInsertCachedMailbox($mailbox);
|
|
|
|
// Delete cached data of mailbox if uidvalid has changed
|
|
$cachedUidvalid = $cachedMailbox->getUidValidity();
|
|
if ($uidvalid !== null
|
|
&& $cachedUidvalid !== null
|
|
&& $cachedUidvalid !== (int)$uidvalid
|
|
) {
|
|
$this->deleteMailbox($mailbox);
|
|
$cachedMailbox = $this->getOrInsertCachedMailbox($mailbox);
|
|
}
|
|
|
|
// Refresh cached uids lazily
|
|
$cachedUids = $cachedMailbox->getUids();
|
|
if ($cachedUids === null) {
|
|
$mailboxEntity = $this->mailboxMapper->find($this->account, $mailbox);
|
|
$cachedUids = $this->dbMessageMapper->findAllUids($mailboxEntity);
|
|
$cachedMailbox->setUids($cachedUids);
|
|
}
|
|
|
|
// Copy the array because we don't know whether horde will mutate it
|
|
return array_merge([], $cachedUids);
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
#[\Override]
|
|
public function set($mailbox, $data, $uidvalid) {
|
|
// Don't mutate any data related to individual messages
|
|
}
|
|
|
|
#[\Override]
|
|
public function getMetaData($mailbox, $uidvalid, $entries) {
|
|
$cachedMailbox = $this->getOrInsertCachedMailbox($mailbox);
|
|
|
|
// Ensure that uidvalid is always set (see the default null cache implementation)
|
|
$md = ['uidvalid' => 0];
|
|
|
|
// Lazily load uidvalid and highestmodseq values from the database
|
|
if ($cachedMailbox->getUidValidity() === null || $cachedMailbox->getHighestModSeq() === null) {
|
|
$mailboxEntity = $this->mailboxMapper->find($this->account, $mailbox);
|
|
$syncToken = $mailboxEntity->getSyncNewToken();
|
|
if ($syncToken !== null) {
|
|
$parsedToken = $this->syncTokenParser->parseSyncToken($syncToken);
|
|
if ($parsedToken->getUidValidity()) {
|
|
$cachedMailbox->setUidValidity($parsedToken->getUidValidity());
|
|
}
|
|
if ($parsedToken->getHighestModSeq()) {
|
|
$cachedMailbox->setHighestModSeq($parsedToken->getHighestModSeq());
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($cachedMailbox->getUidValidity() !== null) {
|
|
$md['uidvalid'] = $cachedMailbox->getUidValidity();
|
|
}
|
|
|
|
if ($cachedMailbox->getHighestModSeq() !== null) {
|
|
$md['_m'] = $cachedMailbox->getHighestModSeq();
|
|
}
|
|
|
|
return $md;
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
#[\Override]
|
|
public function setMetaData($mailbox, $data) {
|
|
// Don't mutate any metadata.
|
|
// The data will be refreshed once the new sync token is written to the db.
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
#[\Override]
|
|
public function deleteMsgs($mailbox, $uids) {
|
|
$mailboxEntity = $this->mailboxMapper->find($this->account, $mailbox);
|
|
$this->dbMessageMapper->deleteByUid($mailboxEntity, ...$uids);
|
|
|
|
if (!isset($this->cachedMailboxes[$mailbox])) {
|
|
return;
|
|
}
|
|
|
|
$cachedMailbox = $this->cachedMailboxes[$mailbox];
|
|
$cachedUids = $cachedMailbox->getUids();
|
|
if ($cachedUids === null) {
|
|
return;
|
|
}
|
|
|
|
$cachedMailbox->setUids(array_diff($cachedUids, $uids));
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
#[\Override]
|
|
public function deleteMailbox($mailbox) {
|
|
unset($this->cachedMailboxes[$mailbox]);
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
#[\Override]
|
|
public function clear($lifetime) {
|
|
$this->cachedMailboxes = [];
|
|
}
|
|
}
|