* SPDX-License-Identifier: AGPL-3.0-or-later */ namespace KTXM\ProviderImap\Stores; use KTXC\Db\DataStore; use KTXM\ProviderImap\Providers\CollectionResource; /** * IMAP Mailbox Meta Store * * One MongoDB document per cached mailbox in `provider_imap_mail_mailboxes`, * keyed by (sid, name). The document holds the mailbox itself and its * harmonization state. */ class MailboxStore { protected const COLLECTION_NAME = 'provider_imap_mail_mailboxes'; public function __construct( protected readonly DataStore $dataStore, ) {} /** * Create the collection indexes. * * MongoDB createIndex is idempotent when the name and specification match. * * @return string[] */ public function ensureIndexes(): array { $collection = $this->dataStore->selectCollection(self::COLLECTION_NAME); return [ $collection->createIndex( ['sid' => 1, 'name' => 1], ['name' => 'mailboxes_key', 'unique' => true] ), $collection->createIndex( ['tid' => 1, 'sid' => 1], ['name' => 'mailboxes_by_tenant_service'] ), ]; } /** * Insert or update the mailbox fields of a document. * * Harmonization state on the same document is left untouched. */ public function upsert(string $tenantId, string $serviceId, CollectionResource $collection): void { $document = $collection->toCacheMeta(); $this->dataStore->selectCollection(self::COLLECTION_NAME)->updateOne( ['sid' => $serviceId, 'name' => $document['name']], ['$set' => ['tid' => $tenantId, 'sid' => $serviceId, ...$document]], ['upsert' => true], ); } /** * Retrieve the document of a mailbox. */ public function fetch(string $serviceId, string $name): ?array { return $this->dataStore->selectCollection(self::COLLECTION_NAME)->findOne([ 'sid' => $serviceId, 'name' => $name, ]); } /** * List the documents of all mailboxes of a service. * * @return array keyed by mailbox name */ public function list(string $serviceId): array { $cursor = $this->dataStore->selectCollection(self::COLLECTION_NAME)->find(['sid' => $serviceId]); $list = []; foreach ($cursor as $document) { $list[(string) $document['name']] = $document; } return $list; } /** * Delete the document of a mailbox. */ public function delete(string $serviceId, string $name): void { $this->dataStore->selectCollection(self::COLLECTION_NAME)->deleteOne([ 'sid' => $serviceId, 'name' => $name, ]); } /** * Delete the documents of all mailboxes of a service. */ public function deleteByService(string $serviceId): void { $this->dataStore->selectCollection(self::COLLECTION_NAME)->deleteMany(['sid' => $serviceId]); } }