From 8096ac0de9e5ee69c504fac1fa66cf8e1cbe68a0 Mon Sep 17 00:00:00 2001 From: team2 Date: Fri, 27 Feb 2026 20:15:43 +0100 Subject: [PATCH] move controller service logics into a service --- .../Admin/IngestProfileController.php | 115 ++++++--------- .../Admin/IngestProfileAdminService.php | 135 ++++++++++++++++++ 2 files changed, 175 insertions(+), 75 deletions(-) create mode 100644 src/Service/Admin/IngestProfileAdminService.php diff --git a/src/Controller/Admin/IngestProfileController.php b/src/Controller/Admin/IngestProfileController.php index 0c19c00..99d8a11 100644 --- a/src/Controller/Admin/IngestProfileController.php +++ b/src/Controller/Admin/IngestProfileController.php @@ -5,107 +5,72 @@ declare(strict_types=1); namespace App\Controller\Admin; use App\Entity\IngestProfile; -use App\Index\IndexConfigurationProvider; -use App\Index\IndexMetaManager; -use App\Index\IndexStructureComparator; -use App\Repository\IngestProfileRepository; -use Doctrine\ORM\EntityManagerInterface; +use App\Service\Admin\IngestProfileAdminService; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; #[Route('/admin/ingest-profiles')] -class IngestProfileController extends AbstractController +final class IngestProfileController extends AbstractController { #[Route('/', name: 'admin_ingest_profile_list')] - public function list( - IngestProfileRepository $repo, - IndexMetaManager $metaManager, - IndexConfigurationProvider $provider, - IndexStructureComparator $comparator - ): Response { + public function list(IngestProfileAdminService $svc): Response + { + $data = $svc->listData(); - $profiles = $repo->findBy([], ['version' => 'DESC']); - $activeProfile = $repo->findActive(); - - $meta = $metaManager->readMeta(); - $currentStructure = $provider->getConfiguration()->toStructureArray(); - - $diff = $comparator->compare($meta, $currentStructure); - - $structureMismatch = false; - foreach ($diff as $row) { - if (!$row['equal']) { - $structureMismatch = true; - break; - } - } - - return $this->render('admin/ingest_profile/list.html.twig', [ - 'profiles' => $profiles, - 'activeProfile' => $activeProfile, - 'indexMeta' => $meta, - 'diff' => $diff, - 'structureMismatch' => $structureMismatch, - ]); + return $this->render('admin/ingest_profile/list.html.twig', $data); } #[Route('/create', name: 'admin_ingest_profile_create', methods: ['GET', 'POST'])] - public function create( - Request $request, - IngestProfileRepository $repo, - EntityManagerInterface $em - ): Response { - + public function create(Request $request, IngestProfileAdminService $svc): Response + { if ($request->isMethod('POST')) { + try { + $svc->create([ + 'chunk_size' => $request->request->get('chunk_size'), + 'chunk_overlap' => $request->request->get('chunk_overlap'), + 'embedding_model' => $request->request->get('embedding_model'), + 'embedding_dimension' => $request->request->get('embedding_dimension'), + 'scoring_version' => $request->request->get('scoring_version'), + ]); - $latest = $repo->findLatestVersion(); - $nextVersion = $latest ? $latest->getVersion() + 1 : 1; - - $profile = new IngestProfile( - $nextVersion, - (int)$request->request->get('chunk_size'), - (int)$request->request->get('chunk_overlap'), - (string)$request->request->get('embedding_model'), - (int)$request->request->get('embedding_dimension'), - (int)$request->request->get('scoring_version') - ); - - $em->persist($profile); - $em->flush(); - - return $this->redirectToRoute('admin_ingest_profile_list'); + $this->addFlash('success', 'Ingest-Profil wurde erstellt.'); + return $this->redirectToRoute('admin_ingest_profile_list'); + } catch (\Throwable $e) { + $this->addFlash('danger', $e->getMessage()); + // fallthrough -> render form again + } } return $this->render('admin/ingest_profile/create.html.twig'); } - #[Route('/activate/{id}', name: 'admin_ingest_profile_activate')] + #[Route('/activate/{id}', name: 'admin_ingest_profile_activate', methods: ['POST'])] public function activate( IngestProfile $profile, - IngestProfileRepository $repo, - EntityManagerInterface $em + IngestProfileAdminService $svc ): Response { - - $active = $repo->findActive(); - if ($active) { - $active->deactivate(); + try { + $svc->activate($profile); + $this->addFlash('success', 'Ingest-Profil wurde aktiviert.'); + } catch (\Throwable $e) { + $this->addFlash('danger', $e->getMessage()); } - $profile->activate(); - - $em->flush(); - return $this->redirectToRoute('admin_ingest_profile_list'); } - #[Route('/remove/{id}', name: 'admin_ingest_profile_remove')] - public function remove( - IngestProfileRepository $repo, - string $id - ): Response { - $repo->remove($id); + #[Route('/remove/{id}', name: 'admin_ingest_profile_remove', methods: ['POST', 'GET'])] + public function remove(string $id, IngestProfileAdminService $svc): Response + { + try { + $svc->remove($id); + $this->addFlash('success', 'Ingest-Profil wurde entfernt.'); + } catch (\Throwable $e) { + $this->addFlash('danger', $e->getMessage()); + } + return $this->redirectToRoute('admin_ingest_profile_list'); } -} +} \ No newline at end of file diff --git a/src/Service/Admin/IngestProfileAdminService.php b/src/Service/Admin/IngestProfileAdminService.php new file mode 100644 index 0000000..7f4f5d7 --- /dev/null +++ b/src/Service/Admin/IngestProfileAdminService.php @@ -0,0 +1,135 @@ +repo->findBy([], ['version' => 'DESC']); + $activeProfile = $this->repo->findActive(); + + $meta = $this->metaManager->readMeta(); + $currentStructure = $this->provider->getConfiguration()->toStructureArray(); + + $diff = $this->comparator->compare($meta, $currentStructure); + + $structureMismatch = false; + foreach ($diff as $row) { + if (!($row['equal'] ?? false)) { + $structureMismatch = true; + break; + } + } + + return [ + 'profiles' => $profiles, + 'activeProfile' => $activeProfile, + 'indexMeta' => $meta, + 'diff' => $diff, + 'structureMismatch' => $structureMismatch, + ]; + } + + /** + * Erzeugt ein neues Profil mit nextVersion aus Repo. + * + * @param array{ + * chunk_size:mixed, + * chunk_overlap:mixed, + * embedding_model:mixed, + * embedding_dimension:mixed, + * scoring_version:mixed + * } $data + */ + public function create(array $data): IngestProfile + { + $latest = $this->repo->findLatestVersion(); + $nextVersion = $latest ? $latest->getVersion() + 1 : 1; + + $chunkSize = $this->requireInt($data['chunk_size'] ?? null, 'chunk_size'); + $chunkOverlap = $this->requireInt($data['chunk_overlap'] ?? null, 'chunk_overlap'); + $embeddingModel = $this->requireString($data['embedding_model'] ?? null, 'embedding_model'); + $embeddingDim = $this->requireInt($data['embedding_dimension'] ?? null, 'embedding_dimension'); + $scoringVersion = $this->requireInt($data['scoring_version'] ?? null, 'scoring_version'); + + $profile = new IngestProfile( + $nextVersion, + $chunkSize, + $chunkOverlap, + $embeddingModel, + $embeddingDim, + $scoringVersion + ); + + $this->em->persist($profile); + $this->em->flush(); + + return $profile; + } + + public function activate(IngestProfile $profile): void + { + $active = $this->repo->findActive(); + if ($active instanceof IngestProfile) { + $active->deactivate(); + } + + $profile->activate(); + $this->em->flush(); + } + + public function remove(string $id): void + { + // Repo macht intern flush/remove - wie bei dir bereits + $this->repo->remove($id); + } + + private function requireInt(mixed $value, string $field): int + { + if ($value === null || $value === '') { + throw new \InvalidArgumentException("Missing field: {$field}"); + } + if (is_int($value)) { + return $value; + } + if (is_numeric($value)) { + return (int)$value; + } + throw new \InvalidArgumentException("Invalid int for {$field}"); + } + + private function requireString(mixed $value, string $field): string + { + if (!is_string($value) || trim($value) === '') { + throw new \InvalidArgumentException("Invalid string for {$field}"); + } + return trim($value); + } +} \ No newline at end of file