, addedSeq: int, modSeq: int, removedSeq: ?int}>> by UIDVALIDITY and UID */ private array $documents = []; public function upsert(string $tenantId, string $serviceId, int $uidValidity, EntityResource $entity, int $seq): void { $meta = $entity->toCacheMeta(); $existing = $this->documents[$uidValidity][$meta['uid']] ?? null; $this->documents[$uidValidity][$meta['uid']] = [ 'meta' => $meta, 'flags' => $meta['flags'], 'addedSeq' => $existing['addedSeq'] ?? $seq, 'modSeq' => $seq, 'removedSeq' => null, ]; ksort($this->documents[$uidValidity]); } /** Last query() arguments, for assertions */ public ?array $lastQuery = null; /** * Live UIDs in ascending order; the filter / sort translation is covered by MessageQueryBuilderTest. */ public function query(string $serviceId, string $mailbox, int $uidValidity, array $filter = [], array $sort = ['uid' => 1], ?array $collation = null): array { $this->lastQuery = [$filter, $sort, $collation]; return array_keys($this->flags($serviceId, $mailbox, $uidValidity)); } public function fetchMany(string $serviceId, string $mailbox, int $uidValidity, int ...$uids): array { $list = []; foreach ($uids as $uid) { $document = $this->documents[$uidValidity][$uid] ?? null; if ($document !== null && $document['removedSeq'] === null) { $list[$uid] = [...$document['meta'], 'uid' => $uid, 'flags' => $document['flags']]; } } return $list; } public function flags(string $serviceId, string $mailbox, int $uidValidity): array { $flags = []; foreach ($this->documents[$uidValidity] ?? [] as $uid => $document) { if ($document['removedSeq'] === null) { $flags[$uid] = $document['flags']; } } return $flags; } public function updateFlags(string $serviceId, string $mailbox, int $uidValidity, int $uid, array $flags, int $seq): void { $this->documents[$uidValidity][$uid]['flags'] = array_values($flags); $this->documents[$uidValidity][$uid]['modSeq'] = $seq; } public function tombstone(string $serviceId, string $mailbox, int $uidValidity, int $seq, int ...$uids): void { foreach ($uids as $uid) { $this->documents[$uidValidity][$uid]['removedSeq'] = $seq; $this->documents[$uidValidity][$uid]['modSeq'] = $seq; $this->documents[$uidValidity][$uid]['flags'] = []; } } public function changes(string $serviceId, string $mailbox, int $uidValidity, int $since): array { $changes = ['additions' => [], 'modifications' => [], 'deletions' => []]; foreach ($this->documents[$uidValidity] ?? [] as $uid => $document) { if ($document['removedSeq'] !== null) { if ($document['addedSeq'] <= $since && $document['removedSeq'] > $since) { $changes['deletions'][] = $uid; } } elseif ($document['addedSeq'] > $since) { $changes['additions'][] = $uid; } elseif ($document['modSeq'] > $since) { $changes['modifications'][] = $uid; } } return $changes; } public function deleteByMailbox(string $serviceId, string $mailbox): void { $this->documents = []; } }