debug
This commit is contained in:
@@ -291,6 +291,16 @@ $mm->registerFunction($moduleName, 'bavest_request', static function (
|
|||||||
$method = in_array($method, ['GET', 'POST'], true) ? $method : 'POST';
|
$method = in_array($method, ['GET', 'POST'], true) ? $method : 'POST';
|
||||||
|
|
||||||
if ($apiKey === '') {
|
if ($apiKey === '') {
|
||||||
|
module_debug_push('boersenchecker', [
|
||||||
|
'label' => 'Bavest Request',
|
||||||
|
'type' => 'api:error',
|
||||||
|
'request' => [
|
||||||
|
'method' => $method,
|
||||||
|
'path' => $path,
|
||||||
|
'payload' => $payload,
|
||||||
|
],
|
||||||
|
'message' => 'Bavest-API-Key fehlt. Bitte im Modul-Setup hinterlegen.',
|
||||||
|
]);
|
||||||
return [
|
return [
|
||||||
'ok' => false,
|
'ok' => false,
|
||||||
'message' => 'Bavest-API-Key fehlt. Bitte im Modul-Setup hinterlegen.',
|
'message' => 'Bavest-API-Key fehlt. Bitte im Modul-Setup hinterlegen.',
|
||||||
@@ -366,6 +376,21 @@ $mm->registerFunction($moduleName, 'bavest_request', static function (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!is_string($responseBody) || $responseBody === '') {
|
if (!is_string($responseBody) || $responseBody === '') {
|
||||||
|
module_debug_push('boersenchecker', [
|
||||||
|
'label' => 'Bavest Request',
|
||||||
|
'type' => 'api:error',
|
||||||
|
'request' => [
|
||||||
|
'method' => $method,
|
||||||
|
'url' => $url,
|
||||||
|
'payload' => $payload,
|
||||||
|
],
|
||||||
|
'response' => [
|
||||||
|
'http_code' => $httpCode,
|
||||||
|
'curl_error' => $curlError,
|
||||||
|
'body' => null,
|
||||||
|
],
|
||||||
|
'message' => 'Bavest Anfrage fehlgeschlagen.',
|
||||||
|
]);
|
||||||
return [
|
return [
|
||||||
'ok' => false,
|
'ok' => false,
|
||||||
'message' => 'Bavest Anfrage fehlgeschlagen.'
|
'message' => 'Bavest Anfrage fehlgeschlagen.'
|
||||||
@@ -376,6 +401,20 @@ $mm->registerFunction($moduleName, 'bavest_request', static function (
|
|||||||
|
|
||||||
$decoded = json_decode($responseBody, true);
|
$decoded = json_decode($responseBody, true);
|
||||||
if (!is_array($decoded)) {
|
if (!is_array($decoded)) {
|
||||||
|
module_debug_push('boersenchecker', [
|
||||||
|
'label' => 'Bavest Request',
|
||||||
|
'type' => 'api:error',
|
||||||
|
'request' => [
|
||||||
|
'method' => $method,
|
||||||
|
'url' => $url,
|
||||||
|
'payload' => $payload,
|
||||||
|
],
|
||||||
|
'response' => [
|
||||||
|
'http_code' => $httpCode,
|
||||||
|
'body_preview' => substr($responseBody, 0, 4000),
|
||||||
|
],
|
||||||
|
'message' => 'Bavest Antwort ist kein gueltiges JSON.',
|
||||||
|
]);
|
||||||
return [
|
return [
|
||||||
'ok' => false,
|
'ok' => false,
|
||||||
'message' => 'Bavest Antwort ist kein gueltiges JSON.',
|
'message' => 'Bavest Antwort ist kein gueltiges JSON.',
|
||||||
@@ -385,6 +424,20 @@ $mm->registerFunction($moduleName, 'bavest_request', static function (
|
|||||||
|
|
||||||
foreach (['error', 'message', 'detail'] as $errorKey) {
|
foreach (['error', 'message', 'detail'] as $errorKey) {
|
||||||
if (isset($decoded[$errorKey]) && is_string($decoded[$errorKey]) && trim($decoded[$errorKey]) !== '') {
|
if (isset($decoded[$errorKey]) && is_string($decoded[$errorKey]) && trim($decoded[$errorKey]) !== '') {
|
||||||
|
module_debug_push('boersenchecker', [
|
||||||
|
'label' => 'Bavest Request',
|
||||||
|
'type' => 'api:error',
|
||||||
|
'request' => [
|
||||||
|
'method' => $method,
|
||||||
|
'url' => $url,
|
||||||
|
'payload' => $payload,
|
||||||
|
],
|
||||||
|
'response' => [
|
||||||
|
'http_code' => $httpCode,
|
||||||
|
'body' => $decoded,
|
||||||
|
],
|
||||||
|
'message' => trim((string) $decoded[$errorKey]),
|
||||||
|
]);
|
||||||
return [
|
return [
|
||||||
'ok' => false,
|
'ok' => false,
|
||||||
'message' => trim((string) $decoded[$errorKey]),
|
'message' => trim((string) $decoded[$errorKey]),
|
||||||
@@ -393,6 +446,20 @@ $mm->registerFunction($moduleName, 'bavest_request', static function (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module_debug_push('boersenchecker', [
|
||||||
|
'label' => 'Bavest Request',
|
||||||
|
'type' => 'api:response',
|
||||||
|
'request' => [
|
||||||
|
'method' => $method,
|
||||||
|
'url' => $url,
|
||||||
|
'payload' => $payload,
|
||||||
|
],
|
||||||
|
'response' => [
|
||||||
|
'http_code' => $httpCode,
|
||||||
|
'body' => $decoded,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'ok' => true,
|
'ok' => true,
|
||||||
'data' => $decoded,
|
'data' => $decoded,
|
||||||
@@ -769,3 +836,77 @@ $mm->registerFunction($moduleName, 'bavest_fetch_chart_series', static function
|
|||||||
'source' => 'bavest:timeseries/history',
|
'source' => 'bavest:timeseries/history',
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$mm->registerFunction($moduleName, 'store_market_quote', static function (
|
||||||
|
int $instrumentId,
|
||||||
|
float $price,
|
||||||
|
string $currency,
|
||||||
|
string $quotedAt,
|
||||||
|
string $source
|
||||||
|
): array {
|
||||||
|
$pdo = module_fn('boersenchecker', 'pdo');
|
||||||
|
$quoteTable = module_fn('boersenchecker', 'table', 'quotes');
|
||||||
|
|
||||||
|
$quotedAt = trim($quotedAt);
|
||||||
|
$currency = strtoupper(trim($currency)) ?: 'EUR';
|
||||||
|
$source = trim($source) !== '' ? trim($source) : 'bavest:quote';
|
||||||
|
|
||||||
|
$checkStmt = $pdo->prepare(
|
||||||
|
'SELECT id
|
||||||
|
FROM ' . $quoteTable . '
|
||||||
|
WHERE instrument_id = :instrument_id
|
||||||
|
AND price = :price
|
||||||
|
AND currency = :currency
|
||||||
|
AND quoted_at = :quoted_at
|
||||||
|
AND source = :source
|
||||||
|
LIMIT 1'
|
||||||
|
);
|
||||||
|
$checkStmt->execute([
|
||||||
|
'instrument_id' => $instrumentId,
|
||||||
|
'price' => $price,
|
||||||
|
'currency' => $currency,
|
||||||
|
'quoted_at' => $quotedAt,
|
||||||
|
'source' => $source,
|
||||||
|
]);
|
||||||
|
$existingId = (int) $checkStmt->fetchColumn();
|
||||||
|
if ($existingId > 0) {
|
||||||
|
module_debug_push('boersenchecker', [
|
||||||
|
'label' => 'Quote Store',
|
||||||
|
'type' => 'quote:reuse',
|
||||||
|
'instrument_id' => $instrumentId,
|
||||||
|
'price' => $price,
|
||||||
|
'currency' => $currency,
|
||||||
|
'quoted_at' => $quotedAt,
|
||||||
|
'source' => $source,
|
||||||
|
'message' => 'Identischer Snapshot bereits vorhanden.',
|
||||||
|
]);
|
||||||
|
return ['ok' => true, 'inserted' => false, 'id' => $existingId];
|
||||||
|
}
|
||||||
|
|
||||||
|
$insertStmt = $pdo->prepare(
|
||||||
|
'INSERT INTO ' . $quoteTable . ' (instrument_id, price, currency, quoted_at, source)
|
||||||
|
VALUES (:instrument_id, :price, :currency, :quoted_at, :source)'
|
||||||
|
);
|
||||||
|
$insertStmt->execute([
|
||||||
|
'instrument_id' => $instrumentId,
|
||||||
|
'price' => $price,
|
||||||
|
'currency' => $currency,
|
||||||
|
'quoted_at' => $quotedAt,
|
||||||
|
'source' => $source,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$insertedId = (int) $pdo->lastInsertId();
|
||||||
|
module_debug_push('boersenchecker', [
|
||||||
|
'label' => 'Quote Store',
|
||||||
|
'type' => 'quote:insert',
|
||||||
|
'instrument_id' => $instrumentId,
|
||||||
|
'price' => $price,
|
||||||
|
'currency' => $currency,
|
||||||
|
'quoted_at' => $quotedAt,
|
||||||
|
'source' => $source,
|
||||||
|
'inserted_id' => $insertedId,
|
||||||
|
'message' => 'Neuer Snapshot gespeichert.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ['ok' => true, 'inserted' => true, 'id' => $insertedId];
|
||||||
|
});
|
||||||
|
|||||||
@@ -427,14 +427,19 @@ final class DashboardPage
|
|||||||
throw new RuntimeException((string) ($apiResult['message'] ?? 'API-Abruf fehlgeschlagen.'));
|
throw new RuntimeException((string) ($apiResult['message'] ?? 'API-Abruf fehlgeschlagen.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->storeQuote(
|
$storeResult = \module_fn(
|
||||||
|
'boersenchecker',
|
||||||
|
'store_market_quote',
|
||||||
$instrumentId,
|
$instrumentId,
|
||||||
(float) $apiResult['price'],
|
(float) $apiResult['price'],
|
||||||
$quoteCurrency,
|
$quoteCurrency,
|
||||||
(string) $apiResult['fetched_at'],
|
(string) $apiResult['fetched_at'],
|
||||||
(string) $apiResult['source']
|
(string) $apiResult['source']
|
||||||
);
|
);
|
||||||
return 'Bavest-Kurs fuer ' . (string) $row['instrument_name'] . ' gespeichert.';
|
if (!empty($storeResult['inserted'])) {
|
||||||
|
return 'Bavest-Kurs fuer ' . (string) $row['instrument_name'] . ' gespeichert.';
|
||||||
|
}
|
||||||
|
return 'Vorhandener Bavest-Snapshot fuer ' . (string) $row['instrument_name'] . ' wiederverwendet.';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function refreshMarketDataAll(): string
|
private function refreshMarketDataAll(): string
|
||||||
@@ -499,14 +504,20 @@ final class DashboardPage
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->storeQuote(
|
$storeResult = \module_fn(
|
||||||
|
'boersenchecker',
|
||||||
|
'store_market_quote',
|
||||||
$instrumentId,
|
$instrumentId,
|
||||||
(float) $apiResult['price'],
|
(float) $apiResult['price'],
|
||||||
$quoteCurrency,
|
$quoteCurrency,
|
||||||
(string) $apiResult['fetched_at'],
|
(string) $apiResult['fetched_at'],
|
||||||
(string) $apiResult['source']
|
(string) $apiResult['source']
|
||||||
);
|
);
|
||||||
$fetched++;
|
if (!empty($storeResult['inserted'])) {
|
||||||
|
$fetched++;
|
||||||
|
} else {
|
||||||
|
$reused++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,25 +157,26 @@ final class HomePage
|
|||||||
if ($bulkCandidates !== []) {
|
if ($bulkCandidates !== []) {
|
||||||
$bulkResult = \module_fn('boersenchecker', 'bavest_fetch_bulk_quotes', $bulkCandidates);
|
$bulkResult = \module_fn('boersenchecker', 'bavest_fetch_bulk_quotes', $bulkCandidates);
|
||||||
$quotes = is_array($bulkResult['quotes'] ?? null) ? $bulkResult['quotes'] : [];
|
$quotes = is_array($bulkResult['quotes'] ?? null) ? $bulkResult['quotes'] : [];
|
||||||
$stmtInsert = $this->pdo->prepare(
|
|
||||||
'INSERT INTO ' . $this->quoteTable . ' (instrument_id, price, currency, quoted_at, source)
|
|
||||||
VALUES (:instrument_id, :price, :currency, :quoted_at, :source)'
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ($bulkCandidates as $row) {
|
foreach ($bulkCandidates as $row) {
|
||||||
$instrumentId = (int) ($row['id'] ?? 0);
|
$instrumentId = (int) ($row['id'] ?? 0);
|
||||||
$quote = $quotes[$instrumentId] ?? null;
|
$quote = $quotes[$instrumentId] ?? null;
|
||||||
if (!is_array($quote) || !is_numeric($quote['price'] ?? null)) {
|
if (!is_array($quote) || !is_numeric($quote['price'] ?? null)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$stmtInsert->execute([
|
$storeResult = \module_fn(
|
||||||
'instrument_id' => $instrumentId,
|
'boersenchecker',
|
||||||
'price' => (float) $quote['price'],
|
'store_market_quote',
|
||||||
'currency' => strtoupper(trim((string) ($quote['currency'] ?? $row['quote_currency'] ?? $this->defaultReportCurrency))) ?: $this->defaultReportCurrency,
|
$instrumentId,
|
||||||
'quoted_at' => (string) ($quote['fetched_at'] ?? date('Y-m-d H:i:s')),
|
(float) $quote['price'],
|
||||||
'source' => (string) ($quote['source'] ?? 'bavest:quote'),
|
strtoupper(trim((string) ($quote['currency'] ?? $row['quote_currency'] ?? $this->defaultReportCurrency))) ?: $this->defaultReportCurrency,
|
||||||
]);
|
(string) ($quote['fetched_at'] ?? gmdate('Y-m-d H:i:s')),
|
||||||
$updated++;
|
(string) ($quote['source'] ?? 'bavest:quote')
|
||||||
|
);
|
||||||
|
if (!empty($storeResult['inserted'])) {
|
||||||
|
$updated++;
|
||||||
|
} else {
|
||||||
|
$reused++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,19 +224,19 @@ final class InstrumentPage
|
|||||||
throw new RuntimeException((string) ($apiResult['message'] ?? 'API-Abruf fehlgeschlagen.'));
|
throw new RuntimeException((string) ($apiResult['message'] ?? 'API-Abruf fehlgeschlagen.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmtInsert = $this->pdo->prepare(
|
$storeResult = \module_fn(
|
||||||
'INSERT INTO ' . $this->quoteTable . ' (instrument_id, price, currency, quoted_at, source)
|
'boersenchecker',
|
||||||
VALUES (:instrument_id, :price, :currency, :quoted_at, :source)'
|
'store_market_quote',
|
||||||
|
$instrumentId,
|
||||||
|
(float) $apiResult['price'],
|
||||||
|
strtoupper(trim((string) ($instrument['quote_currency'] ?? $this->defaultReportCurrency))) ?: $this->defaultReportCurrency,
|
||||||
|
(string) $apiResult['fetched_at'],
|
||||||
|
(string) $apiResult['source']
|
||||||
);
|
);
|
||||||
$stmtInsert->execute([
|
|
||||||
'instrument_id' => $instrumentId,
|
|
||||||
'price' => (float) $apiResult['price'],
|
|
||||||
'currency' => strtoupper(trim((string) ($instrument['quote_currency'] ?? $this->defaultReportCurrency))) ?: $this->defaultReportCurrency,
|
|
||||||
'quoted_at' => (string) $apiResult['fetched_at'],
|
|
||||||
'source' => (string) $apiResult['source'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
return 'Bavest-Kurs gespeichert.';
|
return !empty($storeResult['inserted'])
|
||||||
|
? 'Bavest-Kurs gespeichert.'
|
||||||
|
: 'Vorhandener Bavest-Snapshot wiederverwendet.';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function searchSymbol(): string
|
private function searchSymbol(): string
|
||||||
|
|||||||
@@ -1098,6 +1098,90 @@ a {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.module-debug {
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 22px;
|
||||||
|
background: var(--surface);
|
||||||
|
box-shadow: 0 12px 30px rgba(1, 22, 32, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-details {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-summary {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 16px 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
list-style: none;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-summary::-webkit-details-marker {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-meta,
|
||||||
|
.module-debug-entry-time {
|
||||||
|
color: var(--muted);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.92rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-body {
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 0 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-empty {
|
||||||
|
padding: 14px 16px;
|
||||||
|
border: 1px dashed var(--line);
|
||||||
|
border-radius: 16px;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-entry {
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 16px;
|
||||||
|
background: color-mix(in srgb, var(--surface) 92%, var(--brand-accent-2) 8%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-entry summary {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-entry summary::-webkit-details-marker {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-debug-pre {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 14px 14px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||||
|
font-size: 0.86rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
.module-box-head p {
|
.module-box-head p {
|
||||||
margin: 6px 0 0;
|
margin: 6px 0 0;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
|
|||||||
@@ -276,6 +276,46 @@ function module_design(string $module): array
|
|||||||
return $cache[$module];
|
return $cache[$module];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function module_debug_entries(string $module): array
|
||||||
|
{
|
||||||
|
if (preg_match('/[^a-zA-Z0-9_\-]/', $module)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
app()->session()->start();
|
||||||
|
$entries = $_SESSION['module_debug'][$module] ?? [];
|
||||||
|
return is_array($entries) ? array_values(array_filter($entries, 'is_array')) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function module_debug_push(string $module, array $entry): void
|
||||||
|
{
|
||||||
|
if (preg_match('/[^a-zA-Z0-9_\-]/', $module)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
app()->session()->start();
|
||||||
|
if (!isset($_SESSION['module_debug']) || !is_array($_SESSION['module_debug'])) {
|
||||||
|
$_SESSION['module_debug'] = [];
|
||||||
|
}
|
||||||
|
if (!isset($_SESSION['module_debug'][$module]) || !is_array($_SESSION['module_debug'][$module])) {
|
||||||
|
$_SESSION['module_debug'][$module] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry['at'] = $entry['at'] ?? date('Y-m-d H:i:s');
|
||||||
|
array_unshift($_SESSION['module_debug'][$module], $entry);
|
||||||
|
$_SESSION['module_debug'][$module] = array_slice($_SESSION['module_debug'][$module], 0, 25);
|
||||||
|
}
|
||||||
|
|
||||||
|
function module_debug_clear(string $module): void
|
||||||
|
{
|
||||||
|
if (preg_match('/[^a-zA-Z0-9_\-]/', $module)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
app()->session()->start();
|
||||||
|
unset($_SESSION['module_debug'][$module]);
|
||||||
|
}
|
||||||
|
|
||||||
function module_shell_header(string $module, array $options = []): string
|
function module_shell_header(string $module, array $options = []): string
|
||||||
{
|
{
|
||||||
$design = module_design($module);
|
$design = module_design($module);
|
||||||
@@ -374,7 +414,53 @@ function module_shell_header(string $module, array $options = []): string
|
|||||||
|
|
||||||
function module_shell_footer(): string
|
function module_shell_footer(): string
|
||||||
{
|
{
|
||||||
return '</div></div></div>';
|
$html = '';
|
||||||
|
$module = current_module_name();
|
||||||
|
if (is_string($module) && $module !== '') {
|
||||||
|
if ((string) ($_GET['module_debug_clear'] ?? '') === '1') {
|
||||||
|
module_debug_clear($module);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entries = module_debug_entries($module);
|
||||||
|
$currentPath = app()->request()->path();
|
||||||
|
$clearHref = $currentPath . '?module_debug_clear=1';
|
||||||
|
|
||||||
|
$html .= '<section class="module-debug">';
|
||||||
|
$html .= '<details class="module-debug-details"' . ($entries !== [] ? ' open' : '') . '>';
|
||||||
|
$html .= '<summary class="module-debug-summary">';
|
||||||
|
$html .= '<span>Debug</span>';
|
||||||
|
$html .= '<span class="module-debug-meta">' . e((string) count($entries)) . ' Eintraege</span>';
|
||||||
|
$html .= '</summary>';
|
||||||
|
$html .= '<div class="module-debug-body">';
|
||||||
|
$html .= '<div class="module-debug-toolbar">';
|
||||||
|
$html .= '<div class="muted">Standard-Debugbereich des Moduls. Zeigt die letzten Request-/Response-Daten der aktuellen Sitzung.</div>';
|
||||||
|
$html .= '<a class="module-button module-button--ghost module-button--small" href="' . e($clearHref) . '">Debug leeren</a>';
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
|
if ($entries === []) {
|
||||||
|
$html .= '<div class="module-debug-empty">Noch keine Debug-Daten vorhanden.</div>';
|
||||||
|
} else {
|
||||||
|
foreach ($entries as $index => $entry) {
|
||||||
|
$label = trim((string) ($entry['label'] ?? ('Eintrag ' . ($index + 1))));
|
||||||
|
$at = trim((string) ($entry['at'] ?? ''));
|
||||||
|
$payload = json_encode($entry, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
if (!is_string($payload)) {
|
||||||
|
$payload = '{}';
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= '<details class="module-debug-entry"' . ($index === 0 ? ' open' : '') . '>';
|
||||||
|
$html .= '<summary><strong>' . e($label) . '</strong>' . ($at !== '' ? '<span class="module-debug-entry-time">' . e($at) . '</span>' : '') . '</summary>';
|
||||||
|
$html .= '<pre class="module-debug-pre">' . e($payload) . '</pre>';
|
||||||
|
$html .= '</details>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= '</div>';
|
||||||
|
$html .= '</details>';
|
||||||
|
$html .= '</section>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html . '</div></div></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user