From b682b0629c6b65ca8dc8f29108ecb42b4b335861 Mon Sep 17 00:00:00 2001 From: Sebastian Krupinski Date: Tue, 5 May 2026 22:32:52 -0400 Subject: [PATCH] feat: colleciton delete Signed-off-by: Sebastian Krupinski --- lib/Controllers/DefaultController.php | 44 ++++++++++++++++++++++++++- lib/Manager.php | 5 ++- src/services/collectionService.ts | 10 ++++-- src/services/entityService.ts | 1 - src/stores/collectionsStore.ts | 22 ++++++++++++-- src/types/collection.ts | 3 +- 6 files changed, 74 insertions(+), 11 deletions(-) diff --git a/lib/Controllers/DefaultController.php b/lib/Controllers/DefaultController.php index ef9a9cf..2e20ae0 100644 --- a/lib/Controllers/DefaultController.php +++ b/lib/Controllers/DefaultController.php @@ -549,7 +549,7 @@ class DefaultController extends ControllerAbstract { throw new InvalidArgumentException(self::ERR_INVALID_IDENTIFIER); } - return $this->mailManager->collectionDelete( + $result = $this->mailManager->collectionDelete( $tenantId, $userId, $data['provider'], @@ -557,6 +557,48 @@ class DefaultController extends ControllerAbstract { $data['identifier'], $data['options'] ?? [] ); + + if (is_bool($result)) { + return [ + 'outcome' => 'deleted' + ]; + } + + if ($result instanceof JsonSerializable) { + return [ + 'outcome' => 'moved', + 'data' => $result + ]; + } + + return $result; + } + + private function collectionMove(string $tenantId, string $userId, array $data): mixed { + if (!isset($data['target'])) { + throw new InvalidArgumentException(self::ERR_MISSING_TARGET); + } + if (!is_string($data['target'])) { + throw new InvalidArgumentException(self::ERR_INVALID_TARGET); + } + if (!isset($data['sources'])) { + throw new InvalidArgumentException(self::ERR_MISSING_SOURCES); + } + if (!is_array($data['sources'])) { + throw new InvalidArgumentException(self::ERR_INVALID_SOURCES); + } + + $target = ResourceIdentifier::fromString($data['target']); + if (!$target instanceof CollectionIdentifier) { + throw new InvalidArgumentException('Invalid parameter: target must be provider:service:collection'); + } + + $source = ResourceIdentifier::fromArray($data['source']); + if (!$source instanceof CollectionIdentifier) { + throw new InvalidArgumentException('Invalid parameter: sources must contain provider:service:collection identifiers'); + } + + return $this->mailManager->collectionMove($tenantId, $userId, $target, $source); } // ==================== Entity Operations ==================== diff --git a/lib/Manager.php b/lib/Manager.php index 97de2c4..43276d1 100644 --- a/lib/Manager.php +++ b/lib/Manager.php @@ -653,7 +653,7 @@ class Manager { * * @return CollectionBaseInterface|null */ - public function collectionDelete(string $tenantId, ?string $userId, string $providerId, string|int $serviceId, string|int $collectionId, array $options = []): bool { + public function collectionDelete(string $tenantId, ?string $userId, string $providerId, string|int $serviceId, string|int $collectionId, array $options = []): CollectionBaseInterface | bool { // retrieve service $service = $this->serviceFetch($tenantId, $userId, $providerId, $serviceId); @@ -666,10 +666,9 @@ class Manager { } $force = $options['force'] ?? false; - $recursive = $options['recursive'] ?? false; // delete collection - return $service->collectionDelete($collectionId, $force, $recursive); + return $service->collectionDelete($collectionId, $force); } // ==================== Message Operations ==================== diff --git a/src/services/collectionService.ts b/src/services/collectionService.ts index b255576..aabb2b7 100644 --- a/src/services/collectionService.ts +++ b/src/services/collectionService.ts @@ -123,8 +123,14 @@ export const collectionService = { * * @returns Promise with deletion result */ - async delete(request: CollectionDeleteRequest): Promise { - return await transceivePost('collection.delete', request); + async delete(request: CollectionDeleteRequest): Promise { + const response = await transceivePost('collection.delete', request); + + if (response.outcome === 'moved' && response.data) { + return createCollectionObject(response.data); + } + + return true; }, }; diff --git a/src/services/entityService.ts b/src/services/entityService.ts index dd365e6..4db39b4 100644 --- a/src/services/entityService.ts +++ b/src/services/entityService.ts @@ -26,7 +26,6 @@ import type { EntityStreamRequest, EntityStreamResponse, } from '../types/entity'; -import type { EntityIdentifier } from '../types/common'; import { useIntegrationStore } from '@KTXC/stores/integrationStore'; import { EntityObject } from '../models'; diff --git a/src/stores/collectionsStore.ts b/src/stores/collectionsStore.ts index 8d361d9..3246144 100644 --- a/src/stores/collectionsStore.ts +++ b/src/stores/collectionsStore.ts @@ -385,12 +385,16 @@ export const useCollectionsStore = defineStore('mailCollectionsStore', () => { * * @returns Promise with deletion result */ - async function remove(provider: string, service: string | number, identifier: string | number): Promise { + async function remove(provider: string, service: string | number, identifier: string | number): Promise { transceiving.value = true try { - await collectionService.delete({ provider, service, identifier }) + const response = await collectionService.delete({ provider, service, identifier }) - // Remove deleted collection from state + if (response !== true && !(response instanceof CollectionObject)) { + console.warn('[Mail Manager][Store] - Delete failed. Received unexpected response from delete operation:', response) + return false + } + const key = identifierKey(provider, service, identifier) const previousCollection = _collections.value[key] @@ -400,7 +404,19 @@ export const useCollectionsStore = defineStore('mailCollectionsStore', () => { delete _collections.value[key] + if (response instanceof CollectionObject) { + const movedCollection = response + const movedKey = identifierKey(movedCollection.provider, movedCollection.service, movedCollection.identifier) + + _collections.value[movedKey] = movedCollection + indexCollection(movedCollection) + + console.debug('[Mail Manager][Store] - Successfully moved collection to trash', key, '->', movedKey) + return response + } + console.debug('[Mail Manager][Store] - Successfully deleted collection:', key) + return response } catch (error: any) { console.error('[Mail Manager][Store] - Failed to delete collection:', error) throw error diff --git a/src/types/collection.ts b/src/types/collection.ts index 6ac1595..bc6ec19 100644 --- a/src/types/collection.ts +++ b/src/types/collection.ts @@ -124,5 +124,6 @@ export interface CollectionDeleteRequest { } export interface CollectionDeleteResponse { - success: boolean; + outcome: 'deleted' | 'moved'; + data?: CollectionInterface | null; // If moved, the new location of the collection } -- 2.39.5