refactor: role based mailbox resolution

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-09-26 21:46:34 -04:00
parent 025812fe4e
commit ec6bdcf7fd
+51 -57
View File
@@ -474,31 +474,15 @@ class Service implements ServiceBaseInterface, ServiceMutableInterface, ServiceC
$this->initialize();
$deleteMode = $this->auxiliary['deleteMode'] ?? 'soft';
$deleteTarget = $this->auxiliary['deleteTarget'] ?? null;
if ($deleteMode !== 'soft' && $deleteMode !== 'hard') {
throw new \InvalidArgumentException("Invalid delete mode: $deleteMode");
}
// Move to target collection (e.g. Trash) instead of deleting
if ($deleteMode === 'soft' && $deleteTarget !== null) {
return $this->collectionMove(new CollectionIdentifier($target->provider(), $target->service(), $deleteTarget), $target);
}
if ($deleteMode === 'soft' && $deleteTarget === null) {
$filter = $this->collectionListFilter();
$filter->condition('role', CollectionRoles::Trash->value);
$mailboxes = iterator_to_array($this->remoteService->collectionList(null, $filter, null));
if (empty($mailboxes)) {
throw new \RuntimeException('No Trash collection configured or found for deletion');
}
$deleteTarget = key($mailboxes);
}
$deleteTarget = $deleteMode === 'soft' ? $this->resolveDeleteDestination() : null;
// we need to determine if the folder being deleted is already in the trash
if (str_starts_with((string) $target->collection(), (string) $deleteTarget)) {
if ($deleteTarget !== null && str_starts_with((string) $target->collection(), $deleteTarget)) {
// if so, we should hard delete instead of moving to avoid duplicates in the trash
$deleteMode = 'hard';
}
@@ -699,23 +683,6 @@ class Service implements ServiceBaseInterface, ServiceMutableInterface, ServiceC
);
}
/**
* Resolve the native name of the collection flagged with the Sent role.
*/
private function resolveSentCollection(): ?string
{
$filter = $this->collectionListFilter();
$filter->condition('role', CollectionRoles::Sent->value);
/** @var Mailbox[] $mailboxes */
$mailboxes = iterator_to_array($this->remoteService->collectionList(null, $filter, null));
if ($mailboxes === []) {
return null;
}
$mailbox = reset($mailboxes);
return $mailbox === false ? null : $mailbox->name();
}
public function entityCreate(CollectionIdentifier $target, MessagePropertiesMutableInterface $properties, array $options = []): EntityResource
{
if ($target->provider() !== $this->provider() || (string)$target->service() !== (string)$this->identifier()) {
@@ -799,7 +766,6 @@ class Service implements ServiceBaseInterface, ServiceMutableInterface, ServiceC
// determine delete mode and target collection (e.g. Trash) if applicable
$deleteMode = $this->auxiliary['deleteMode'] ?? 'soft';
$deleteTarget = $this->auxiliary['deleteTarget'] ?? null;
if ($deleteMode !== 'soft' && $deleteMode !== 'hard') {
throw new \InvalidArgumentException("Invalid delete mode: $deleteMode");
@@ -808,26 +774,10 @@ class Service implements ServiceBaseInterface, ServiceMutableInterface, ServiceC
// connect to remote store
$this->initialize();
// attempt to find a target collection for soft deletion if none was specified
if ($deleteMode === 'soft' && $deleteTarget === null) {
$filter = $this->collectionListFilter();
$filter->condition('role', CollectionRoles::Trash->value);
/** @var Mailbox[] $mailboxes */
$mailboxes = iterator_to_array($this->remoteService->collectionList(null, $filter, null));
if (empty($mailboxes)) {
throw new \RuntimeException('No Trash collection configured or found for deletion');
}
$targetMailbox = reset($mailboxes);
if ($targetMailbox === false) {
throw new \RuntimeException('No Trash collection configured or found for deletion');
}
$deleteTargetNative = $targetMailbox->name();
$deleteTargetIdentifier = new CollectionIdentifier($this->provider(), (string) $this->identifier(), $deleteTargetNative);
} else {
$deleteTargetNative = $deleteTarget;
$deleteTargetNative = null;
$deleteTargetIdentifier = null;
if ($deleteMode === 'soft') {
$deleteTargetNative = $this->resolveDeleteDestination();
$deleteTargetIdentifier = new CollectionIdentifier($this->provider(), (string) $this->identifier(), $deleteTargetNative);
}
@@ -930,6 +880,51 @@ class Service implements ServiceBaseInterface, ServiceMutableInterface, ServiceC
return $list;
}
/**
* Resolve the native name of the first collection flagged with the given role.
*/
private function resolveRoleCollection(CollectionRoles $role): ?string
{
$filter = $this->collectionListFilter();
$filter->condition('role', $role->value);
/** @var Mailbox[] $mailboxes */
$mailboxes = iterator_to_array($this->remoteService->collectionList(null, $filter, null));
if ($mailboxes === []) {
return null;
}
$mailbox = reset($mailboxes);
return $mailbox === false ? null : $mailbox->name();
}
/**
* Resolve the native name of the collection flagged with the Sent role.
*/
private function resolveSentCollection(): ?string
{
return $this->resolveRoleCollection(CollectionRoles::Sent);
}
/**
* Resolve the native name of the collection soft-deleted messages and collections are moved to.
*/
private function resolveDeleteDestination(): string
{
$destination = trim((string) ($this->auxiliary['deleteDestination'] ?? ''));
if ($destination === '') {
return $this->resolveRoleCollection(CollectionRoles::Trash)
?? throw new \RuntimeException('No Trash collection configured or found for deletion');
}
$role = CollectionRoles::tryFrom(strtolower($destination));
if ($role !== null && $role !== CollectionRoles::None) {
return $this->resolveRoleCollection($role) ?? $destination;
}
return $destination;
}
private function groupEntitiesByCollection(EntityIdentifier ...$identifiers): array
{
$list = [];
@@ -982,5 +977,4 @@ class Service implements ServiceBaseInterface, ServiceMutableInterface, ServiceC
return [(new MessageBuilder())->build($properties), $flags];
}
}