Files
intranet/web/intranet_repo/projects/brandschutz/brandschutz.php
T

154 lines
8.5 KiB
PHP

<?php
/* Name: brandschutz.php
Beschreibung: Konfigurationsbasierte interaktive Brandschutzunterweisung */
require_once $_SERVER['DOCUMENT_ROOT'] . '/intranet_repo/general_files/initialise.php';
require_once __DIR__ . '/util/brandschutz_helpers.php';
require_once __DIR__ . '/util/brandschutz_course.php';
require_once __DIR__ . '/util/brandschutz_renderer.php';
$csrfToken = brandschutz_csrf_token();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
brandschutz_verify_csrf($_POST['csrf_token'] ?? null);
} catch (InvalidArgumentException $exception) {
http_response_code(400);
exit($exception->getMessage());
}
if (($_POST['action'] ?? '') !== 'complete_training') {
http_response_code(400);
exit('Ungültige Aktion.');
}
if ((int) ($groups['Brandschutz'] ?? 0) !== 1) {
http_response_code(403);
exit('Keine Berechtigung für diese Aktion.');
}
$userId = (int) $_SESSION['user_id'];
$today = brandschutz_today();
$trainingDate = $today->format('Y-m-d');
$trainingDateDisplay = $today->format('d.m.Y');
$dueDateDisplay = $today->modify('+' . BRANDSCHUTZ_VALIDITY_DAYS . ' days')->format('d.m.Y');
$userName = brandschutz_display_name(is_array($user) ? $user : []);
$senderMail = trim((string) ($user['mail'] ?? ''));
$pdo->beginTransaction();
try {
brandschutz_store_training_date($pdo, $userId, $trainingDate, true);
brandschutz_log_admin_message(
$pdo,
$userName,
$senderMail,
'Brandschutzschulung absolviert: ' . $userName,
$userName . ' hat die Brandschutzunterweisung am ' . $trainingDateDisplay . ' erfolgreich absolviert.'
);
$pdo->commit();
} catch (Throwable $exception) {
if ($pdo->inTransaction()) $pdo->rollBack();
throw $exception;
}
if ($senderMail !== '') {
require_once $_SERVER['DOCUMENT_ROOT'] . '/intranet_repo/general_files/ini/send_mail.php';
$mailSubject = 'Brandschutzunterweisung erfolgreich absolviert';
$mailMessage = brandschutz_greeting(is_array($user) ? $user : [])
. ",\n\nSie haben die Brandschutzunterweisung am {$trainingDateDisplay} erfolgreich absolviert."
. "\n\nIhre nächste Unterweisung ist bis zum {$dueDateDisplay} fällig."
. "\n\nVielen Dank für Ihre Teilnahme!";
if (!send_intranet_mail($senderMail, $mailSubject, $mailMessage)) {
error_log('Brandschutz: Bestätigungsmail an ' . $senderMail . ' konnte nicht gesendet werden.');
}
}
header('Location: /intranet_repo/projects/intranet/index.php?message=8', true, 303);
exit();
}
$courseError = null;
$course = ['title' => 'Brandschutzunterweisung', 'settings' => [], 'chapters' => []];
try {
$course = brandschutz_course_load($pdo)['config'];
} catch (Throwable $exception) {
error_log('Brandschutz-Konfiguration: ' . $exception->getMessage());
$courseError = 'Die Schulung konnte momentan nicht geladen werden. Bitte versuchen Sie es später erneut.';
}
$clientSettings = [
'passingScore' => (int) ($course['settings']['passing_score'] ?? 70),
'maxAttempts' => (int) ($course['settings']['max_attempts'] ?? 3),
'successTitle' => (string) ($course['settings']['success_title'] ?? 'Schulung bestanden!'),
'successText' => brandschutz_course_sanitize_html($course['settings']['success_text'] ?? ''),
'failureTitle' => (string) ($course['settings']['failure_title'] ?? 'Schulung nicht bestanden'),
'failureText' => brandschutz_course_sanitize_html($course['settings']['failure_text'] ?? ''),
'confirmationText' => brandschutz_course_sanitize_html($course['settings']['confirmation_text'] ?? ''),
];
?>
<!DOCTYPE html>
<html lang="de" dir="ltr">
<head>
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
<link rel="stylesheet" href="/intranet_repo/projects/_central/layouts/brandschutz.css">
<script id="bsCourseSettings" type="application/json"><?= json_encode($clientSettings, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_THROW_ON_ERROR) ?></script>
<script src="/intranet_repo/projects/_central/scripts/brandschutz.js" defer></script>
<title><?= brandschutz_h((string) $course['title']) ?></title>
</head>
<body class="theme-orange">
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/header.php'; ?>
<?php include $g_phpSnippetsPath.'overlay_message.php'; ?>
<div class="header_title ht_orange" id="header_title">
<span class="header_title_text"><?= brandschutz_h((string) $course['title']) ?></span>
</div>
<form id="bsCompleteForm" method="post" action="/intranet_repo/projects/brandschutz/brandschutz.php" hidden>
<input type="hidden" name="action" value="complete_training">
<input type="hidden" name="csrf_token" value="<?= brandschutz_h($csrfToken) ?>">
</form>
<div class="bs-page-wrapper"><div class="bs-wizard">
<?php if ($courseError !== null): ?>
<div class="bs-section"><div class="bs-body"><div class="bs-warnbox"><div class="bs-warnbox-title">Schulung nicht verfügbar</div><?= brandschutz_h($courseError) ?></div></div></div>
<?php elseif (empty($course['chapters'])): ?>
<div class="bs-section"><div class="bs-body"><div class="bs-chapter-title">Noch keine Inhalte</div><div class="bs-text">Für diese Schulung wurden noch keine Kapitel angelegt.</div></div></div>
<?php else: ?>
<div class="bs-progress" id="bsMainProgress" aria-label="Schulungsfortschritt">
<?php foreach ($course['chapters'] as $chapterIndex => $chapter): ?>
<?php if ($chapterIndex > 0): ?><div class="bs-progress-line"></div><?php endif; ?>
<div class="bs-progress-step<?= $chapterIndex === 0 ? ' active' : '' ?>" data-chapter-index="<?= $chapterIndex ?>">
<div class="bs-progress-circle"><?= $chapterIndex ?></div>
<span class="bs-progress-label"><?= brandschutz_h((string) $chapter['short_title']) ?></span>
</div>
<?php endforeach; ?>
</div>
<?php foreach ($course['chapters'] as $chapterIndex => $chapter): ?>
<section class="bs-section" data-chapter="<?= $chapterIndex ?>"<?= $chapterIndex > 0 ? ' hidden' : '' ?>>
<?php if ($chapterIndex > 0 || count($course['chapters']) === 1): ?><div class="bs-section-header"><?= brandschutz_h((string) $chapter['title']) ?></div><?php endif; ?>
<?php if (empty($chapter['pages'])): ?>
<div class="bs-substep" data-page="0"><div class="bs-body"><div class="bs-chapter-title">Leeres Kapitel</div><div class="bs-text">Dieses Kapitel enthält noch keine Seiten.</div></div>
<div class="bs-actions"><div class="bs-actions-left"><button type="button" class="bs-btn bs-prev-page">&lt; Zurück</button></div><div class="bs-actions-right"><button type="button" class="bs-btn bs-btn-primary bs-next-page">Weiter &gt;</button></div></div>
</div>
<?php else: ?>
<?php foreach ($chapter['pages'] as $pageIndex => $page): ?>
<div class="bs-substep" data-page="<?= $pageIndex ?>"<?= $pageIndex > 0 ? ' hidden' : '' ?>>
<div class="bs-body"><div class="bs-chapter-title"><?= brandschutz_h((string) $page['title']) ?></div>
<?php if (empty($page['elements'])): ?><div class="bs-text bs-empty-state">Diese Seite enthält noch keine Elemente.</div><?php endif; ?>
<?php foreach ($page['elements'] as $element) brandschutz_render_element($element); ?>
</div>
<div class="bs-actions"><div class="bs-actions-left"><button type="button" class="bs-btn bs-prev-page">&lt; Zurück</button></div><div class="bs-actions-right"><button type="button" class="bs-btn bs-btn-primary bs-next-page">Weiter &gt;</button></div></div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</section>
<?php endforeach; ?>
<section class="bs-section" id="bsSectionScore" hidden><div class="bs-section-header">Zwischenstand</div><div class="bs-body"></div><div class="bs-actions"><div class="bs-actions-left"></div><div class="bs-actions-right"></div></div></section>
<section class="bs-section" id="bsFinalResult" hidden><div class="bs-body"></div></section>
<?php endif; ?>
</div></div>
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
</body>
</html>