Upload via GUI (396 Dateien)

This commit is contained in:
2026-11-04 07:56:07 +00:00
parent 3a408cd8dc
commit 79c6424c77
8 changed files with 524 additions and 8 deletions
+126
View File
@@ -1980,6 +1980,132 @@ function run_migrations(PDO $pdo, bool $verbose = false): array
}
}
// E-Mails mit Formatierung und eingebetteten Bildern: HTML-Fassung der Nachricht, Content-ID und Kennzeichnung eingebetteter Bilder
if (!isset($done['php_0070_mail_html'])) {
try {
$drv = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
$columns = function (string $table) use ($pdo, $drv): array {
$rows = $pdo->query($drv === 'sqlite' ? "PRAGMA table_info($table)" : "SHOW COLUMNS FROM $table")->fetchAll();
return array_map(fn($r) => (string) ($r['name'] ?? $r['Field'] ?? ''), $rows);
};
if (!in_array('message_html', $columns('ticket_threads'), true)) $pdo->exec('ALTER TABLE ticket_threads ADD COLUMN message_html MEDIUMTEXT NULL');
$att = $columns('ticket_attachments');
if (!in_array('content_id', $att, true)) $pdo->exec('ALTER TABLE ticket_attachments ADD COLUMN content_id VARCHAR(255) NULL');
if (!in_array('is_inline', $att, true)) $pdo->exec('ALTER TABLE ticket_attachments ADD COLUMN is_inline TINYINT NOT NULL DEFAULT 0');
$pdo->prepare('INSERT INTO schema_migrations (migration) VALUES (?)')->execute(['php_0070_mail_html']);
$result['applied']++;
if ($verbose) $result['log'][] = ' [OK] php_0070_mail_html';
} catch (Throwable $e) {
$result['errors'][] = 'php_0070_mail_html: ' . $e->getMessage();
if ($verbose) $result['log'][] = ' [FAIL] php_0070_mail_html - ' . $e->getMessage();
}
}
// Migration 0071: verknüpfte Tickets, zeitversetzt gesendete Antworten und Berichte per E-Mail nach Zeitplan.
if (!isset($done['php_0071_links_schedules'])) {
try {
$drv = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
$ai = $drv === 'sqlite' ? 'INTEGER PRIMARY KEY AUTOINCREMENT' : 'INT AUTO_INCREMENT PRIMARY KEY';
$eng = $drv === 'sqlite' ? '' : ' ENGINE=InnoDB DEFAULT CHARSET=utf8mb4';
$pdo->exec("CREATE TABLE IF NOT EXISTS ticket_links (
id $ai,
ticket_id INT NOT NULL,
linked_ticket_id INT NOT NULL,
link_type VARCHAR(20) NOT NULL DEFAULT 'related',
created_by INT NULL,
created_at DATETIME NULL,
UNIQUE (ticket_id, linked_ticket_id)
)$eng");
$pdo->exec("CREATE TABLE IF NOT EXISTS scheduled_replies (
id $ai,
ticket_id INT NOT NULL,
staff_id INT NOT NULL,
message MEDIUMTEXT NOT NULL,
set_status VARCHAR(20) NOT NULL DEFAULT 'answered',
resolution_code VARCHAR(40) NULL,
resolution_note TEXT NULL,
signature_choice VARCHAR(40) NULL,
send_at DATETIME NOT NULL,
state VARCHAR(12) NOT NULL DEFAULT 'pending',
error TEXT NULL,
created_at DATETIME NULL,
sent_at DATETIME NULL
)$eng");
$pdo->exec("CREATE TABLE IF NOT EXISTS report_schedules (
id $ai,
report_id INT NOT NULL,
staff_id INT NOT NULL,
recipients TEXT NOT NULL,
frequency VARCHAR(10) NOT NULL DEFAULT 'weekly',
weekday TINYINT NOT NULL DEFAULT 1,
monthday TINYINT NOT NULL DEFAULT 1,
send_time VARCHAR(5) NOT NULL DEFAULT '08:00',
period VARCHAR(12) NOT NULL DEFAULT 'last_7',
enabled TINYINT(1) NOT NULL DEFAULT 1,
next_run_at DATETIME NULL,
last_sent_at DATETIME NULL,
last_error TEXT NULL,
created_at DATETIME NULL
)$eng");
$pdo->prepare('INSERT INTO schema_migrations (migration) VALUES (?)')->execute(['php_0071_links_schedules']);
$result['applied']++;
if ($verbose) $result['log'][] = ' [OK] php_0071_links_schedules';
} catch (Throwable $e) {
$result['errors'][] = 'php_0071_links_schedules: ' . $e->getMessage();
if ($verbose) $result['log'][] = ' [FAIL] php_0071_links_schedules - ' . $e->getMessage();
}
}
// Migration 0072: Merker „Mitarbeiter hat das Ticket gesehen“ für den Zähler in Chrome-Erweiterung und Windows-Programm.
if (!isset($done['php_0072_ticket_acks'])) {
try {
$pdo->exec("CREATE TABLE IF NOT EXISTS ticket_acks (
staff_id INT NOT NULL,
ticket_id INT NOT NULL,
acked_at DATETIME NOT NULL,
PRIMARY KEY (staff_id, ticket_id)
)" . ($pdo->getAttribute(PDO::ATTR_DRIVER_NAME) === 'sqlite' ? '' : ' ENGINE=InnoDB DEFAULT CHARSET=utf8mb4'));
$pdo->prepare('INSERT INTO schema_migrations (migration) VALUES (?)')->execute(['php_0072_ticket_acks']);
$result['applied']++;
if ($verbose) $result['log'][] = ' [OK] php_0072_ticket_acks';
} catch (Throwable $e) {
$result['errors'][] = 'php_0072_ticket_acks: ' . $e->getMessage();
if ($verbose) $result['log'][] = ' [FAIL] php_0072_ticket_acks - ' . $e->getMessage();
}
}
// Migration 0073: weniger Berichts-Mails: nur bei Daten, nur bei Änderung, bei „täglich“ nur an Werktagen.
if (!isset($done['php_0073_report_schedule_quiet'])) {
try {
$drv = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
$cols = array_map(fn($r) => (string) ($r['name'] ?? $r['Field'] ?? ''), $pdo->query($drv === 'sqlite' ? 'PRAGMA table_info(report_schedules)' : 'SHOW COLUMNS FROM report_schedules')->fetchAll());
foreach (['only_if_data' => 'TINYINT NOT NULL DEFAULT 1', 'skip_unchanged' => 'TINYINT NOT NULL DEFAULT 1', 'weekdays_only' => 'TINYINT NOT NULL DEFAULT 0', 'last_hash' => 'VARCHAR(64) NULL', 'last_note' => 'VARCHAR(190) NULL'] as $col => $def) {
if (!in_array($col, $cols, true)) $pdo->exec("ALTER TABLE report_schedules ADD COLUMN {$col} {$def}");
}
$pdo->prepare('INSERT INTO schema_migrations (migration) VALUES (?)')->execute(['php_0073_report_schedule_quiet']);
$result['applied']++;
if ($verbose) $result['log'][] = ' [OK] php_0073_report_schedule_quiet';
} catch (Throwable $e) {
$result['errors'][] = 'php_0073_report_schedule_quiet: ' . $e->getMessage();
if ($verbose) $result['log'][] = ' [FAIL] php_0073_report_schedule_quiet - ' . $e->getMessage();
}
}
// Migration 0074: Merker für die Erinnerung „Ticket wartet auf Antwort“ (eine Erinnerung je Kundennachricht).
if (!isset($done['php_0074_wait_reminder'])) {
try {
$drv = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
$cols = array_map(fn($r) => (string) ($r['name'] ?? $r['Field'] ?? ''), $pdo->query($drv === 'sqlite' ? 'PRAGMA table_info(tickets)' : 'SHOW COLUMNS FROM tickets')->fetchAll());
if (!in_array('wait_reminded_at', $cols, true)) $pdo->exec('ALTER TABLE tickets ADD COLUMN wait_reminded_at DATETIME NULL');
$pdo->prepare('INSERT INTO schema_migrations (migration) VALUES (?)')->execute(['php_0074_wait_reminder']);
$result['applied']++;
if ($verbose) $result['log'][] = ' [OK] php_0074_wait_reminder';
} catch (Throwable $e) {
$result['errors'][] = 'php_0074_wait_reminder: ' . $e->getMessage();
if ($verbose) $result['log'][] = ' [FAIL] php_0074_wait_reminder - ' . $e->getMessage();
}
}
return $result;
}