diff --git a/src/Controller/Admin/TagController.php b/src/Controller/Admin/TagController.php index f396f34..84dcde1 100644 --- a/src/Controller/Admin/TagController.php +++ b/src/Controller/Admin/TagController.php @@ -4,13 +4,8 @@ declare(strict_types=1); namespace App\Controller\Admin; -use App\Entity\Document; -use App\Entity\DocumentTag; -use App\Entity\Tag; use App\Entity\TagRebuildJob; -use App\Tag\TagService; -use App\Service\TagRebuildJobService; -use Doctrine\ORM\EntityManagerInterface; +use App\Service\Admin\TagAdminService; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; @@ -21,18 +16,12 @@ use Symfony\Component\Routing\Attribute\Route; final class TagController extends AbstractController { #[Route('', name: 'admin_tags_index', methods: ['GET'])] - public function index( - EntityManagerInterface $em, - TagRebuildJobService $jobs - ): Response { - - $tags = $em->getRepository(Tag::class) - ->findBy([], ['label' => 'ASC']); + public function index(TagAdminService $svc): Response + { + $data = $svc->getIndexData(); return $this->render('admin/tag/index.html.twig', [ - 'tags' => $tags, - 'latestJob' => $jobs->getLatestJob(), - 'hasActiveJob' => $jobs->hasActiveJob(), + ...$data, 'statusRunning' => TagRebuildJob::STATUS_RUNNING, 'statusQueued' => TagRebuildJob::STATUS_QUEUED, 'statusCompleted' => TagRebuildJob::STATUS_COMPLETED, @@ -41,27 +30,26 @@ final class TagController extends AbstractController } #[Route('/create', name: 'admin_tags_create', methods: ['POST'])] - public function create( - Request $request, - TagService $tagService - ): RedirectResponse { - $token = (string) $request->request->get('_token', ''); - - if (!$this->isCsrfTokenValid('admin_tag_create', $token)) { + public function create(Request $request, TagAdminService $svc): RedirectResponse + { + if (!$this->isCsrfTokenValid( + 'admin_tag_create', + $request->request->get('_token') + )) { $this->addFlash('danger', 'Ungültiges CSRF Token.'); return $this->redirectToRoute('admin_tags_index'); } try { - $tagService->create( - (string) $request->request->get('slug', ''), - (string) $request->request->get('label', ''), + $svc->create( + (string)$request->request->get('slug', ''), + (string)$request->request->get('label', ''), $request->request->get('description') - ? (string) $request->request->get('description') + ? (string)$request->request->get('description') : null ); - $this->addFlash('success', 'Tag wurde erstellt. Rebuild läuft im Hintergrund.'); + $this->addFlash('success', 'Tag wurde erstellt.'); } catch (\Throwable $e) { $this->addFlash('danger', $e->getMessage()); } @@ -70,21 +58,19 @@ final class TagController extends AbstractController } #[Route('/{id}/delete', name: 'admin_tags_delete', methods: ['POST'])] - public function delete( - string $id, - Request $request, - TagService $tagService - ): RedirectResponse { - $token = (string) $request->request->get('_token', ''); - - if (!$this->isCsrfTokenValid('admin_tag_delete_' . $id, $token)) { + public function delete(string $id, Request $request, TagAdminService $svc): RedirectResponse + { + if (!$this->isCsrfTokenValid( + 'admin_tag_delete_' . $id, + $request->request->get('_token') + )) { $this->addFlash('danger', 'Ungültiges CSRF Token.'); return $this->redirectToRoute('admin_tags_index'); } try { - $tagService->deleteById($id); - $this->addFlash('success', 'Tag wurde gelöscht. Rebuild läuft im Hintergrund.'); + $svc->delete($id); + $this->addFlash('success', 'Tag wurde gelöscht.'); } catch (\Throwable $e) { $this->addFlash('danger', $e->getMessage()); } @@ -95,64 +81,33 @@ final class TagController extends AbstractController #[Route('/{id}/assign', name: 'admin_tags_assign', methods: ['GET', 'POST'])] public function assign( string $id, - EntityManagerInterface $em, Request $request, - TagService $tagService, - TagRebuildJobService $jobs + TagAdminService $svc ): Response { - $tag = $em->getRepository(Tag::class)->find($id); - - if (!$tag instanceof Tag) { - throw $this->createNotFoundException('Tag nicht gefunden.'); - } - - // Alle Dokumente laden - $documents = $em->getRepository(Document::class)->findAll(); - - $documentsData = array_map( - fn(Document $d) => [ - 'id' => (string) $d->getId(), - 'title' => $d->getTitle(), - ], - $documents - ); - - // Aktuell zugewiesene Dokumente ermitteln - $existingRelations = $em - ->getRepository(DocumentTag::class) - ->findBy(['tag' => $tag]); - - $assignedDocIds = array_map( - fn(DocumentTag $dt) => (string) $dt->getDocument()->getId(), - $existingRelations - ); if ($request->isMethod('POST')) { if (!$this->isCsrfTokenValid( - 'assign_tag_' . $tag->getId(), + 'assign_tag_' . $id, $request->request->get('_token') )) { throw $this->createAccessDeniedException(); } - $selectedIds = $request->request->all('documents') ?? []; - - $tagService->syncTagDocuments($tag, $selectedIds); + $svc->syncAssignments( + $id, + $request->request->all('documents') ?? [] + ); $this->addFlash('success', 'Zuweisungen aktualisiert.'); - return $this->redirectToRoute('admin_tags_assign', [ - 'id' => $tag->getId() - ]); + return $this->redirectToRoute('admin_tags_assign', ['id' => $id]); } + $data = $svc->getAssignData($id); + return $this->render('admin/tag/assign.html.twig', [ - 'tag' => $tag, - 'documents' => $documentsData, - 'assignedDocIds' => $assignedDocIds, - 'latestJob' => $jobs->getLatestJob(), - 'hasActiveJob' => $jobs->hasActiveJob(), + ...$data, 'statusRunning' => TagRebuildJob::STATUS_RUNNING, 'statusQueued' => TagRebuildJob::STATUS_QUEUED, 'statusCompleted' => TagRebuildJob::STATUS_COMPLETED, diff --git a/src/Service/Admin/TagAdminService.php b/src/Service/Admin/TagAdminService.php new file mode 100644 index 0000000..c954309 --- /dev/null +++ b/src/Service/Admin/TagAdminService.php @@ -0,0 +1,90 @@ +em->getRepository(Tag::class) + ->findBy([], ['label' => 'ASC']); + + return [ + 'tags' => $tags, + 'latestJob' => $this->jobs->getLatestJob(), + 'hasActiveJob' => $this->jobs->hasActiveJob(), + ]; + } + + public function create(string $slug, string $label, ?string $description): void + { + $this->tagService->create($slug, $label, $description); + } + + public function delete(string $id): void + { + $this->tagService->deleteById($id); + } + + public function getAssignData(string $tagId): array + { + $tag = $this->em->getRepository(Tag::class)->find($tagId); + + if (!$tag instanceof Tag) { + throw new \RuntimeException('Tag nicht gefunden.'); + } + + $documents = $this->em->getRepository(Document::class)->findAll(); + + $documentsData = array_map( + fn(Document $d) => [ + 'id' => (string)$d->getId(), + 'title' => $d->getTitle(), + ], + $documents + ); + + $existingRelations = $this->em + ->getRepository(DocumentTag::class) + ->findBy(['tag' => $tag]); + + $assignedDocIds = array_map( + fn(DocumentTag $dt) => (string)$dt->getDocument()->getId(), + $existingRelations + ); + + return [ + 'tag' => $tag, + 'documents' => $documentsData, + 'assignedDocIds' => $assignedDocIds, + 'latestJob' => $this->jobs->getLatestJob(), + 'hasActiveJob' => $this->jobs->hasActiveJob(), + ]; + } + + public function syncAssignments(string $tagId, array $selectedDocIds): void + { + $tag = $this->em->getRepository(Tag::class)->find($tagId); + + if (!$tag instanceof Tag) { + throw new \RuntimeException('Tag nicht gefunden.'); + } + + $this->tagService->syncTagDocuments($tag, $selectedDocIds); + } +} \ No newline at end of file