From d63acce8f7d82d6715674363ca17cbc7616895ab Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Sat, 29 Nov 2025 01:57:38 +0100 Subject: [PATCH] up --- partials/structure/header.php | 49 ++++----- partials/structure/layout_start.php | 156 ++++++++++++++++------------ src/functions.php | 138 ++++++++++++++++++++---- 3 files changed, 226 insertions(+), 117 deletions(-) diff --git a/partials/structure/header.php b/partials/structure/header.php index 3d7c9a6..3443bda 100644 --- a/partials/structure/header.php +++ b/partials/structure/header.php @@ -1,10 +1,8 @@
-
- +
@@ -120,27 +117,23 @@ function build_lang_url(string $code, string $path, array $query): string
- - - - - - + + +
diff --git a/partials/structure/layout_start.php b/partials/structure/layout_start.php index 52e387d..cc995f0 100644 --- a/partials/structure/layout_start.php +++ b/partials/structure/layout_start.php @@ -3,11 +3,9 @@ // Erwartet (vor require): // - $pageKey (string) – Seiten-Key für i18n, z. B. 'landing', 'fakecheck', 'login', 'dashboard' -// - $lang (2-letter ISO, z. B. 'de', 'en', 'it', 'fr'), möglichst bereits aus fileload.php // - optional: $pageTitle (string) // - optional: $pageDescription (string) // - optional: $canonical (string) -// - optional: $userInitials (string|null) // ----------------------------------------------------------- // Fallbacks & i18n Title/Description @@ -21,45 +19,39 @@ if (!isset($pageKey) || !is_string($pageKey) || $pageKey === '') { $pageKey = 'landing'; } -// Sprache: erst lokale $lang prüfen, sonst global aus fileload.php, dann Fallback -if (!isset($lang) || !isset($availableLangs[$lang])) { - $lang = $GLOBALS['lang'] ?? (array_key_first($availableLangs) ?: 'en'); -} +// Sprache: aus Globals (fileload.php) bzw. Fallback +$lang = $GLOBALS['lang'] ?? (array_key_first($availableLangs) ?: 'en'); // Title aus i18n, falls nichts explizit gesetzt wurde if (!isset($pageTitle) || !is_string($pageTitle) || $pageTitle === '') { - // pages.{pageKey}.meta.title $pageTitle = i18n_get("pages.$pageKey.meta.title", app_primary_domain()); } // Description aus i18n, falls nichts explizit gesetzt wurde if (!isset($pageDescription) || !is_string($pageDescription) || $pageDescription === '') { - // pages.{pageKey}.meta.description $pageDescription = i18n_get("pages.$pageKey.meta.description", ''); } // ----------------------------------------------------------- -// Standard-Script für Header-Interaktionen +// Standard-Scripts für Header-Interaktionen (Footer-Scripts) // ----------------------------------------------------------- if (function_exists('tpl_add_script')) { - // header.js kommt wie gehabt in den Footer tpl_add_script('/assets/js/header.js', 'footer', true, false, '', null); + tpl_add_script('/assets/js/lang.js', 'footer', true, false, '', null); } -if (function_exists('tpl_add_script')) { - // header.js kommt wie gehabt in den Footer - tpl_add_script('/assets/js/lang.js', 'footer', true, false, '', null); -} -// ----------------------------------------------------------- -// Canonical-URL bestimmen -// ----------------------------------------------------------- -$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; -$host = $_SERVER['HTTP_HOST'] ?? app_primary_domain(); -$requestUri = $_SERVER['REQUEST_URI'] ?? '/'; -// Wenn $canonical gesetzt → verwenden, sonst aktuelle URL ohne Query-String -$effectiveCanonical = isset($canonical) && is_string($canonical) && $canonical !== '' - ? $canonical - : ($scheme . '://' . $host . strtok($requestUri, '?')); +// ----------------------------------------------------------- +// Globales CSS registrieren (z.B. main.css) +// → Priority 'late', damit es Tailwind überschreiben kann +// ----------------------------------------------------------- +if (function_exists('tpl_add_style')) { + tpl_add_style('/assets/css/main.css', 'header', 'late'); // <– Pfad ist korrekt, relativ zum Webroot +} + +// ----------------------------------------------------------- +// Canonical-URL bestimmen (zentral über Helper) +// ----------------------------------------------------------- +$effectiveCanonical = app_canonical_url($canonical ?? null); ?> @@ -79,47 +71,12 @@ $effectiveCanonical = isset($canonical) && is_string($canonical) && $canonical ! - - - ' . PHP_EOL; - } - - // Scripts im Header aus der zentralen Registry - foreach ($GLOBALS['page_header_scripts'] as $script) { - $src = $script['src']; - if (!empty($script['version'])) { - $src .= (str_contains($src, '?') ? '&' : '?') . 'v=' . urlencode($script['version']); - } - - $attr = ''; - if (!empty($script['async'])) { - $attr .= ' async'; - } elseif (!empty($script['defer'])) { - $attr .= ' defer'; - } - if (!empty($script['type'])) { - $attr .= ' type="' . htmlspecialchars($script['type']) . '"'; - } - - echo '' . PHP_EOL; - } - ?> + + + - - + 0, 'normal' => 1, 'late' => 2]; + + $pa = $order[$a['priority'] ?? 'normal'] ?? 1; + $pb = $order[$b['priority'] ?? 'normal'] ?? 1; + + return $pa <=> $pb; + }); + + foreach ($styles as $s) { + $href = $s['href'] ?? ''; + $version = $s['version'] ?? null; + + if ($href === '') { + continue; + } + + // Cache-Buster nur, wenn Version explizit gesetzt und nicht leer + if ($version !== null && $version !== '') { + $separator = (strpos($href, '?') === false) ? '?' : '&'; + $href .= $separator . 'v=' . rawurlencode($version); + } + + echo '' . "\n"; + } + } + + // ------------------------------------------------------- + // Scripts im Header aus der zentralen Registry + // ------------------------------------------------------- + $headerScripts = $GLOBALS['page_header_scripts'] ?? []; + + foreach ($headerScripts as $script) { + $src = $script['src'] ?? ''; + $version = $script['version'] ?? null; + + if ($src === '') { + continue; + } + + if ($version !== null && $version !== '') { + $src .= (str_contains($src, '?') ? '&' : '?') . 'v=' . urlencode($version); + } + + $attr = ''; + if (!empty($script['async'])) { + $attr .= ' async'; + } elseif (!empty($script['defer'])) { + $attr .= ' defer'; + } + if (!empty($script['type'])) { + $attr .= ' type="' . htmlspecialchars($script['type']) . '"'; + } + + echo '' . PHP_EOL; + } + ?> + diff --git a/src/functions.php b/src/functions.php index 90c16fc..99faf2c 100644 --- a/src/functions.php +++ b/src/functions.php @@ -3,6 +3,9 @@ $GLOBALS['page_header_scripts'] = $GLOBALS['page_header_scripts'] ?? []; $GLOBALS['page_footer_scripts'] = $GLOBALS['page_footer_scripts'] ?? []; $GLOBALS['page_styles'] = $GLOBALS['page_styles'] ?? []; +/** + * Primäre Domain / URL (Brand) + */ function app_primary_domain(): string { return defined('APP_DOMAIN_PRIMARY') ? APP_DOMAIN_PRIMARY : 'usbcheck.it'; @@ -25,6 +28,88 @@ function app_fakecheck_url(): string return rtrim($url, '/'); } +/* ------------------------------------------------- + Zentrale Request-/URL-Helper + ------------------------------------------------- */ + +/** + * Aktuelles Schema (http / https), inkl. Proxy-Header-Fallback. + */ +function app_request_scheme(): string +{ + // Proxy / Loadbalancer + if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) { + $proto = strtolower((string)$_SERVER['HTTP_X_FORWARDED_PROTO']); + if ($proto === 'https' || $proto === 'http') { + return $proto; + } + } + + // Direkt + if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') { + return 'https'; + } + + return 'http'; +} + +/** + * Aktueller Host (inkl. Port, falls im Host-Header). + */ +function app_request_host(): string +{ + return $_SERVER['HTTP_HOST'] ?? app_primary_domain(); +} + +/** + * Basis-URL der aktuellen Anfrage, z. B. https://staging.usbcheck.it + */ +function app_current_base_url(): string +{ + return app_request_scheme() . '://' . app_request_host(); +} + +/** + * Aktueller Pfad ohne Query, z. B. /login/ oder /fakecheck/demo + */ +function app_current_path(): string +{ + return strtok($_SERVER['REQUEST_URI'] ?? '/', '?'); +} + +/** + * Aktuelle URL, optional mit Query-String. + */ +function app_current_url(bool $withQuery = true): string +{ + $base = app_current_base_url(); + $uri = $_SERVER['REQUEST_URI'] ?? '/'; + + if ($withQuery) { + return $base . $uri; + } + + return $base . strtok($uri, '?'); +} + +/** + * Canonical-URL bestimmen. + * - Wenn $override gesetzt: exakt diesen Wert verwenden. + * - Sonst: aktuelle URL ohne Query. + */ +function app_canonical_url(?string $override = null): string +{ + if (is_string($override) && $override !== '') { + return $override; + } + + return app_current_url(false); +} + +/* ------------------------------------------------- + Assets: JS / CSS + ------------------------------------------------- */ + /** * Script registrieren */ @@ -59,32 +144,37 @@ function tpl_add_script( } /** - * CSS registrieren – MIT korrekt funktionierendem Cache-Buster + * CSS registrieren – MIT Cache-Buster und Priorität + * + * @param string $href Pfad zur CSS-Datei oder externe URL + * @param string $pos aktuell nur 'header' relevant (aber für Symmetrie drin) + * @param string $priority 'early' | 'normal' | 'late' + * @param string|null $version null = nutze ASSET_VERSION (falls definiert), + * '' = kein ?v=, + * 'xyz'= erzwinge diese Version */ -function tpl_add_style(string $href, string $pos = 'header', ?string $version = null): void -{ +function tpl_add_style( + string $href, + string $pos = 'header', + string $priority = 'normal', + ?string $version = null +): void { if ($version === null && defined('ASSET_VERSION')) { $version = ASSET_VERSION; } - // version = null oder '' → kein Cache-Buster - $finalHref = $href; - - if ($version !== null && $version !== '') { - $separator = (strpos($href, '?') === false) ? '?' : '&'; - $finalHref = $href . $separator . 'v=' . rawurlencode($version); - } - $GLOBALS['page_styles'][] = [ - 'href' => $finalHref, - 'pos' => $pos, - 'version' => $version, + 'href' => $href, + 'pos' => $pos, + 'priority' => $priority, + 'version' => $version, ]; } -/** - * Template Loader - */ +/* ------------------------------------------------- + Template Loader + ------------------------------------------------- */ + function tpl(string $file, string $type = 'structure', string $site = 'main'): void { $base = __DIR__ . '/../partials/'; @@ -117,9 +207,10 @@ function tpl(string $file, string $type = 'structure', string $site = 'main'): v } } -/** - * Flash setzen - */ +/* ------------------------------------------------- + Flash-Messages + ------------------------------------------------- */ + function flash_set(string $type, string $message, ?string $context = null): void { if (session_status() !== PHP_SESSION_ACTIVE) { @@ -133,9 +224,6 @@ function flash_set(string $type, string $message, ?string $context = null): void ]; } -/** - * Flash holen - */ function flash_get(): ?array { if (session_status() !== PHP_SESSION_ACTIVE) { @@ -156,6 +244,10 @@ function flash_get(): ?array return $flash; } +/* ------------------------------------------------- + i18n Helper + ------------------------------------------------- */ + /** * interner Helper für dot-notation keys */