hasPermission('r-task-cert-admin')) { TaskCertResponse::error('Keine Berechtigung', 403, false); } $csrfToken = TaskCertRequest::queryString('csrf_token', ''); if (!TaskCertCsrf::validate($csrfToken)) { TaskCertResponse::error('CSRF validation failed', 419, false); } $taskId = TaskCertRequest::queryInt('id', 0); if ($taskId <= 0) { TaskCertResponse::error('Ungültige Aufgaben-ID.', 400, false); } $services = task_cert_services(); $task = $services['definitionRepo']->findById($taskId); if ($task === null) { TaskCertResponse::error('Aufgabe nicht gefunden.', 404, false); } // Aktive Methoden (mit Feld-/Quiz-/Beitragskonfiguration) laden — analog zur // echten User-Detailseite (actions/user/task_detail_action.php). $methods = $services['ruleRepo']->getMethodsByTask($taskId); $methods = array_values(array_filter($methods, static function (array $method): bool { return (int) ($method['active'] ?? 1) === 1; })); // Beitragstitel für knowledge_read-Methoden auflösen. $postIds = []; foreach ($methods as $method) { if ((string) ($method['method_type'] ?? '') !== 'knowledge_read') { continue; } foreach ((array) ($method['knowledge_posts'] ?? []) as $post) { $postId = (int) ($post['knowledge_post_id'] ?? 0); if ($postId > 0) { $postIds[] = $postId; } } } $knowledgePostTitleMap = []; $lookupService = $services['lookupService'] ?? null; if ($lookupService instanceof TaskLookupService && $postIds !== []) { $languageId = (int) ($GLOBALS['language']['id'] ?? 1); $knowledgePostTitleMap = $lookupService->getKnowledgePostTitleMapByIds($languageId, $postIds); } foreach ($methods as &$method) { if ((string) ($method['method_type'] ?? '') !== 'knowledge_read') { continue; } foreach ((array) ($method['knowledge_posts'] ?? []) as &$post) { $postId = (int) ($post['knowledge_post_id'] ?? 0); $post['title'] = $knowledgePostTitleMap[$postId] ?? ('Beitrag #' . $postId); } unset($post); } unset($method); $responsibles = $services['ruleRepo']->getResponsiblesWithContactData($taskId); // Eigene Kontaktdaten des Admins für die Prefill-Demo (nur falls Felder das // nutzen) — sonst leer. $neededPrefillColumns = []; foreach ($methods as $m) { foreach ((array) ($m['form_fields'] ?? []) as $ff) { $col = trim((string) ($ff['prefill_column'] ?? '')); if ($col !== '' && ContactPrefillColumns::isValid($col)) { $neededPrefillColumns[$col] = true; } } } $contactData = []; if ($neededPrefillColumns !== []) { try { $contactRow = TaskCertDb::fetchOne( 'SELECT * FROM main_contact WHERE id = ? LIMIT 1', 'i', [$auth->contactId()] ); if (is_array($contactRow)) { $contactData = $contactRow; } } catch (Throwable $e) { $contactData = []; } } // Stub-Assignment: offen, in ferner Zukunft fällig, gehört dem Admin. Damit // rendert die Detailseite alle Methoden/Felder, ohne ein echtes Assignment. $assignment = [ 'id' => 0, 'task_id' => $taskId, 'status' => 'open', 'due_at' => '2099-12-31 23:59:59', 'main_contact_id' => $auth->contactId(), ]; // Variablen für das User-Template vorbelegen (überspringt dessen Lade-Guard). $error = null; $submissions = []; $task_certificates_history = []; $contact_data = $contactData; $csrf_token = TaskCertCsrf::token(); $previewMode = true; while (ob_get_level() > 0) { ob_end_clean(); } header('Content-Type: text/html; charset=utf-8'); // Host-Design-Tokens (--blue-accent, --border, --ff-primary, --tc-radius …) // laden, damit die Vorschau exakt wie die echte, vom Host umrahmte Detailseite // aussieht. Pfad entspricht dem Host-Wrapper (mysyde/frontend/frontend_mysyde.php). $globalCssPath = '/layout/frontend/b2c/dist/css/global.css'; $globalCssAbs = ($_SERVER['DOCUMENT_ROOT'] ?? '') . $globalCssPath; $globalCssHref = $globalCssPath; if (is_file($globalCssAbs)) { $globalCssHref .= '?time=' . filemtime($globalCssAbs); } ?>