p101d
This commit is contained in:
@@ -92,6 +92,7 @@ final class AdminEvalController extends AbstractController
|
||||
|
||||
return $this->render('admin/evals/case_new.html.twig', [
|
||||
'types' => $evals->supportedTypes(),
|
||||
'cases_by_type' => $evals->casesByType(),
|
||||
'case_draft' => $draft,
|
||||
]);
|
||||
}
|
||||
@@ -146,7 +147,46 @@ final class AdminEvalController extends AbstractController
|
||||
|
||||
return $this->render('admin/evals/case_new.html.twig', [
|
||||
'types' => $evals->supportedTypes(),
|
||||
'cases_by_type' => $evals->casesByType(),
|
||||
'case_draft' => $draft,
|
||||
], new Response('', Response::HTTP_UNPROCESSABLE_ENTITY));
|
||||
}
|
||||
|
||||
|
||||
#[Route('/cases/delete', name: 'admin_evals_case_delete', methods: ['POST'])]
|
||||
public function deleteCase(Request $request, EvalAdminService $evals): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted(ApplicationRoles::ROLE_KNOWLEDGE_ADMIN);
|
||||
|
||||
$type = trim((string) $request->request->get('type', 'retrieval'));
|
||||
$caseId = trim((string) $request->request->get('case_id', ''));
|
||||
|
||||
if (!$this->isCsrfTokenValid(
|
||||
sprintf('admin_eval_case_delete_%s_%s', $type, $caseId),
|
||||
(string) $request->request->get('_token')
|
||||
)) {
|
||||
throw $this->createAccessDeniedException();
|
||||
}
|
||||
|
||||
try {
|
||||
$deleted = $evals->deleteCase($type, $caseId);
|
||||
$type = (string) ($deleted['type'] ?? $type);
|
||||
|
||||
$this->addFlash(
|
||||
'success',
|
||||
sprintf('Eval-Case "%s" wurde aus %s.ndjson entfernt.', (string) ($deleted['id'] ?? $caseId), $type)
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
$this->addFlash('danger', $e->getMessage());
|
||||
}
|
||||
|
||||
if (!in_array($type, $evals->supportedTypeNames(), true)) {
|
||||
$type = 'retrieval';
|
||||
}
|
||||
|
||||
return $this->redirectToRoute('admin_evals_case_new', [
|
||||
'type' => $type,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -290,6 +290,77 @@ final readonly class EvalAdminService
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array{type:string,id:string,path:string,case_count:int}
|
||||
*/
|
||||
public function deleteCase(string $type, string $caseId): array
|
||||
{
|
||||
$type = $this->assertSupportedType($type);
|
||||
$caseId = $this->normalizeExistingCaseId($caseId);
|
||||
$path = $this->caseFilePath($type);
|
||||
|
||||
if (!is_file($path)) {
|
||||
throw new \RuntimeException(sprintf('Eval-Case-Datei wurde nicht gefunden: %s', $path));
|
||||
}
|
||||
|
||||
$lines = file($path, FILE_IGNORE_NEW_LINES);
|
||||
if ($lines === false) {
|
||||
throw new \RuntimeException(sprintf('Eval-Case-Datei konnte nicht gelesen werden: %s', $path));
|
||||
}
|
||||
|
||||
$keptLines = [];
|
||||
$deleted = false;
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$trimmed = trim((string) $line);
|
||||
if ($trimmed === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$decoded = json_decode($trimmed, true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (\JsonException $e) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Eval-Case-Datei enthält ungültiges JSON und wurde nicht verändert: %s',
|
||||
$e->getMessage()
|
||||
));
|
||||
}
|
||||
|
||||
if (!is_array($decoded)) {
|
||||
throw new \RuntimeException('Eval-Case-Datei enthält eine ungültige NDJSON-Zeile und wurde nicht verändert.');
|
||||
}
|
||||
|
||||
if ((string) ($decoded['id'] ?? '') === $caseId) {
|
||||
$deleted = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$keptLines[] = $trimmed;
|
||||
}
|
||||
|
||||
if (!$deleted) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Eval-Case "%s" wurde im Typ "%s" nicht gefunden.',
|
||||
$caseId,
|
||||
$type
|
||||
));
|
||||
}
|
||||
|
||||
$contents = $keptLines === [] ? '' : implode(PHP_EOL, $keptLines) . PHP_EOL;
|
||||
$written = file_put_contents($path, $contents, LOCK_EX);
|
||||
if ($written === false) {
|
||||
throw new \RuntimeException(sprintf('Eval-Case-Datei konnte nicht geschrieben werden: %s', $path));
|
||||
}
|
||||
|
||||
return [
|
||||
'type' => $type,
|
||||
'id' => $caseId,
|
||||
'path' => $path,
|
||||
'case_count' => count($this->loadCases($type)),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, EvalCase> $cases
|
||||
* @return array<int, EvalCase>
|
||||
@@ -411,6 +482,23 @@ final readonly class EvalAdminService
|
||||
return $id;
|
||||
}
|
||||
|
||||
private function normalizeExistingCaseId(string $id): string
|
||||
{
|
||||
$id = trim($id);
|
||||
|
||||
if ($id === '') {
|
||||
throw new \InvalidArgumentException('Es wurde keine Eval-Case-ID zum Löschen übergeben.');
|
||||
}
|
||||
|
||||
if (preg_match('/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/', $id) !== 1) {
|
||||
throw new \InvalidArgumentException(
|
||||
'Die Eval-Case-ID ist ungültig. Erlaubt sind nur Buchstaben, Zahlen, Unterstriche und Bindestriche.'
|
||||
);
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
private function caseIdExists(string $id): bool
|
||||
{
|
||||
foreach (array_keys(self::TYPES) as $type) {
|
||||
|
||||
Reference in New Issue
Block a user