Files
emailtemplate.it/public/tools/db-doctor.php
2026-02-09 01:38:39 +01:00

112 lines
3.5 KiB
PHP
Executable File

<?php
header('Content-Type: text/html; charset=utf-8');
$conf = @include __DIR__ . '/../../inc/config.php';
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES|ENT_SUBSTITUTE,'UTF-8'); }
if (!is_array($conf) || !isset($conf['projectdb'])) {
echo 'Invalid config.php (expected return array with key projectdb)'; exit;
}
$cfg = $conf['projectdb'];
$prefix = (string)($cfg['prefix'] ?? '');
$attempts=[]; $pdo=null;
$mkPdo=function(array $cfg) use(&$attempts){
$host = $cfg['db_host'] ?? null;
$socket = $cfg['db_socket'] ?? null;
$name = $cfg['db_name'] ?? '';
$user = $cfg['db_user'] ?? '';
$pass = $cfg['db_pass'] ?? '';
$charset = $cfg['db_charset'] ?? 'utf8mb4';
$port = (int)($cfg['db_port'] ?? 3306);
$dsn = $socket
? "mysql:unix_socket={$socket};dbname={$name};charset={$charset}"
: "mysql:host=".($host?:'127.0.0.1').";port={$port};dbname={$name};charset={$charset}";
try{
$pdo = new PDO($dsn,$user,$pass,[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,PDO::ATTR_EMULATE_PREPARES=>false]);
$attempts[]=['dsn'=>$dsn,'ok'=>true];
return $pdo;
}catch(Throwable $e){
$attempts[]=['dsn'=>$dsn,'ok'=>false,'error'=>$e->getMessage()];
return null;
}
};
if (is_array($cfg)) $pdo=$mkPdo($cfg);
$tables = [
$prefix.'templates',
$prefix.'sections',
$prefix.'blocks',
$prefix.'snippets',
$prefix.'template_items',
$prefix.'section_items',
];
$tblStatus=[];
if ($pdo){
foreach($tables as $t){
try{ $pdo->query("SELECT 1 FROM {$t} LIMIT 1"); $tblStatus[$t]='ok'; }
catch(Throwable $e){ $tblStatus[$t]='missing/invalid: '.$e->getMessage(); }
}
}
?>
<!doctype html>
<html lang="de">
<meta charset="utf-8">
<title>DB-Doctor</title>
<style>
body{font:14px/1.5 system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;background:#f8fafc;color:#0f172a;margin:0;padding:24px;}
.nav a{display:inline-block;margin-right:8px;padding:8px 12px;border:1px solid #e5e7eb;border-radius:8px;background:#fff;text-decoration:none;color:#0f172a}
.nav .active{background:#eef2ff;border-color:#c7d2fe;}
.card{background:#fff;border:1px solid #e5e7eb;border-radius:12px;padding:16px;margin:16px 0;}
table{border-collapse:collapse;width:100%;}
th,td{border-bottom:1px solid #e5e7eb;padding:8px 6px;text-align:left;}
.ok{color:#166534} .bad{color:#991b1b}
code{background:#0b1020;color:#e5e7eb;padding:2px 6px;border-radius:6px}
</style>
<h1>DB-Doctor</h1>
<div class="card">
<h3>Verbindungsversuche</h3>
<table>
<tr><th>DSN</th><th>Ergebnis</th><th>Detail</th></tr>
<?php foreach($attempts as $a): ?>
<tr>
<td><code><?=h($a['dsn'])?></code></td>
<td><?= !empty($a['ok']) ? '<span class="ok">OK</span>' : '<span class="bad">FAIL</span>' ?></td>
<td><?= h($a['error'] ?? '') ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div class="card">
<h3>Tabellen-Check (Templates-Schema)</h3>
<table>
<tr><th>Tabelle</th><th>Status</th></tr>
<?php foreach($tables as $t): ?>
<tr>
<td><code><?=h($t)?></code></td>
<td>
<?php $s=$tblStatus[$t]??'not checked';
echo ($s==='ok') ? '<span class="ok">OK</span>' : '<span class="bad">'.h($s).'</span>'; ?>
</td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div class="card">
<h3>Rohdaten</h3>
<pre><?=h(json_encode([
'prefix'=>$prefix,
'hasPdo'=>!!$pdo,
'configKeys'=>array_keys($conf),
], JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES))?></pre>
</div>
</html>