Abwesenheitskalender erweitert
This commit is contained in:
+378
-154
@@ -2,190 +2,414 @@
|
||||
session_start();
|
||||
require_once(__DIR__ . '/../inc/config.inc.php');
|
||||
require_once(__DIR__ . '/../inc/functions.inc.php');
|
||||
require_once(__DIR__ . '/../inc/vacation_absence.inc.php');
|
||||
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (!function_exists('vacationApiTableHasColumn')) {
|
||||
function vacationApiTableHasColumn(PDO $pdo, string $table, string $column): bool
|
||||
{
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT COUNT(*)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = :table_name
|
||||
AND COLUMN_NAME = :column_name"
|
||||
);
|
||||
$stmt->execute([
|
||||
'table_name' => $table,
|
||||
'column_name' => $column,
|
||||
]);
|
||||
return (int)$stmt->fetchColumn() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('vacationApiLower')) {
|
||||
function vacationApiLower(?string $value): string
|
||||
{
|
||||
$value = trim((string)$value);
|
||||
if ($value === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (function_exists('mb_strtolower')) {
|
||||
return mb_strtolower($value, 'UTF-8');
|
||||
}
|
||||
|
||||
return strtolower($value);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('vacationApiNormalizeAbsenceType')) {
|
||||
function vacationApiNormalizeAbsenceType(?string $type): string
|
||||
{
|
||||
$type = vacationApiLower($type);
|
||||
if ($type === '') {
|
||||
return vacationAbsenceDefaultReason();
|
||||
}
|
||||
|
||||
$type = strtr($type, [
|
||||
'ä' => 'ae',
|
||||
'ö' => 'oe',
|
||||
'ü' => 'ue',
|
||||
'ß' => 'ss',
|
||||
]);
|
||||
|
||||
$type = preg_replace('/[^a-z0-9]+/u', '_', $type);
|
||||
$type = trim((string)$type, '_');
|
||||
|
||||
$map = [
|
||||
'urlaub' => 'urlaub',
|
||||
'urlaubsantrag' => 'urlaub',
|
||||
'krankheit_mit_attest' => 'krankheit_mit_atest',
|
||||
'krankheit_mit_atest' => 'krankheit_mit_atest',
|
||||
'krank_mit_attest' => 'krankheit_mit_atest',
|
||||
'krankheit_ohne_attest' => 'krankheit_ohne_atest',
|
||||
'krankheit_ohne_atest' => 'krankheit_ohne_atest',
|
||||
'krank_ohne_attest' => 'krankheit_ohne_atest',
|
||||
'berufsschule' => 'berufsschule',
|
||||
'weiterbildung' => 'weiterbildung',
|
||||
'persoenliche_gruende' => 'persoenliche_gruende',
|
||||
'persoenliche_gruende_' => 'persoenliche_gruende',
|
||||
'persoenliche_gruende_mit' => 'persoenliche_gruende',
|
||||
'sonstiges' => 'sonstiges',
|
||||
];
|
||||
|
||||
return vacationAbsenceNormalizeReason($map[$type] ?? $type);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('vacationApiNormalizeStatus')) {
|
||||
function vacationApiNormalizeStatus(?string $status): string
|
||||
{
|
||||
$status = vacationApiLower($status);
|
||||
if ($status === '') {
|
||||
return 'beantragt';
|
||||
}
|
||||
|
||||
$status = preg_replace('/\s+/u', ' ', $status);
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('vacationApiTypeLabel')) {
|
||||
function vacationApiTypeLabel(string $type): string
|
||||
{
|
||||
return vacationAbsenceReasonLabel($type);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('vacationApiStatusLabel')) {
|
||||
function vacationApiStatusLabel(string $status): string
|
||||
{
|
||||
$labels = [
|
||||
'genehmigt' => 'Genehmigt',
|
||||
'beantragt' => 'Beantragt',
|
||||
'abgelehnt' => 'Abgelehnt',
|
||||
];
|
||||
|
||||
return $labels[$status] ?? ucfirst($status);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('vacationApiStatusColor')) {
|
||||
function vacationApiStatusColor(string $status): string
|
||||
{
|
||||
$colors = [
|
||||
'genehmigt' => '#28a745',
|
||||
'beantragt' => '#f0ad4e',
|
||||
'abgelehnt' => '#6c757d',
|
||||
];
|
||||
|
||||
return $colors[$status] ?? '#17a2b8';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('vacationApiTypeColor')) {
|
||||
function vacationApiTypeColor(string $type): string
|
||||
{
|
||||
$colors = [
|
||||
'urlaub' => '#2f9e44',
|
||||
'krankheit_mit_atest' => '#d9480f',
|
||||
'krankheit_ohne_atest' => '#c92a2a',
|
||||
'berufsschule' => '#1971c2',
|
||||
'weiterbildung' => '#5f3dc4',
|
||||
'persoenliche_gruende' => '#e67700',
|
||||
'sonstiges' => '#495057',
|
||||
];
|
||||
|
||||
return $colors[$type] ?? '#0d6efd';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('vacationApiRequestedTypes')) {
|
||||
function vacationApiRequestedTypes(?string $rawTypes, string $scope): ?array
|
||||
{
|
||||
$rawTypes = trim((string)$rawTypes);
|
||||
if ($rawTypes === '') {
|
||||
if ($scope === 'team') {
|
||||
return ['urlaub'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$normalized = vacationApiLower($rawTypes);
|
||||
if (in_array($normalized, ['all', '*'], true)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$types = [];
|
||||
foreach (preg_split('/\s*,\s*/', $rawTypes) as $rawType) {
|
||||
$normalizedType = vacationApiNormalizeAbsenceType($rawType);
|
||||
if ($normalizedType !== '') {
|
||||
$types[$normalizedType] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$types = array_keys($types);
|
||||
sort($types);
|
||||
|
||||
return $types;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('vacationApiStatusAllowed')) {
|
||||
function vacationApiStatusAllowed(string $status, string $mode): bool
|
||||
{
|
||||
$mode = vacationApiLower($mode);
|
||||
$status = vacationApiNormalizeStatus($status);
|
||||
|
||||
switch ($mode) {
|
||||
case 'approved':
|
||||
return $status === 'genehmigt';
|
||||
case 'open':
|
||||
return $status === 'beantragt' || $status === '';
|
||||
case 'active':
|
||||
return $status === 'genehmigt' || $status === 'beantragt' || $status === '';
|
||||
case 'rejected':
|
||||
return $status === 'abgelehnt';
|
||||
case 'all':
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$user = check_user();
|
||||
$isAdmin = is_admin_user();
|
||||
|
||||
$start = $_GET['start'] ?? null;
|
||||
$end = $_GET['end'] ?? null;
|
||||
$start = trim((string)($_GET['start'] ?? ''));
|
||||
$end = trim((string)($_GET['end'] ?? ''));
|
||||
|
||||
if ($start === '' || $end === '') {
|
||||
http_response_code(400);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode(['error' => 'start and end required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$onlyApproved = isset($_GET['only_approved']) && ($_GET['only_approved'] == '1' || $_GET['only_approved'] === 'true');
|
||||
$public = isset($_GET['public']) && ($_GET['public'] == '1' || $_GET['public'] === 'true');
|
||||
$includeRejected = isset($_GET['include_rejected']) && ($_GET['include_rejected'] == '1' || $_GET['include_rejected'] === 'true');
|
||||
$onlyPersonal = isset($_GET['only_personal']) && ($_GET['only_personal'] == '1' || $_GET['only_personal'] === 'true');
|
||||
$publicAll = isset($_GET['public_all']) && ($_GET['public_all'] == '1' || $_GET['public_all'] === 'true');
|
||||
|
||||
if (!$start || !$end) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'start and end required']);
|
||||
exit;
|
||||
$scope = strtolower(trim((string)($_GET['scope'] ?? '')));
|
||||
if ($scope === '') {
|
||||
if ($onlyPersonal) {
|
||||
$scope = 'personal';
|
||||
} elseif ($public || $publicAll) {
|
||||
$scope = 'team';
|
||||
} elseif ($isAdmin) {
|
||||
$scope = 'team';
|
||||
} else {
|
||||
$scope = 'personal';
|
||||
}
|
||||
}
|
||||
|
||||
$events = [];
|
||||
try {
|
||||
$branch = 'unknown';
|
||||
$debugMode = isset($_GET['debug']) && ($_GET['debug'] == '1' || $_GET['debug'] === 'true');
|
||||
$showEmployeeNames = $isAdmin || $public;
|
||||
if (!in_array($scope, ['personal', 'team', 'admin_all'], true)) {
|
||||
$scope = 'personal';
|
||||
}
|
||||
|
||||
if ($onlyPersonal) {
|
||||
$branch = 'onlyPersonal';
|
||||
if ($onlyApproved) {
|
||||
$branch = 'onlyPersonal_onlyApproved';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? AND LOWER(TRIM(v.status)) = 'genehmigt' ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
} else {
|
||||
if ($includeRejected) {
|
||||
$branch = 'onlyPersonal_includeRejected';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
} else {
|
||||
$branch = 'onlyPersonal_excludeRejected';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? AND (v.status IS NULL OR LOWER(TRIM(v.status)) != 'abgelehnt') ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
}
|
||||
}
|
||||
} elseif ($isAdmin) {
|
||||
$branch = 'admin';
|
||||
if ($onlyApproved) {
|
||||
$branch = 'admin_onlyApproved';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.start_date <= ? AND v.end_date >= ? AND LOWER(TRIM(v.status)) = 'genehmigt' ORDER BY v.start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
} else {
|
||||
if ($includeRejected) {
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.start_date <= ? AND v.end_date >= ? ORDER BY v.start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
} else {
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.start_date <= ? AND v.end_date >= ? AND (v.status IS NULL OR LOWER(TRIM(v.status)) IN ('genehmigt','beantragt')) ORDER BY v.start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
}
|
||||
}
|
||||
if ($scope === 'admin_all' && !$isAdmin) {
|
||||
$scope = 'personal';
|
||||
}
|
||||
|
||||
$statusMode = strtolower(trim((string)($_GET['status_filter'] ?? '')));
|
||||
if ($statusMode === '') {
|
||||
if ($onlyApproved) {
|
||||
$statusMode = 'approved';
|
||||
} elseif ($includeRejected) {
|
||||
$statusMode = 'all';
|
||||
} elseif ($scope === 'personal' || $scope === 'admin_all') {
|
||||
$statusMode = 'all';
|
||||
} else {
|
||||
$branch = 'public_or_regular';
|
||||
if ($public && $onlyApproved) {
|
||||
$branch = 'public_onlyApproved';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.start_date <= ? AND v.end_date >= ? AND LOWER(TRIM(v.status)) = 'genehmigt' ORDER BY v.start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
} elseif ($public && $publicAll) {
|
||||
$branch = 'public_publicAll';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.start_date <= ? AND v.end_date >= ? AND (v.status IS NULL OR LOWER(TRIM(v.status)) IN ('genehmigt','beantragt')) ORDER BY v.start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
} else {
|
||||
if ($onlyApproved) {
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? AND LOWER(TRIM(v.status)) = 'genehmigt' ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
} else {
|
||||
if ($includeRejected) {
|
||||
$branch = 'regular_includeRejected';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
} else {
|
||||
$branch = 'regular_excludeRejected';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? AND (v.status IS NULL OR LOWER(TRIM(v.status)) != 'abgelehnt') ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$statusMode = 'active';
|
||||
}
|
||||
}
|
||||
|
||||
$includeCompany = !isset($_GET['include_company']) || $_GET['include_company'] === '1' || $_GET['include_company'] === 'true';
|
||||
$requestedTypes = vacationApiRequestedTypes($_GET['absence_types'] ?? null, $scope);
|
||||
|
||||
$hasAbsenceReasonColumn = vacationApiTableHasColumn($pdo, 'vacations', 'absence_reason');
|
||||
$absenceTypeSelect = $hasAbsenceReasonColumn ? 'v.absence_reason' : "'" . vacationAbsenceDefaultReason() . "'";
|
||||
|
||||
$selectColumns = "
|
||||
SELECT
|
||||
v.id,
|
||||
v.user_id,
|
||||
v.start_date,
|
||||
v.end_date,
|
||||
v.days,
|
||||
v.status,
|
||||
v.comment_user,
|
||||
u.vorname,
|
||||
u.nachname,
|
||||
{$absenceTypeSelect} AS absence_type
|
||||
FROM vacations v
|
||||
JOIN users u ON v.user_id = u.id
|
||||
WHERE v.start_date <= ?
|
||||
AND v.end_date >= ?
|
||||
";
|
||||
|
||||
$params = [$end, $start];
|
||||
|
||||
if ($scope === 'personal') {
|
||||
$selectColumns .= " AND v.user_id = ?";
|
||||
$params[] = $_SESSION['userid'];
|
||||
} elseif ($scope === 'team' || $scope === 'admin_all') {
|
||||
// No further restriction here. Scope filters are applied in PHP so
|
||||
// the query remains flexible for future admin and team views.
|
||||
}
|
||||
|
||||
$selectColumns .= " ORDER BY v.start_date ASC, v.id ASC";
|
||||
|
||||
$stmt = $pdo->prepare($selectColumns);
|
||||
$stmt->execute($params);
|
||||
$vacations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$events = [];
|
||||
|
||||
foreach ($vacations as $v) {
|
||||
$absenceType = vacationApiNormalizeAbsenceType($v['absence_type'] ?? '');
|
||||
$status = vacationApiNormalizeStatus($v['status'] ?? '');
|
||||
|
||||
if ($scope === 'team' && $absenceType !== 'urlaub') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($requestedTypes !== null && !in_array($absenceType, $requestedTypes, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!vacationApiStatusAllowed($status, $statusMode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$employeeName = trim((string)($v['vorname'] ?? '') . ' ' . (string)($v['nachname'] ?? ''));
|
||||
$typeLabel = vacationApiTypeLabel($absenceType);
|
||||
$statusLabel = vacationApiStatusLabel($status);
|
||||
|
||||
if ($scope === 'personal') {
|
||||
$title = $typeLabel;
|
||||
} elseif ($employeeName !== '') {
|
||||
$title = $employeeName . ' - ' . $typeLabel;
|
||||
} else {
|
||||
$title = $typeLabel;
|
||||
}
|
||||
|
||||
if ($status !== '' && $status !== 'genehmigt') {
|
||||
$title .= ' (' . $statusLabel . ')';
|
||||
}
|
||||
|
||||
try {
|
||||
$vacations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($debugMode) {
|
||||
$rawStatuses = array_map(function($r){ return $r['status'] ?? null; }, $vacations);
|
||||
$meta = [
|
||||
'branch' => $branch,
|
||||
'count' => count($vacations),
|
||||
'raw_statuses' => $rawStatuses
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($vacations as $v) {
|
||||
if (isset($v['status'])) {
|
||||
$normalized = preg_replace('/\s+/u', ' ', $v['status']);
|
||||
$status = mb_strtolower(trim($normalized));
|
||||
} else {
|
||||
$status = '';
|
||||
}
|
||||
|
||||
if (!$isAdmin && !$includeRejected && mb_stripos($status, 'abgelehnt') !== false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isApproved = (mb_stripos($status, 'genehmigt') !== false);
|
||||
$employeeName = trim(($v['vorname'] ?? '') . ' ' . ($v['nachname'] ?? ''));
|
||||
if ($showEmployeeNames && $employeeName !== '') {
|
||||
$title = $employeeName;
|
||||
if ($v['status'] !== null && $v['status'] !== '') {
|
||||
$title .= ' (' . $v['status'] . ')';
|
||||
}
|
||||
} elseif ($isApproved) {
|
||||
$title = 'Urlaub';
|
||||
} else {
|
||||
$title = 'Urlaubsantrag';
|
||||
}
|
||||
|
||||
try {
|
||||
$endInclusive = (new DateTime($v['end_date']))->modify('+1 day')->format('Y-m-d');
|
||||
} catch (Exception $e) {
|
||||
$endInclusive = $v['start_date'];
|
||||
}
|
||||
|
||||
$events[] = [
|
||||
'id' => 'vac_' . $v['id'],
|
||||
'title' => $title,
|
||||
'start' => $v['start_date'],
|
||||
'end' => $endInclusive,
|
||||
'allDay' => true,
|
||||
'color' => ($isApproved) ? '#28a745' : '#ffc107',
|
||||
'extendedProps' => [
|
||||
'type' => 'user',
|
||||
'user_id' => $v['user_id'],
|
||||
'employee_name' => $employeeName,
|
||||
'status' => $v['status'],
|
||||
'comment' => $v['comment_user'] ?? ''
|
||||
]
|
||||
];
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
$payload = ['error' => $ex->getMessage(), 'branch' => $branch, 'trace' => $ex->getTraceAsString()];
|
||||
echo json_encode($payload);
|
||||
exit;
|
||||
$endInclusive = (new DateTime($v['end_date']))->modify('+1 day')->format('Y-m-d');
|
||||
} catch (Exception $e) {
|
||||
$endInclusive = $v['start_date'];
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
$payload = ['error' => $ex->getMessage(), 'branch' => $branch, 'trace' => $ex->getTraceAsString()];
|
||||
echo json_encode($payload);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM company_holidays WHERE start_date <= ? AND end_date >= ? ORDER BY start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
$holidays = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$backgroundColor = vacationApiTypeColor($absenceType);
|
||||
if ($status === 'abgelehnt') {
|
||||
$backgroundColor = vacationApiStatusColor($status);
|
||||
}
|
||||
|
||||
foreach ($holidays as $h) {
|
||||
$endInclusive = (new DateTime($h['end_date']))->modify('+1 day')->format('Y-m-d');
|
||||
$events[] = [
|
||||
'id' => 'com_' . $h['id'],
|
||||
'title' => $h['description'] ?: 'Betriebsurlaub',
|
||||
'start' => $h['start_date'],
|
||||
'id' => 'vac_' . $v['id'],
|
||||
'title' => $title,
|
||||
'start' => $v['start_date'],
|
||||
'end' => $endInclusive,
|
||||
'allDay' => true,
|
||||
'color' => '#007bff',
|
||||
'backgroundColor' => $backgroundColor,
|
||||
'borderColor' => $backgroundColor,
|
||||
'textColor' => '#ffffff',
|
||||
'extendedProps' => [
|
||||
'type' => 'company',
|
||||
'description' => $h['description']
|
||||
]
|
||||
'type' => 'user',
|
||||
'user_id' => $v['user_id'],
|
||||
'employee_name' => $employeeName,
|
||||
'absence_type' => $absenceType,
|
||||
'absence_label' => $typeLabel,
|
||||
'status' => $v['status'],
|
||||
'status_label' => $statusLabel,
|
||||
'comment' => $v['comment_user'] ?? '',
|
||||
'scope' => $scope,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
if ($debugMode) {
|
||||
echo json_encode(['events' => $events, 'meta' => $meta]);
|
||||
} else {
|
||||
echo json_encode($events);
|
||||
if ($includeCompany) {
|
||||
$stmt = $pdo->prepare("SELECT id, start_date, end_date, description, vertretung, vertretertelefon, vertreteradresse, vertreterurl FROM company_holidays WHERE start_date <= ? AND end_date >= ? ORDER BY start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
$holidays = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
foreach ($holidays as $h) {
|
||||
try {
|
||||
$endInclusive = (new DateTime($h['end_date']))->modify('+1 day')->format('Y-m-d');
|
||||
} catch (Exception $e) {
|
||||
$endInclusive = $h['start_date'];
|
||||
}
|
||||
|
||||
$description = trim((string)($h['description'] ?? ''));
|
||||
$title = $description !== '' ? $description : 'Betriebsurlaub';
|
||||
|
||||
$events[] = [
|
||||
'id' => 'com_' . $h['id'],
|
||||
'title' => $title,
|
||||
'start' => $h['start_date'],
|
||||
'end' => $endInclusive,
|
||||
'allDay' => true,
|
||||
'backgroundColor' => '#0b7285',
|
||||
'borderColor' => '#0b7285',
|
||||
'textColor' => '#ffffff',
|
||||
'extendedProps' => [
|
||||
'type' => 'company',
|
||||
'description' => $description,
|
||||
'vertretung' => $h['vertretung'] ?? '',
|
||||
'vertretertelefon' => $h['vertretertelefon'] ?? '',
|
||||
'vertreteradresse' => $h['vertreteradresse'] ?? '',
|
||||
'vertreterurl' => $h['vertreterurl'] ?? '',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
$json = json_encode(
|
||||
$events,
|
||||
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE
|
||||
);
|
||||
|
||||
if ($json === false) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'error' => 'Kalenderdaten konnten nicht kodiert werden.',
|
||||
'json_error' => json_last_error_msg(),
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo $json;
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user