clientFactory = $clientFactory; $this->synchronizer = $synchronizer; $this->filterStringParser = $filterStringParser; $this->messageMapper = $messageMapper; $this->previewEnhancer = $previewEnhancer; $this->logger = $logger; $this->mailboxSync = $mailboxSync; } /** * @param Account $account * @param Mailbox $mailbox * * @throws MailboxLockedException * @throws ServiceException */ public function clearCache(Account $account, Mailbox $mailbox): void { $this->synchronizer->clearCache($account, $mailbox); } /** * Run a (rather costly) sync to delete cached messages which are not present on IMAP anymore. * * @throws MailboxLockedException * @throws ServiceException */ public function repairSync(Account $account, Mailbox $mailbox): void { $this->synchronizer->repairSync($account, $mailbox, $this->logger); } /** * @param Account $account * @param Mailbox $mailbox * @param int $criteria * @param bool $partialOnly * @param string|null $filter * * @param int[] $knownIds * * @return Response * @throws ClientException * @throws MailboxNotCachedException * @throws ServiceException */ public function syncMailbox(Account $account, Mailbox $mailbox, int $criteria, bool $partialOnly, ?int $lastMessageTimestamp, ?array $knownIds = null, string $sortOrder = IMailSearch::ORDER_NEWEST_FIRST, ?string $filter = null): Response { if ($partialOnly && !$mailbox->isCached()) { throw MailboxNotCachedException::from($mailbox); } $client = $this->clientFactory->getClient($account); $this->synchronizer->sync( $account, $client, $mailbox, $this->logger, $criteria, $knownIds === null ? null : $this->messageMapper->findUidsForIds($mailbox, $knownIds), !$partialOnly ); $this->mailboxSync->syncStats($client, $mailbox); $client->logout(); $query = $filter === null ? null : $this->filterStringParser->parse($filter); return $this->getDatabaseSyncChanges( $account, $mailbox, $knownIds ?? [], $lastMessageTimestamp, $sortOrder, $query ); } /** * @param Account $account * @param Mailbox $mailbox * @param int[] $knownIds * @param SearchQuery $query * * @return Response * @todo does not work with text token search queries * */ private function getDatabaseSyncChanges(Account $account, Mailbox $mailbox, array $knownIds, ?int $lastMessageTimestamp, string $sortOrder, ?SearchQuery $query): Response { if ($knownIds === []) { $newIds = $this->messageMapper->findAllIds($mailbox); } else { $newIds = $this->messageMapper->findNewIds($mailbox, $knownIds, $lastMessageTimestamp, $sortOrder); } $order = $sortOrder === 'oldest' ? IMailSearch::ORDER_OLDEST_FIRST : IMailSearch::ORDER_NEWEST_FIRST; if ($query !== null) { // Filter new messages to those that also match the current filter $newUids = $this->messageMapper->findUidsForIds($mailbox, $newIds); $newIds = $this->messageMapper->findIdsByQuery($mailbox, $query, $order, null, $newUids); } $new = $this->messageMapper->findByMailboxAndIds($mailbox, $account->getUserId(), $newIds); // TODO: $changed = $this->messageMapper->findChanged($account, $mailbox, $uids); if ($query !== null) { $changedUids = $this->messageMapper->findUidsForIds($mailbox, $knownIds); $changedIds = $this->messageMapper->findIdsByQuery($mailbox, $query, $order, null, $changedUids); } else { $changedIds = $knownIds; } $changed = $this->messageMapper->findByMailboxAndIds($mailbox, $account->getUserId(), $changedIds); $stillKnownIds = array_map(static fn (Message $msg) => $msg->getId(), $changed); $vanished = array_values(array_diff($knownIds, $stillKnownIds)); return new Response( $this->previewEnhancer->process($account, $mailbox, $new), $changed, $vanished, $mailbox->getStats() ); } }