big update
This commit is contained in:
320
src/functions.php
Normal file
320
src/functions.php
Normal file
@@ -0,0 +1,320 @@
|
||||
<?php
|
||||
$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';
|
||||
}
|
||||
|
||||
function app_primary_url(): string
|
||||
{
|
||||
$url = defined('APP_URL_PRIMARY') ? APP_URL_PRIMARY : 'https://usbcheck.it';
|
||||
return rtrim($url, '/');
|
||||
}
|
||||
|
||||
function app_fakecheck_domain(): string
|
||||
{
|
||||
return defined('APP_DOMAIN_FAKECHECK') ? APP_DOMAIN_FAKECHECK : 'ismyusbfake.com';
|
||||
}
|
||||
|
||||
function app_fakecheck_url(): string
|
||||
{
|
||||
$url = defined('APP_URL_FAKECHECK') ? APP_URL_FAKECHECK : 'https://ismyusbfake.com';
|
||||
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
|
||||
*/
|
||||
function tpl_add_script(
|
||||
string $src,
|
||||
string $pos = 'footer',
|
||||
bool $defer = true,
|
||||
bool $async = false,
|
||||
string $type = '',
|
||||
?string $version = null
|
||||
): void {
|
||||
if ($version === null && defined('ASSET_VERSION')) {
|
||||
$version = ASSET_VERSION;
|
||||
}
|
||||
|
||||
$GLOBALS['page_header_scripts'] = $GLOBALS['page_header_scripts'] ?? [];
|
||||
$GLOBALS['page_footer_scripts'] = $GLOBALS['page_footer_scripts'] ?? [];
|
||||
|
||||
$data = [
|
||||
'src' => $src,
|
||||
'defer' => $defer,
|
||||
'async' => $async,
|
||||
'type' => $type,
|
||||
'version' => $version,
|
||||
];
|
||||
|
||||
if ($pos === 'header') {
|
||||
$GLOBALS['page_header_scripts'][] = $data;
|
||||
} else {
|
||||
$GLOBALS['page_footer_scripts'][] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 $priority = 'normal',
|
||||
?string $version = null
|
||||
): void {
|
||||
if ($version === null && defined('ASSET_VERSION')) {
|
||||
$version = ASSET_VERSION;
|
||||
}
|
||||
|
||||
$GLOBALS['page_styles'][] = [
|
||||
'href' => $href,
|
||||
'pos' => $pos,
|
||||
'priority' => $priority,
|
||||
'version' => $version,
|
||||
];
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
Template Loader
|
||||
------------------------------------------------- */
|
||||
|
||||
function tpl(string $file, string $type = 'structure', string $site = 'main'): void
|
||||
{
|
||||
$base = __DIR__ . '/../partials/';
|
||||
|
||||
if (preg_match('/[^a-zA-Z0-9_\-]/', $file)) {
|
||||
echo "<!-- tpl(): Ungültiger Template-Name -->";
|
||||
return;
|
||||
}
|
||||
if (preg_match('/[^a-zA-Z0-9_\-]/', $type)) {
|
||||
echo "<!-- tpl(): Ungültiger Type -->";
|
||||
return;
|
||||
}
|
||||
if (preg_match('/[^a-zA-Z0-9_\-]/', $site)) {
|
||||
echo "<!-- tpl(): Ungültiger Site -->";
|
||||
return;
|
||||
}
|
||||
|
||||
if ($type === 'landing') {
|
||||
$path = $base . "landing/$site/$file.php";
|
||||
} else {
|
||||
$path = $base . "structure/$file.php";
|
||||
}
|
||||
|
||||
extract($GLOBALS, EXTR_SKIP);
|
||||
|
||||
if (file_exists($path)) {
|
||||
include $path;
|
||||
} else {
|
||||
echo "<!-- tpl(): Datei nicht gefunden: $path -->";
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
Flash-Messages
|
||||
------------------------------------------------- */
|
||||
|
||||
function flash_set(string $type, string $message, ?string $context = null): void
|
||||
{
|
||||
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
@session_start();
|
||||
}
|
||||
|
||||
$_SESSION['flash'] = [
|
||||
'type' => $type,
|
||||
'message' => $message,
|
||||
'context' => $context,
|
||||
];
|
||||
}
|
||||
|
||||
function flash_get(): ?array
|
||||
{
|
||||
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
@session_start();
|
||||
}
|
||||
|
||||
if (empty($_SESSION['flash']) || !is_array($_SESSION['flash'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$flash = $_SESSION['flash'];
|
||||
unset($_SESSION['flash']);
|
||||
|
||||
$flash['type'] = $flash['type'] ?? 'info';
|
||||
$flash['message'] = $flash['message'] ?? '';
|
||||
$flash['context'] = $flash['context'] ?? null;
|
||||
|
||||
return $flash;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
i18n Helper
|
||||
------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* interner Helper für dot-notation keys
|
||||
*/
|
||||
function _i18n_traverse_array(array $data, string $key)
|
||||
{
|
||||
$segments = explode('.', $key);
|
||||
$node = $data;
|
||||
|
||||
foreach ($segments as $seg) {
|
||||
if (!is_array($node) || !array_key_exists($seg, $node)) {
|
||||
return null;
|
||||
}
|
||||
$node = $node[$seg];
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hauptfunktion i18n_get
|
||||
*/
|
||||
function i18n_get(string $path, $default = null, array $replacements = []): string
|
||||
{
|
||||
if (!isset($GLOBALS['i18n']) || !is_array($GLOBALS['i18n'])) {
|
||||
return $default !== null ? (string)$default : '';
|
||||
}
|
||||
|
||||
$current = $GLOBALS['i18n']['current'] ?? [];
|
||||
$fallback = $GLOBALS['i18n']['fallback'] ?? [];
|
||||
|
||||
$value = _i18n_traverse_array($current, $path);
|
||||
|
||||
if ($value === null && !empty($fallback)) {
|
||||
$value = _i18n_traverse_array($fallback, $path);
|
||||
}
|
||||
|
||||
if (!is_string($value)) {
|
||||
return $default !== null ? (string)$default : '';
|
||||
}
|
||||
|
||||
$text = $value;
|
||||
|
||||
// built-in placeholder
|
||||
$builtIn = [
|
||||
'{year}' => date('Y'),
|
||||
'{{primary_domain}}' => function_exists('app_primary_domain') ? app_primary_domain() : '',
|
||||
'{{primary_url}}' => function_exists('app_primary_url') ? app_primary_url() : '',
|
||||
];
|
||||
|
||||
foreach ($builtIn as $ph => $val) {
|
||||
$text = str_replace($ph, $val, $text);
|
||||
}
|
||||
|
||||
foreach ($replacements as $key => $val) {
|
||||
$val = (string)$val;
|
||||
$text = str_replace('{' . $key . '}', $val, $text);
|
||||
$text = str_replace('{{' . $key . '}}', $val, $text);
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kurzform für i18n_get
|
||||
*/
|
||||
function i18n_get_fmt(string $path, $default = '', array $vars = []): string
|
||||
{
|
||||
$def = $default ?? '';
|
||||
return i18n_get($path, $def, $vars);
|
||||
}
|
||||
Reference in New Issue
Block a user