Files
kaffeekasse-saas/app/database.php
T
clemensandClaude Opus 4.8 064c872c30 Zeitzonen-Angleich PHP/MySQL + veralteten Settings-Test aktualisiert
Zwei vorbestehende, bislang rote Pruefungen behoben.

1) PHP lief in UTC, MySQL in der System-Zeitzone (hier CEST, +2h). Ueberall,
   wo ein in PHP berechneter Zeitstempel gegen MySQL NOW() verglichen wird,
   liefen die Uhren dadurch gegeneinander:
   - Hinweise mit kurzer Restlaufzeit galten sofort als abgelaufen
     (notices: valid_from = NOW() aus MySQL, valid_until aus PHP date()).
   - Auth-Token (Passwort-Reset, E-Mail-Verifikation) liefen bis zu 2h zu
     frueh ab (expires_at aus PHP date(), Pruefung gegen NOW()).
   bootstrap.php pinnt die PHP-Zeitzone jetzt deterministisch aus
   APP_TIMEZONE (Standard Europe/Berlin), app_db_pdo() setzt die DB-Session
   per numerischem Offset auf dieselbe Zeit. Damit stimmen beide Uhren
   ueberein. Behebt check-m8-tenant-isolation (11/1 -> 12/0).

2) check-m3-settings-flow stammte aus M3 und lieferte nicht die spaeter
   hinzugekommenen Pflichtfelder (pdf_row_height_px,
   payment_reminder_interval_days). Dadurch schlug bereits das Update fehl und
   alle Folge-Assertions kippten. Der Test sendet jetzt den vollstaendigen
   Feldsatz wie das Einstellungsformular und prueft die beiden Felder mit.
   Die Update-Funktion selbst war korrekt (7/6 -> 15/0).

Voller Regressionslauf gruen: http-smoke 33/0, role-matrix 55/0,
tenant-isolation 12/0, m3-auth 9/0, password-email 14/0, settings 15/0,
tenant-resolution 12/0, billing 10/0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 08:40:55 +02:00

41 lines
1.2 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/bootstrap.php';
function app_db_pdo(): PDO
{
static $pdo = null;
if ($pdo instanceof PDO) {
return $pdo;
}
$host = app_env('DB_HOST', '');
$database = app_env('DB_NAME', '');
$user = app_env('DB_USER', '');
$password = app_env('DB_PASS', '');
$port = app_env('DB_PORT', '3306');
if ($host === '' || $database === '' || $user === '') {
throw new RuntimeException('Database environment is incomplete.');
}
$dsn = sprintf('mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4', $host, $port, $database);
$pdo = new PDO($dsn, $user, $password ?? '', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => true,
]);
// DB-Session auf denselben Offset wie die (in bootstrap.php gepinnte)
// PHP-Zeitzone setzen, damit MySQL NOW() und PHP-Zeitstempel
// uebereinstimmen. Numerischer Offset, damit keine MySQL-Zeitzonentabellen
// noetig sind.
$offset = (new DateTimeImmutable('now'))->format('P');
$pdo->exec("SET time_zone = '{$offset}'");
return $pdo;
}