diff --git a/lib/Controllers/DefaultController.php b/lib/Controllers/DefaultController.php index 386dd52..869f09b 100644 --- a/lib/Controllers/DefaultController.php +++ b/lib/Controllers/DefaultController.php @@ -160,7 +160,7 @@ class DefaultController extends ControllerAbstract { 'entity.extant' => $this->entityExtant($tenantId, $userId, $data), 'entity.create' => throw new InvalidArgumentException('Operation not implemented: ' . $operation), 'entity.update' => throw new InvalidArgumentException('Operation not implemented: ' . $operation), - 'entity.delete' => throw new InvalidArgumentException('Operation not implemented: ' . $operation), + 'entity.delete' => $this->entityDelete($tenantId, $userId, $data), 'entity.stream' => $this->entityStream($tenantId, $userId, $data, $version, $transaction), 'entity.delta' => $this->entityDelta($tenantId, $userId, $data), 'entity.move' => $this->entityMove($tenantId, $userId, $data), @@ -640,6 +640,24 @@ class DefaultController extends ControllerAbstract { return $this->mailManager->entityDelta($tenantId, $userId, $sources); } + private function entityDelete(string $tenantId, string $userId, array $data): mixed { + if (!isset($data['sources'])) { + throw new InvalidArgumentException(self::ERR_MISSING_SOURCES); + } + if (!is_array($data['sources'])) { + throw new InvalidArgumentException(self::ERR_INVALID_SOURCES); + } + + $sources = ResourceIdentifiers::fromArray($data['sources']); + foreach ($sources as $source) { + if (!$source instanceof EntityIdentifier) { + throw new InvalidArgumentException('Invalid parameter: sources must contain provider:service:collection:entity identifiers'); + } + } + + return $this->mailManager->entityDelete($tenantId, $userId, $sources); + } + private function entityMove(string $tenantId, string $userId, array $data): mixed { if (!isset($data['target'])) { throw new InvalidArgumentException(self::ERR_MISSING_TARGET); diff --git a/lib/Manager.php b/lib/Manager.php index b739f24..acd768b 100644 --- a/lib/Manager.php +++ b/lib/Manager.php @@ -981,24 +981,105 @@ class Manager { return $responseData; } + public function entityDelete(string $tenantId, string $userId, ResourceIdentifiers $sources): array { + $operationOutcome = []; + + foreach ($sources->providers() as $providerName) { + $providerSources = $sources->byProvider($providerName); + foreach ($providerSources->services() as $serviceName) { + $serviceSources = $providerSources->byService($serviceName); + + $service = null; + try { + $service = $this->serviceFetch($tenantId, $userId, $providerName, $serviceName); + } catch (\Throwable $e) { + // Service not found, mark all identifiers as failed + } + + if ($service === null) { + foreach ($serviceSources as $identifier) { + $operationOutcome[(string)$identifier] = [ + 'success' => false, + 'error' => 'serviceNotFound', + ]; + } + continue; + } + + // Temporarily disabled check until all methods are properly implemented from ServiceEntityMutableInterface + /* + if (!($service instanceof ServiceEntityMutableInterface)) { + foreach ($serviceSources as $identifier) { + $operationOutcome[(string)$identifier] = [ + 'success' => false, + 'error' => 'serviceNotEntityMutable', + ]; + } + continue; + } + + if (!$service->capable(ServiceEntityMutableInterface::CAPABILITY_ENTITY_DELETE)) { + foreach ($serviceSources as $identifier) { + $operationOutcome[(string)$identifier] = [ + 'success' => false, + 'error' => 'serviceCannotDeleteEntities', + ]; + } + continue; + } + */ + + try { + $operationResult = $service->entityDelete(...$serviceSources->all()); + + foreach ($serviceSources as $identifier) { + $sourceIdentifier = (string)$identifier; + $entityIdentifier = $identifier->entity(); + $result = $operationResult[$entityIdentifier] ?? null; + + if ($result === true) { + $operationOutcome[$sourceIdentifier] = [ + 'success' => true, + ]; + continue; + } + + $operationOutcome[$sourceIdentifier] = [ + 'success' => false, + 'error' => is_string($result) && $result !== '' ? $result : 'unknownError', + ]; + } + } catch (\Throwable $e) { + foreach ($serviceSources as $identifier) { + $operationOutcome[(string)$identifier] = [ + 'success' => false, + 'error' => $e->getMessage(), + ]; + } + } + } + } + + return $operationOutcome; + } + public function entityMove(string $tenantId, string $userId, CollectionIdentifier $target, ResourceIdentifiers $sources): array { $targetService = $this->serviceFetch($tenantId, $userId, $target->provider(), $target->service()); // Check if service supports entity move + // Temporarily disabled check until all methods are properly implemented from ServiceEntityMutableInterface + /* if ($targetService instanceof ServiceEntityMutableInterface === false) { - //return []; + return []; } + */ $operationOutcome = []; $destinationSources = $sources->byProvider($targetService->provider())->byService((string)$targetService->identifier()); if (!$destinationSources->isEmpty()) { - $entitiesToMove = []; - foreach ($destinationSources as $identifier) { - $entitiesToMove[$identifier->collection()][] = $identifier->entity(); - } - $operationResult = $targetService->entityMove($target->collection(), $entitiesToMove); + $operationResult = $targetService->entityMove($target, ...$destinationSources->all()); foreach ($destinationSources as $identifier) { $sourceIdentifier = (string)$identifier; diff --git a/src/components/AddAccountDialog.vue b/src/components/AddAccountDialog.vue index ca08267..2f129aa 100644 --- a/src/components/AddAccountDialog.vue +++ b/src/components/AddAccountDialog.vue @@ -1,15 +1,16 @@ Provider - {{ providerLabel }} + {{ localProvider.label }} -