- Removed hardcoded iCloud username and password from Data.class.php - Added config/icloud.php for external credential storage - Protected config directory with Apache access rules - Updated Data constructor to load credentials from config - Kept backwards compatibility with existing Data instantiation
663 lines
22 KiB
PHP
663 lines
22 KiB
PHP
<?php
|
||
|
||
class Data {
|
||
|
||
public $id;
|
||
private $pdo;
|
||
private $icloudCalendarUrl;
|
||
private $icloudUser;
|
||
private $icloudPass;
|
||
|
||
|
||
public function __construct($pdo, ?array $icloudConfig = null) {
|
||
$this->pdo = $pdo;
|
||
|
||
if ($icloudConfig === null) {
|
||
$configPath = __DIR__ . '/config/icloud.php';
|
||
$icloudConfig = file_exists($configPath) ? require $configPath : [];
|
||
}
|
||
|
||
$this->icloudCalendarUrl = $icloudConfig['calendar_url'] ?? '';
|
||
$this->icloudUser = $icloudConfig['username'] ?? '';
|
||
$this->icloudPass = $icloudConfig['password'] ?? '';
|
||
}
|
||
|
||
public function renderTemplate(string $template, array $vars): string {
|
||
foreach ($vars as $key => $value) {
|
||
$template = preg_replace(
|
||
'/{{\s*' . preg_quote($key, '/') . '\s*}}/',
|
||
(string)$value,
|
||
$template
|
||
);
|
||
}
|
||
return $template;
|
||
}
|
||
|
||
|
||
public function getDataByID($id, $column){
|
||
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE id = :id");
|
||
$stmt->execute([':id' => $id]);
|
||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
return $row[$column] ?? null;
|
||
}
|
||
|
||
public function getTerminDataById($id, $column){
|
||
$stmt = $this->pdo->prepare("SELECT * FROM termine WHERE id = :id");
|
||
$stmt->execute([':id' => $id]);
|
||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
return $row[$column] ?? null;
|
||
}
|
||
|
||
public function getSettingsData($column){
|
||
$stmt = $this->pdo->prepare("SELECT * FROM settings_calendar WHERE id = 1");
|
||
$stmt->execute();
|
||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
return $row[$column] ?? null;
|
||
}
|
||
|
||
public function timestampToDate($timestamp){
|
||
return date('d.m.Y H:i', $timestamp);
|
||
}
|
||
|
||
/* ======================================
|
||
KALENDER HASH BERECHNEN (zentral)
|
||
====================================== */
|
||
private function buildCalendarHashFromTermin(array $t): string {
|
||
$data = [
|
||
'start' => (int)$t['startzeit'],
|
||
'end' => (int)$t['endzeit'],
|
||
'title' => trim((string)$t['location']),
|
||
'desc' => trim((string)$t['beschreibung']),
|
||
];
|
||
|
||
return hash('sha256', json_encode($data));
|
||
}
|
||
|
||
/* ======================================
|
||
KALENDER SYNC STATUS SPEICHERN
|
||
====================================== */
|
||
private function storeCalendarSyncState(int $terminId, array $terminRow): void
|
||
{
|
||
$hash = $this->buildCalendarHashFromTermin($terminRow);
|
||
$eventId = "termin-$terminId@anjuma";
|
||
|
||
$stmt = $this->pdo->prepare("
|
||
UPDATE termine SET
|
||
calendar_event_id = :eid,
|
||
calendar_hash = :hash,
|
||
calendar_synced_at = :ts
|
||
WHERE id = :id
|
||
");
|
||
|
||
$stmt->execute([
|
||
':eid' => $eventId,
|
||
':hash' => $hash,
|
||
':ts' => time(),
|
||
':id' => $terminId
|
||
]);
|
||
}
|
||
|
||
|
||
|
||
public function getTerminLabel($id) {
|
||
$sql = "SELECT status FROM termine WHERE id = :id";
|
||
$stmt = $this->pdo->prepare($sql);
|
||
$stmt->execute([':id' => $id]);
|
||
$status = $stmt->fetchColumn();
|
||
|
||
return match ((int)$status) {
|
||
0 => "status-open", // Blau
|
||
1 => "status-ready", // Gelb
|
||
2 => "status-done", // Grün
|
||
3 => "status-cancel", // Rot
|
||
default => "",
|
||
};
|
||
}
|
||
|
||
|
||
public function getOnlineStatusLabel($id): string {
|
||
$stmt = $this->pdo->prepare("SELECT online FROM users WHERE id = :id");
|
||
$stmt->execute([':id' => $id]);
|
||
$online = $stmt->fetchColumn();
|
||
|
||
if ($online === false) {
|
||
return "badge-secondary";
|
||
}
|
||
|
||
return ((int)$online === 0) ? "badge-danger" : "badge-success";
|
||
}
|
||
|
||
public function getTodoStatusLabel($id): string {
|
||
$stmt = $this->pdo->prepare("SELECT status FROM todo WHERE id = :id");
|
||
$stmt->execute([':id' => $id]);
|
||
$status = $stmt->fetchColumn();
|
||
|
||
return match ((int)$status) {
|
||
0 => "danger",
|
||
1 => "warning",
|
||
2 => "success",
|
||
default => "secondary",
|
||
};
|
||
}
|
||
|
||
private function getLastEditorInfo($terminId)
|
||
{
|
||
$sql = $this->pdo->prepare("
|
||
SELECT user_id, timestamp
|
||
FROM changes
|
||
WHERE termin_id = :id
|
||
ORDER BY timestamp DESC
|
||
LIMIT 1
|
||
");
|
||
$sql->execute([':id' => $terminId]);
|
||
$row = $sql->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if (!$row) {
|
||
return [
|
||
'name' => '—',
|
||
'date' => '—'
|
||
];
|
||
}
|
||
|
||
return [
|
||
'name' => $this->getDataByID($row['user_id'], "name"),
|
||
'date' => date("d.m.Y H:i", $row['timestamp'])
|
||
];
|
||
}
|
||
|
||
|
||
private function caldavPut($url, $ics, $isUpdate = false)
|
||
{
|
||
$ch = curl_init($url);
|
||
|
||
curl_setopt($ch, CURLOPT_USERPWD, $this->icloudUser . ":" . $this->icloudPass);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
|
||
curl_setopt($ch, CURLOPT_HTTPHEADER, $isUpdate ? [
|
||
"Content-Type: text/calendar"
|
||
// KEIN If-None-Match bei Updates!
|
||
] : [
|
||
"Content-Type: text/calendar",
|
||
"If-None-Match: *" // nur bei neuen Events
|
||
]);
|
||
|
||
curl_setopt($ch, CURLOPT_POSTFIELDS, $ics);
|
||
|
||
$response = curl_exec($ch);
|
||
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||
$err = curl_error($ch);
|
||
|
||
curl_close($ch);
|
||
|
||
// 🔍 DEBUG VOR dem return
|
||
$this->debugLog("PUT to $url | status=$status | error=$err | isUpdate=" . ($isUpdate ? "1" : "0"));
|
||
|
||
if ($status !== 201 && $status !== 204) {
|
||
$this->debugLog("Response body: " . substr((string)$response, 0, 500));
|
||
}
|
||
|
||
return $status === 201 || $status === 204;
|
||
}
|
||
|
||
|
||
public function createCalendarEvent($id, $startTs, $endTs, $location, $beschreibung)
|
||
{
|
||
$uid = "termin-$id@anjuma";
|
||
|
||
$tz = 'Europe/Berlin';
|
||
$dtstamp = gmdate('Ymd\THis\Z');
|
||
|
||
// Sicherheits-Fallback, falls endTs 0 ist
|
||
if (empty($endTs) || $endTs <= 0) {
|
||
$endTs = $startTs + 2 * 3600; // +2 Stunden
|
||
}
|
||
|
||
// Start/Ende in lokaler Zeit
|
||
$dtstartStr = (new DateTime("@$startTs"))
|
||
->setTimezone(new DateTimeZone($tz))
|
||
->format('Ymd\THis');
|
||
|
||
$dtendStr = (new DateTime("@$endTs"))
|
||
->setTimezone(new DateTimeZone($tz))
|
||
->format('Ymd\THis');
|
||
|
||
$location = $this->icsEscape($location);
|
||
$beschreibung = $this->icsEscape($beschreibung);
|
||
|
||
// Status-Name bestimmen
|
||
$statusRaw = $this->getTerminDataById($id, "status");
|
||
$statusName = [
|
||
0 => "Offen",
|
||
1 => "Bereit",
|
||
2 => "Erledigt",
|
||
3 => "Storniert"
|
||
][$statusRaw] ?? "Unbekannt";
|
||
|
||
// Ersteller-Name holen
|
||
$creatorId = $this->getTerminDataById($id, "user_id");
|
||
$creatorName = $this->getDataByID($creatorId, "name");
|
||
|
||
// Letzten Bearbeiter holen
|
||
$editInfo = $this->getLastEditorInfo($id);
|
||
|
||
// Gage holen
|
||
$gage = $this->getTerminDataById($id, "gage");
|
||
|
||
$vars = [
|
||
'id' => $id,
|
||
'status' => $statusName,
|
||
'locationtype' => $this->getTerminDataById($id, "locationtype"),
|
||
'location' => $this->getTerminDataById($id, "location"),
|
||
'startzeit' => date('d.m.Y H:i', $this->getTerminDataById($id, "startzeit")),
|
||
'endzeit' => date('H:i', $this->getTerminDataById($id, "endzeit")),
|
||
'gage' => $this->getTerminDataById($id, "gage"),
|
||
'desc' => $this->getTerminDataById($id, "beschreibung"),
|
||
'creator' => $creatorName,
|
||
'last_editor' => $editInfo['name'],
|
||
'last_edited' => $editInfo['date']
|
||
];
|
||
|
||
$summary = $this->renderTemplate($this->getSettingsData("title_template"), $vars);
|
||
$beschreibungFull = $this->renderTemplate($this->getSettingsData("description_template"), $vars);
|
||
|
||
$beschreibungFull = $this->icsEscape($beschreibungFull);
|
||
|
||
|
||
|
||
$ics =
|
||
"BEGIN:VCALENDAR\r\n" .
|
||
"VERSION:2.0\r\n" .
|
||
"PRODID:-//ANJUMA//DE\r\n" .
|
||
"CALSCALE:GREGORIAN\r\n" .
|
||
"BEGIN:VEVENT\r\n" .
|
||
"UID:$uid\r\n" .
|
||
"DTSTAMP:$dtstamp\r\n" .
|
||
"DTSTART;TZID=$tz:$dtstartStr\r\n" .
|
||
"DTEND;TZID=$tz:$dtendStr\r\n" .
|
||
"SUMMARY:$summary\r\n" .
|
||
"LOCATION:$location\r\n" .
|
||
"DESCRIPTION:$beschreibungFull\r\n" .
|
||
"URL:https://dashboard.anjuma-crew.de/termin_show.php?id=$id\r\n" .
|
||
|
||
// Erinnerung 1 Tag vorher
|
||
"BEGIN:VALARM\r\n" .
|
||
"TRIGGER:-P1D\r\n" .
|
||
"ACTION:DISPLAY\r\n" .
|
||
"DESCRIPTION:Erinnerung\r\n" .
|
||
"END:VALARM\r\n" .
|
||
|
||
"END:VEVENT\r\n" .
|
||
"END:VCALENDAR\r\n";
|
||
|
||
$url = $this->icloudCalendarUrl . "termin-$id.ics";
|
||
|
||
// Create = isUpdate=false
|
||
$success = $this->caldavPut($url, $ics, false);
|
||
|
||
if ($success) {
|
||
// Termin neu laden (für Hash)
|
||
$stmt = $this->pdo->prepare("SELECT * FROM termine WHERE id = :id");
|
||
$stmt->execute([':id' => $id]);
|
||
$termin = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if ($termin) {
|
||
$this->storeCalendarSyncState($id, $termin);
|
||
}
|
||
}
|
||
|
||
return $success;
|
||
|
||
}
|
||
|
||
|
||
|
||
public function updateCalendarEvent($id)
|
||
{
|
||
$stmt = $this->pdo->prepare("SELECT * FROM termine WHERE id = :id");
|
||
$stmt->execute([':id' => $id]);
|
||
$t = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if (!$t) {
|
||
$this->debugLog("updateCalendarEvent: Termin $id nicht gefunden");
|
||
return false;
|
||
}
|
||
|
||
$startTs = (int)$t["startzeit"];
|
||
$endTs = (int)$t["endzeit"];
|
||
$location = $t["location"] ?? "";
|
||
$beschreibung = $t["beschreibung"] ?? "";
|
||
|
||
$uid = "termin-$id@anjuma";
|
||
$tz = 'Europe/Berlin';
|
||
$dtstamp = gmdate('Ymd\THis\Z');
|
||
|
||
if (empty($endTs) || $endTs <= 0) {
|
||
$endTs = $startTs + 2 * 3600;
|
||
}
|
||
|
||
$dtstartStr = (new DateTime("@$startTs"))
|
||
->setTimezone(new DateTimeZone($tz))
|
||
->format('Ymd\THis');
|
||
|
||
$dtendStr = (new DateTime("@$endTs"))
|
||
->setTimezone(new DateTimeZone($tz))
|
||
->format('Ymd\THis');
|
||
|
||
$locationEsc = $this->icsEscape($location);
|
||
$beschreibungEsc = $this->icsEscape($beschreibung);
|
||
$summary = "ANJUMA DJ $locationEsc ($id)";
|
||
|
||
// Status-Name bestimmen
|
||
$statusRaw = $this->getTerminDataById($id, "status");
|
||
$statusName = [
|
||
0 => "Offen",
|
||
1 => "Bereit",
|
||
2 => "Erledigt",
|
||
3 => "Storniert"
|
||
][$statusRaw] ?? "Unbekannt";
|
||
|
||
// Letzten Bearbeiter holen
|
||
$editInfo = $this->getLastEditorInfo($id);
|
||
|
||
// Gage holen
|
||
$gage = $this->getTerminDataById($id, "gage");
|
||
|
||
$creatorId = $this->getTerminDataById($id, "user_id");
|
||
$creatorName = $this->getDataByID($creatorId, "name");
|
||
|
||
$vars = [
|
||
'id' => $id,
|
||
'status' => $statusName,
|
||
'locationtype' => $this->getTerminDataById($id, "locationtype"),
|
||
'location' => $this->getTerminDataById($id, "location"),
|
||
'startzeit' => date('d.m.Y H:i', $this->getTerminDataById($id, "startzeit")),
|
||
'endzeit' => date('H:i', $this->getTerminDataById($id, "endzeit")),
|
||
'gage' => $this->getTerminDataById($id, "gage"),
|
||
'desc' => $this->getTerminDataById($id, "beschreibung"),
|
||
'creator' => $creatorName,
|
||
'last_editor' => $editInfo['name'],
|
||
'last_edited' => $editInfo['date']
|
||
];
|
||
|
||
$summary = $this->renderTemplate($this->getSettingsData("title_template"), $vars);
|
||
$beschreibungFull = $this->renderTemplate($this->getSettingsData("description_template"), $vars);
|
||
|
||
$beschreibungFull = $this->icsEscape($beschreibungFull);
|
||
|
||
|
||
|
||
$ics =
|
||
"BEGIN:VCALENDAR\r\n" .
|
||
"VERSION:2.0\r\n" .
|
||
"PRODID:-//ANJUMA//DE\r\n" .
|
||
"CALSCALE:GREGORIAN\r\n" .
|
||
"BEGIN:VEVENT\r\n" .
|
||
"UID:$uid\r\n" .
|
||
"DTSTAMP:$dtstamp\r\n" .
|
||
"DTSTART;TZID=$tz:$dtstartStr\r\n" .
|
||
"DTEND;TZID=$tz:$dtendStr\r\n" .
|
||
"SUMMARY:$summary\r\n" .
|
||
"LOCATION:$locationEsc\r\n" .
|
||
"DESCRIPTION:$beschreibungFull\r\n" .
|
||
"URL:https://dashboard.anjuma-crew.de/termin_show.php?id=$id\r\n" .
|
||
|
||
"BEGIN:VALARM\r\n" .
|
||
"TRIGGER:-P1D\r\n" .
|
||
"ACTION:DISPLAY\r\n" .
|
||
"DESCRIPTION:Erinnerung\r\n" .
|
||
"END:VALARM\r\n" .
|
||
|
||
"BEGIN:VALARM\r\n" .
|
||
"TRIGGER:-PT2H\r\n" .
|
||
"ACTION:DISPLAY\r\n" .
|
||
"DESCRIPTION:Erinnerung\r\n" .
|
||
"END:VALARM\r\n" .
|
||
|
||
"END:VEVENT\r\n" .
|
||
"END:VCALENDAR\r\n";
|
||
|
||
$url = $this->icloudCalendarUrl . "termin-$id.ics";
|
||
|
||
// Update = isUpdate=true
|
||
$success = $this->caldavPut($url, $ics, true);
|
||
|
||
if ($success) {
|
||
$this->storeCalendarSyncState($id, $t);
|
||
}
|
||
|
||
return $success;
|
||
|
||
}
|
||
|
||
|
||
public function deleteCalendarEvent($id)
|
||
{
|
||
$url = $this->icloudCalendarUrl . "termin-$id.ics";
|
||
|
||
$ch = curl_init($url);
|
||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
|
||
curl_setopt($ch, CURLOPT_USERPWD, $this->icloudUser . ":" . $this->icloudPass);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||
|
||
$response = curl_exec($ch);
|
||
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||
|
||
curl_close($ch);
|
||
|
||
return $status === 200 || $status === 204;
|
||
}
|
||
|
||
|
||
|
||
public function changeTermin($id, $was, $value): void {
|
||
$allowed = [
|
||
'startzeit', 'endzeit', 'location', 'locationtype',
|
||
'gage', 'anwesend', 'beschreibung', 'status',
|
||
'ansprechpartner', 'preisprostunde', 'realendzeit',
|
||
];
|
||
|
||
if (!in_array($was, $allowed, true)) {
|
||
throw new InvalidArgumentException("Ungültige Spalte: " . $was);
|
||
}
|
||
|
||
$sql = "UPDATE termine SET `" . $was . "` = :value WHERE id = :id";
|
||
$stmt = $this->pdo->prepare($sql);
|
||
$stmt->execute([':value' => $value, ':id' => $id]);
|
||
}
|
||
private function icsEscape($text)
|
||
{
|
||
// Normalize line endings (Windows/Mac/Linux)
|
||
$text = str_replace(["\r\n", "\r"], "\n", $text);
|
||
|
||
// ICS requires escaping BACKSLASH first!
|
||
$text = str_replace("\\", "\\\\", $text);
|
||
|
||
// Then escape comma and semicolon
|
||
$text = str_replace(",", "\\,", $text);
|
||
$text = str_replace(";", "\\;", $text);
|
||
|
||
// Only now convert \n to ICS linebreaks
|
||
$text = str_replace("\n", "\\n", $text);
|
||
|
||
return $text;
|
||
}
|
||
|
||
public function createTermin($startzeit, $endzeit, $location, $user_id, $gage, $locationtype)
|
||
{
|
||
if ($gage === "" || $gage === null) $gage = 0;
|
||
|
||
$sql = "INSERT INTO termine
|
||
(startzeit, endzeit, locationtype, location, user_id, gage, status, anwesend, beschreibung)
|
||
VALUES (:startzeit, :endzeit, :locationtype, :location, :user_id, :gage, 0, '[]', '')";
|
||
|
||
$stmt = $this->pdo->prepare($sql);
|
||
$stmt->execute([
|
||
':startzeit' => $startzeit,
|
||
':endzeit' => $endzeit,
|
||
':locationtype' => $locationtype,
|
||
':location' => $location,
|
||
':user_id' => $user_id,
|
||
':gage' => $gage
|
||
]);
|
||
|
||
$id = $this->pdo->lastInsertId();
|
||
|
||
$this->createCalendarEvent($id, $startzeit, $endzeit, $location, "");
|
||
|
||
return $id;
|
||
}
|
||
|
||
|
||
public function createChanges($id, $user_id, $was, $alt, $neu)
|
||
{
|
||
// =============================================
|
||
// 1) CHANGE SPEICHERN
|
||
// =============================================
|
||
$stmt = $this->pdo->prepare("
|
||
INSERT INTO changes (termin_id, user_id, was, alt, neu, timestamp)
|
||
VALUES (:id, :user, :was, :alt, :neu, :ts)
|
||
");
|
||
|
||
$stmt->execute([
|
||
':id' => $id,
|
||
':user' => $user_id,
|
||
':was' => $was,
|
||
':alt' => $alt,
|
||
':neu' => $neu,
|
||
':ts' => time()
|
||
]);
|
||
// -------------------------------------------
|
||
// NTFY BENACHRICHTIGUNG (schön formatiert)
|
||
// -------------------------------------------
|
||
|
||
// === NTFY CHANNEL ===
|
||
/*$ntfy_url = "https://ntfy.anjuma-crew.de/anjuma-dashboard"; // <<< anpassen
|
||
|
||
// === Basic Auth ===
|
||
$auth = "Basic anVzdGluOm5ZZ0dwNnNNRWdMRWwx";
|
||
|
||
// === Nachricht bauen ===
|
||
$username = $this->getDataByID($user_id, "name");
|
||
|
||
if ($was === "anwesend") {
|
||
$altDecoded = json_decode($alt, true) ?: [];
|
||
$neuDecoded = json_decode($neu, true) ?: [];
|
||
|
||
// IDs zu Namen umwandeln
|
||
$altNames = array_map(fn($u) => $this->getDataByID($u, "name"), $altDecoded);
|
||
$neuNames = array_map(fn($u) => $this->getDataByID($u, "name"), $neuDecoded);
|
||
|
||
$alt = implode(", ", $altNames);
|
||
$neu = implode(", ", $neuNames);
|
||
}
|
||
|
||
// Mapping für schönere Bezeichnungen syfe-xapm-vcjx-dnbi
|
||
$labelMap = [
|
||
"status" => "Status",
|
||
"anwesend" => "Anwesende Personen",
|
||
"location" => "Location",
|
||
"ansprechpartner" => "Ansprechpartner",
|
||
"gage" => "Gage",
|
||
"preisprostunde" => "Preis pro Stunde",
|
||
"startzeit" => "Startzeit",
|
||
"endzeit" => "Endzeit",
|
||
"realendzeit" => "Tatsächliche Endzeit",
|
||
"create" => "Termin Erstellt"
|
||
];
|
||
|
||
$label = $labelMap[$was] ?? ucfirst($was);
|
||
|
||
// Titel
|
||
$title = "Änderung in Termin #$id – $label";
|
||
|
||
// Nachricht
|
||
$body =
|
||
"$username hat $label geändert.\n\n" .
|
||
"🔻 Alt: $alt\n" .
|
||
"🔺 Neu: $neu";
|
||
|
||
|
||
// === CURL Request ===
|
||
$ch = curl_init($ntfy_url);
|
||
curl_setopt($ch, CURLOPT_POST, true);
|
||
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||
"Authorization: $auth",
|
||
"X-Title: $title",
|
||
"X-Priority: 3",
|
||
"Content-Type: text/plain"
|
||
]);
|
||
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
|
||
curl_exec($ch);
|
||
curl_close($ch);*/
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
|
||
public function setTerminStatus($id, $status): void {
|
||
$this->changeTermin($id, 'status', $status);
|
||
}
|
||
|
||
public function setTodoTitle($id, $title): void {
|
||
$stmt = $this->pdo->prepare("UPDATE todo SET title = :title WHERE id = :id");
|
||
$stmt->execute([':title' => $title, ':id' => $id]);
|
||
}
|
||
|
||
public function setTodoDescription($id, $description): void {
|
||
$stmt = $this->pdo->prepare("UPDATE todo SET description = :desc WHERE id = :id");
|
||
$stmt->execute([':desc' => $description, ':id' => $id]);
|
||
}
|
||
|
||
public function deleteTodoById($id): void {
|
||
$stmt = $this->pdo->prepare("DELETE FROM todo WHERE id = :id");
|
||
$stmt->execute([':id' => $id]);
|
||
}
|
||
|
||
public function createTodo($id, $title, $description): void {
|
||
$stmt = $this->pdo->prepare("INSERT INTO todo (creator, title, description) VALUES (:creator, :title, :desc)");
|
||
$stmt->execute([':creator' => $id, ':title' => $title, ':desc' => $description]);
|
||
}
|
||
|
||
public function getTodoDataById($id, $column){
|
||
$stmt = $this->pdo->prepare("SELECT * FROM todo WHERE id = :id");
|
||
$stmt->execute([':id' => $id]);
|
||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
return $row[$column] ?? null;
|
||
}
|
||
|
||
public function getAllReadyGigs(): int {
|
||
$stmt = $this->pdo->prepare("SELECT COUNT(*) FROM termine WHERE status = :status");
|
||
$stmt->execute([':status' => 1]);
|
||
return (int)$stmt->fetchColumn();
|
||
}
|
||
|
||
public function getAllProcessingGigs(): int {
|
||
$stmt = $this->pdo->prepare("SELECT COUNT(*) FROM termine WHERE status = :status");
|
||
$stmt->execute([':status' => 0]);
|
||
return (int)$stmt->fetchColumn();
|
||
}
|
||
|
||
public function getAllCompletedGigs(): int {
|
||
$stmt = $this->pdo->prepare("SELECT COUNT(*) FROM termine WHERE status = :status");
|
||
$stmt->execute([':status' => 2]);
|
||
return (int)$stmt->fetchColumn();
|
||
}
|
||
|
||
private function debugLog($msg) {
|
||
$file = __DIR__ . "/debug/caldav_debug.log";
|
||
file_put_contents($file, date("[Y-m-d H:i:s] ") . $msg . "\n", FILE_APPEND);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
?>
|