debug und so
This commit is contained in:
@@ -5,6 +5,9 @@
|
|||||||
define('APP_URL_PRIMARY', 'https://' . APP_DOMAIN_PRIMARY);
|
define('APP_URL_PRIMARY', 'https://' . APP_DOMAIN_PRIMARY);
|
||||||
define('APP_API_BASE', 'https://api.' . APP_DOMAIN_PRIMARY);
|
define('APP_API_BASE', 'https://api.' . APP_DOMAIN_PRIMARY);
|
||||||
define('APP_DB_ENABLED', true); // set true to enable DB connection
|
define('APP_DB_ENABLED', true); // set true to enable DB connection
|
||||||
|
if (!defined('APP_DEBUG')) {
|
||||||
|
define('APP_DEBUG', false); // Debug in Prod aus
|
||||||
|
}
|
||||||
|
|
||||||
// Crypto-Key für verschlüsselte Felder (Telefon, Kinder etc.)
|
// Crypto-Key für verschlüsselte Felder (Telefon, Kinder etc.)
|
||||||
// Bitte in Staging per Hosting-ENV setzen; dieses putenv dient nur als Fallback/Beispiel.
|
// Bitte in Staging per Hosting-ENV setzen; dieses putenv dient nur als Fallback/Beispiel.
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
define('APP_URL_PRIMARY', 'https://' . APP_DOMAIN_PRIMARY);
|
define('APP_URL_PRIMARY', 'https://' . APP_DOMAIN_PRIMARY);
|
||||||
define('APP_API_BASE', 'https://api.' . APP_DOMAIN_PRIMARY);
|
define('APP_API_BASE', 'https://api.' . APP_DOMAIN_PRIMARY);
|
||||||
define('APP_DB_ENABLED', true); // set true to enable DB connection
|
define('APP_DB_ENABLED', true); // set true to enable DB connection
|
||||||
|
if (!defined('APP_DEBUG')) {
|
||||||
|
define('APP_DEBUG', true); // Debug in Staging
|
||||||
|
}
|
||||||
|
|
||||||
// Crypto-Key für verschlüsselte Felder (Telefon, Kinder etc.)
|
// Crypto-Key für verschlüsselte Felder (Telefon, Kinder etc.)
|
||||||
// Bitte in Staging per Hosting-ENV setzen; dieses putenv dient nur als Fallback/Beispiel.
|
// Bitte in Staging per Hosting-ENV setzen; dieses putenv dient nur als Fallback/Beispiel.
|
||||||
|
|||||||
0
debug/.gitkeep
Normal file
0
debug/.gitkeep
Normal file
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
$app = app();
|
$app = app();
|
||||||
$isLoggedIn = isset($_SESSION['user_id']);
|
$isLoggedIn = isset($_SESSION['user_id']);
|
||||||
|
$isDebug = defined('APP_DEBUG') && APP_DEBUG === true;
|
||||||
?>
|
?>
|
||||||
<header class="site-header">
|
<header class="site-header">
|
||||||
<div class="container nav-row">
|
<div class="container nav-row">
|
||||||
@@ -21,6 +22,9 @@ $isLoggedIn = isset($_SESSION['user_id']);
|
|||||||
<?php if ($isLoggedIn): ?>
|
<?php if ($isLoggedIn): ?>
|
||||||
<a class="btn ghost" href="/dashboard">Dashboard</a>
|
<a class="btn ghost" href="/dashboard">Dashboard</a>
|
||||||
<a class="btn ghost" href="/logout">Logout</a>
|
<a class="btn ghost" href="/logout">Logout</a>
|
||||||
|
<?php if ($isDebug): ?>
|
||||||
|
<a class="btn ghost" href="/debug">Debug</a>
|
||||||
|
<?php endif; ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<a class="btn ghost" href="/login">Anmelden</a>
|
<a class="btn ghost" href="/login">Anmelden</a>
|
||||||
<a class="btn" href="/register">Kostenlos registrieren</a>
|
<a class="btn" href="/register">Kostenlos registrieren</a>
|
||||||
@@ -36,6 +40,9 @@ $isLoggedIn = isset($_SESSION['user_id']);
|
|||||||
<?php if ($isLoggedIn): ?>
|
<?php if ($isLoggedIn): ?>
|
||||||
<a class="btn ghost" href="/dashboard">Dashboard</a>
|
<a class="btn ghost" href="/dashboard">Dashboard</a>
|
||||||
<a class="btn block" href="/logout">Logout</a>
|
<a class="btn block" href="/logout">Logout</a>
|
||||||
|
<?php if ($isDebug): ?>
|
||||||
|
<a class="btn ghost block" href="/debug">Debug</a>
|
||||||
|
<?php endif; ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<a class="btn ghost" href="/login">Anmelden</a>
|
<a class="btn ghost" href="/login">Anmelden</a>
|
||||||
<a class="btn block" href="/register">Kostenlos registrieren</a>
|
<a class="btn block" href="/register">Kostenlos registrieren</a>
|
||||||
|
|||||||
48
public/page/debug.php
Normal file
48
public/page/debug.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
if (!defined('APP_DEBUG') || APP_DEBUG !== true) {
|
||||||
|
http_response_code(404);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$base = dirname(__DIR__, 1) . '/debug';
|
||||||
|
$files = [];
|
||||||
|
if (is_dir($base)) {
|
||||||
|
foreach (scandir($base) as $f) {
|
||||||
|
if ($f === '.' || $f === '..') continue;
|
||||||
|
$path = $base . '/' . $f;
|
||||||
|
if (is_file($path)) {
|
||||||
|
$files[] = $f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$selected = isset($_GET['file']) ? basename((string)$_GET['file']) : '';
|
||||||
|
$content = '';
|
||||||
|
if ($selected && in_array($selected, $files, true)) {
|
||||||
|
$content = @file_get_contents($base . '/' . $selected) ?: '';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<main class="container" style="padding: 32px 0;">
|
||||||
|
<div class="card" style="padding: 16px;">
|
||||||
|
<h1>Debug-Logs</h1>
|
||||||
|
<?php if (!$files): ?>
|
||||||
|
<p class="muted">Keine Logs in /debug/ gefunden.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<form method="get" style="margin-bottom: 16px;">
|
||||||
|
<label for="logSelect" class="label">Log-Datei auswählen</label>
|
||||||
|
<select id="logSelect" name="file" class="select" onchange="this.form.submit()">
|
||||||
|
<option value="">-- auswählen --</option>
|
||||||
|
<?php foreach ($files as $f): ?>
|
||||||
|
<option value="<?= htmlspecialchars($f, ENT_QUOTES) ?>" <?= $f === $selected ? 'selected' : '' ?>><?= htmlspecialchars($f, ENT_QUOTES) ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
|
<?php if ($selected): ?>
|
||||||
|
<h3><?= htmlspecialchars($selected, ENT_QUOTES) ?></h3>
|
||||||
|
<pre style="white-space:pre-wrap; background:#f8fafc; padding:12px; border:1px solid #e5e7eb; border-radius:8px; max-height: 60vh; overflow:auto;"><?= htmlspecialchars($content, ENT_QUOTES) ?></pre>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
@@ -5,13 +5,36 @@ namespace App;
|
|||||||
|
|
||||||
final class Mailer
|
final class Mailer
|
||||||
{
|
{
|
||||||
public function __construct(private App $app) {}
|
private string $logFile;
|
||||||
|
|
||||||
|
public function __construct(private App $app)
|
||||||
|
{
|
||||||
|
$base = dirname(__DIR__, 2);
|
||||||
|
$this->logFile = $base . '/debug/mailer_debug.log';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function log(string $msg, array $ctx = []): void
|
||||||
|
{
|
||||||
|
if (!defined('APP_DEBUG') || APP_DEBUG !== true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$line = '[' . date('Y-m-d H:i:s') . '] ' . $msg;
|
||||||
|
if ($ctx) {
|
||||||
|
$line .= ' ' . json_encode($ctx, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
|
$line .= "\n";
|
||||||
|
$dir = dirname($this->logFile);
|
||||||
|
if (!is_dir($dir)) {
|
||||||
|
@mkdir($dir, 0775, true);
|
||||||
|
}
|
||||||
|
@file_put_contents($this->logFile, $line, FILE_APPEND);
|
||||||
|
}
|
||||||
|
|
||||||
private function templates(): array
|
private function templates(): array
|
||||||
{
|
{
|
||||||
$env = $this->app->config()->env;
|
$env = $this->app->config()->env;
|
||||||
$root = __DIR__ . '/../../config/emailtemplates.php';
|
$root = __DIR__ . '/../../config/emailtemplates.php';
|
||||||
$envPath = __DIR__ . "/../../config/emailtemplates.php";
|
$envPath = __DIR__ . "/../../config/{$env}/emailtemplates.php";
|
||||||
$file = is_file($root) ? $root : $envPath;
|
$file = is_file($root) ? $root : $envPath;
|
||||||
$emailtemplates = [];
|
$emailtemplates = [];
|
||||||
if (is_file($file)) {
|
if (is_file($file)) {
|
||||||
@@ -35,6 +58,7 @@ final class Mailer
|
|||||||
'placeholders' => $vars,
|
'placeholders' => $vars,
|
||||||
];
|
];
|
||||||
$payload['token'] = $apiToken;
|
$payload['token'] = $apiToken;
|
||||||
|
$this->log('template_api_request', ['template' => $id, 'placeholders' => array_keys($vars)]);
|
||||||
$ctx = stream_context_create([
|
$ctx = stream_context_create([
|
||||||
'http' => [
|
'http' => [
|
||||||
'method' => 'POST',
|
'method' => 'POST',
|
||||||
@@ -47,11 +71,15 @@ final class Mailer
|
|||||||
if ($resp !== false) {
|
if ($resp !== false) {
|
||||||
$decoded = json_decode($resp, true);
|
$decoded = json_decode($resp, true);
|
||||||
if (is_array($decoded) && !empty($decoded['ok']) && !empty($decoded['html'])) {
|
if (is_array($decoded) && !empty($decoded['ok']) && !empty($decoded['html'])) {
|
||||||
|
$this->log('template_api_success', ['template' => $id, 'subject' => $decoded['subject'] ?? null, 'html_len' => strlen((string)$decoded['html'])]);
|
||||||
return [
|
return [
|
||||||
'subject' => $decoded['subject'] ?? 'Papakind',
|
'subject' => $decoded['subject'] ?? 'Papa-Kind-Treff',
|
||||||
'html' => $decoded['html'],
|
'html' => $decoded['html'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
$this->log('template_api_response_invalid', ['template' => $id, 'response' => $decoded]);
|
||||||
|
} else {
|
||||||
|
$this->log('template_api_unreachable', ['template' => $id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +89,7 @@ final class Mailer
|
|||||||
foreach ($vars as $k => $v) {
|
foreach ($vars as $k => $v) {
|
||||||
$body = str_replace(['{' . $k . '}', '{{' . $k . '}}'], (string)$v, $body);
|
$body = str_replace(['{' . $k . '}', '{{' . $k . '}}'], (string)$v, $body);
|
||||||
}
|
}
|
||||||
|
$this->log('template_fallback_used', ['template' => $id]);
|
||||||
return [
|
return [
|
||||||
'subject' => $subject,
|
'subject' => $subject,
|
||||||
'html' => nl2br(htmlspecialchars($body, ENT_QUOTES)),
|
'html' => nl2br(htmlspecialchars($body, ENT_QUOTES)),
|
||||||
@@ -81,6 +110,7 @@ final class Mailer
|
|||||||
$fromEmail = getenv('MAIL_FROM') ?: 'no-reply@' . $this->app->config()->primaryDomain;
|
$fromEmail = getenv('MAIL_FROM') ?: 'no-reply@' . $this->app->config()->primaryDomain;
|
||||||
$fromName = getenv('MAIL_FROM_NAME') ?: 'Papa-Kind-Treff';
|
$fromName = getenv('MAIL_FROM_NAME') ?: 'Papa-Kind-Treff';
|
||||||
|
|
||||||
|
$this->log('mail_send_start', ['template' => $templateKey, 'to' => $to, 'transport' => $transport, 'subject' => $subject]);
|
||||||
if ($transport === 'smtp') {
|
if ($transport === 'smtp') {
|
||||||
$this->sendSmtp($to, $subject, $html, $fromEmail, $fromName);
|
$this->sendSmtp($to, $subject, $html, $fromEmail, $fromName);
|
||||||
} else {
|
} else {
|
||||||
@@ -95,7 +125,9 @@ final class Mailer
|
|||||||
$headers[] = 'From: ' . sprintf('"%s" <%s>', addslashes($fromName), $from);
|
$headers[] = 'From: ' . sprintf('"%s" <%s>', addslashes($fromName), $from);
|
||||||
}
|
}
|
||||||
$headers[] = 'Content-Type: text/html; charset=utf-8';
|
$headers[] = 'Content-Type: text/html; charset=utf-8';
|
||||||
if (!@mail($to, $subject, $html, implode("\r\n", $headers))) {
|
$ok = @mail($to, $subject, $html, implode("\r\n", $headers));
|
||||||
|
$this->log('mail_mail_transport', ['to' => $to, 'ok' => $ok]);
|
||||||
|
if (!$ok) {
|
||||||
throw new \RuntimeException('mail() transport failed');
|
throw new \RuntimeException('mail() transport failed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,6 +148,7 @@ final class Mailer
|
|||||||
$proto = ($secure === 'ssl') ? 'ssl://' : '';
|
$proto = ($secure === 'ssl') ? 'ssl://' : '';
|
||||||
$fp = @stream_socket_client($proto . $host . ':' . $port, $errno, $errstr, 15, STREAM_CLIENT_CONNECT);
|
$fp = @stream_socket_client($proto . $host . ':' . $port, $errno, $errstr, 15, STREAM_CLIENT_CONNECT);
|
||||||
if (!$fp) {
|
if (!$fp) {
|
||||||
|
$this->log('mail_smtp_connect_failed', ['host' => $host, 'port' => $port, 'error' => $errstr]);
|
||||||
$this->sendMailFn($to, $subject, $html, $from, $fromName);
|
$this->sendMailFn($to, $subject, $html, $from, $fromName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -170,5 +203,6 @@ final class Mailer
|
|||||||
$read();
|
$read();
|
||||||
$write('QUIT');
|
$write('QUIT');
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
|
$this->log('mail_smtp_sent', ['to' => $to, 'host' => $host, 'port' => $port, 'secure' => $secure]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user