diff --git a/backend/app/Controllers/SetController.php b/backend/app/Controllers/SetController.php index 239963f..a3c89f6 100644 --- a/backend/app/Controllers/SetController.php +++ b/backend/app/Controllers/SetController.php @@ -9,6 +9,8 @@ use App\Set\Set as DomainSet; use App\Set\SetRepository; use App\Set\UseCases\CreateSetWithRoot\CreateSetWithRoot; use App\Set\UseCases\CreateSetWithRoot\CreateSetWithRootRequest; +use App\Set\UseCases\DeleteSet\DeleteSet; +use App\Set\UseCases\DeleteSet\DeleteSetRequest; use App\Set\UseCases\UpdateSet\UpdateSet; use App\Set\UseCases\UpdateSet\UpdateSetRequest; use App\Shared\Files\Filesystem; @@ -23,6 +25,7 @@ class SetController private ElementRepository $elementRepository, private CreateSetWithRoot $createSetWithRoot, private UpdateSet $updateSet, + private DeleteSet $deleteSet, private Filesystem $filesystem, ) { } @@ -96,6 +99,23 @@ class SetController ], 200); } + public function delete(?int $id): JsonResponse + { + try { + $this->deleteSet->execute(new DeleteSetRequest(id: $id)); + } catch (BadRequestException $exception) { + return new JsonResponse([ + 'error' => $exception->getMessage(), + ], 400); + } catch (NotFoundException $exception) { + return new JsonResponse([ + 'error' => $exception->getMessage(), + ], 404); + } + + return new JsonResponse(null, 204); + } + /** * @return array{ * id: int, diff --git a/backend/app/Set/UseCases/DeleteSet/DeleteSet.php b/backend/app/Set/UseCases/DeleteSet/DeleteSet.php new file mode 100644 index 0000000..9ff51a7 --- /dev/null +++ b/backend/app/Set/UseCases/DeleteSet/DeleteSet.php @@ -0,0 +1,115 @@ + + */ + private array $managedFilePaths = []; + + public function __construct( + private SetRepository $setRepository, + private ElementRepository $elementRepository, + private Filesystem $filesystem, + ) { + } + + /** + * @throws BadRequestException + * @throws NotFoundException + */ + public function execute(DeleteSetRequest $request): void + { + if ($request->id === null) { + throw new BadRequestException('setId is required'); + } + + $set = $this->setRepository->find($request->id); + if ($set === null) { + throw new NotFoundException('Set not found'); + } + + $this->managedFilePaths = []; + $this->rememberManagedFile($set->getIconImageUrl()); + + $elements = $this->elementRepository->findBySet($set); + foreach ($elements as $element) { + $this->rememberManagedFile($element->getIconImageUrl()); + $this->rememberManagedFile($element->getShortPdfPath()); + $this->rememberManagedFile($element->getLongPdfPath()); + } + + foreach ($this->deepestElementsFirst($elements) as $element) { + $this->elementRepository->delete($element); + } + + $this->setRepository->delete($set); + foreach (array_keys($this->managedFilePaths) as $path) { + $this->filesystem->delete($path); + } + } + + /** + * @param Element[] $elements + * @return Element[] + */ + private function deepestElementsFirst(array $elements): array + { + usort($elements, function ( + Element $firstElement, + Element $secondElement, + ): int { + $firstDepth = $this->elementDepth($firstElement); + $secondDepth = $this->elementDepth($secondElement); + if ($firstDepth === $secondDepth) { + return $secondElement->getId() <=> $firstElement->getId(); + } + + return $secondDepth <=> $firstDepth; + }); + + return $elements; + } + + private function elementDepth(Element $element): int + { + $depth = 0; + $parentElement = $element->getParentElement(); + while ($parentElement !== null) { + $depth++; + $parentElement = $parentElement->getParentElement(); + } + + return $depth; + } + + private function rememberManagedFile(?string $path): void + { + if ($path === null) { + return; + } + + if (! $this->isManagedFilePath($path)) { + return; + } + + $this->managedFilePaths[$path] = true; + } + + private function isManagedFilePath(string $path): bool + { + return str_starts_with($path, 'set-icons/') + || str_starts_with($path, 'element-icons/') + || str_starts_with($path, 'element-pdfs/short/') + || str_starts_with($path, 'element-pdfs/long/'); + } +} diff --git a/backend/app/Set/UseCases/DeleteSet/DeleteSetRequest.php b/backend/app/Set/UseCases/DeleteSet/DeleteSetRequest.php new file mode 100644 index 0000000..5954a0c --- /dev/null +++ b/backend/app/Set/UseCases/DeleteSet/DeleteSetRequest.php @@ -0,0 +1,10 @@ +middleware(AuthMiddleware::class); Route::post('/sets/{id}/update', [SetController::class, 'update']) ->middleware(AuthMiddleware::class); +Route::delete('/sets/{id}', [SetController::class, 'delete']) + ->middleware(AuthMiddleware::class); Route::get('/elements/{id}', [ElementController::class, 'show']); Route::get('/element-pdfs/{folder}/{fileName}', [ ElementController::class,