Die Domain-Auflösung matchte den Host exakt gegen domain_name — www.presseecho.de fiel dadurch aufs Portal-Default-Theme zurück, dessen theme-portal.css im Web-Build nicht existiert. Alle Route::view-Seiten ohne Controller (Impressum, Datenschutz, AGB, FAQ, …) antworteten auf www-Hosts mit 500 (ViteException, Dauereintrag im Live-Log); die Controller-Seiten traf es nicht, weil WebPortalContext den Host tolerant matcht. resolve() normalisiert Hosts jetzt (lowercase, www. entfernt) auf beiden Seiten des Vergleichs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
194 lines
5.8 KiB
PHP
194 lines
5.8 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\View;
|
|
use Illuminate\Support\Facades\Vite;
|
|
|
|
class DomainAssetContext
|
|
{
|
|
/**
|
|
* Wendet die Domain-/Theme-Konfiguration einer öffentlichen Web-Ausgabe an
|
|
* (config + View::share + Vite) und liefert die aufgelöste Domain-Config.
|
|
* Single Source of Truth für die zuvor je Route-Closure wiederholte Logik.
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
public static function applyWebDomainConfig(string $domainKey): array
|
|
{
|
|
/** @var array<string, mixed> $domainConfig */
|
|
$domainConfig = config("domains.domains.{$domainKey}", []);
|
|
|
|
config([
|
|
'app.theme' => $domainConfig['theme'] ?? $domainKey,
|
|
'app.view_prefix' => $domainConfig['view_prefix'] ?? 'web',
|
|
'app.domain_name' => $domainConfig['domain_name'] ?? request()->getHost(),
|
|
'app.url' => $domainConfig['url'] ?? config('app.url'),
|
|
]);
|
|
|
|
View::share('theme', $domainConfig['theme'] ?? $domainKey);
|
|
View::share('viewPrefix', $domainConfig['view_prefix'] ?? 'web');
|
|
View::share('domainName', $domainConfig['domain_name'] ?? request()->getHost());
|
|
View::share('domainConfig', $domainConfig);
|
|
View::share('domainUrl', $domainConfig['url'] ?? config('app.url'));
|
|
View::share('assetUrl', self::staticAssetOrigin($domainConfig));
|
|
|
|
self::configureVite($domainConfig);
|
|
|
|
return $domainConfig;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $defaults
|
|
* @param array<string, array<string, mixed>> $configuredDomains
|
|
* @return array<string, mixed>
|
|
*/
|
|
public static function resolve(
|
|
string $host,
|
|
array $defaults,
|
|
array $configuredDomains,
|
|
?string $themeOverride = null,
|
|
?Request $request = null,
|
|
): array {
|
|
if ($themeOverride !== null && isset($configuredDomains[$themeOverride])) {
|
|
return array_merge($defaults, $configuredDomains[$themeOverride]);
|
|
}
|
|
|
|
// www-Varianten zählen als ihre Apex-Domain: Ohne Normalisierung
|
|
// fiele z. B. www.presseecho.de auf das Portal-Default-Theme zurück,
|
|
// dessen theme-portal.css im Web-Build nicht existiert → 500
|
|
// (ViteException) auf allen Route::view-Seiten (Impressum, AGB, …).
|
|
$host = self::normalizedHost($host);
|
|
|
|
$portalHost = self::normalizedHost((string) config('domains.domain_portal'));
|
|
|
|
if ($host === $portalHost) {
|
|
$request ??= request();
|
|
|
|
if (self::isBackendRequest($request)) {
|
|
return array_merge($defaults, $configuredDomains['portal'] ?? $defaults);
|
|
}
|
|
|
|
return array_merge($defaults, $configuredDomains['pressekonto'] ?? $defaults);
|
|
}
|
|
|
|
foreach ($configuredDomains as $config) {
|
|
if (! is_array($config)) {
|
|
continue;
|
|
}
|
|
|
|
$domainName = $config['domain_name'] ?? null;
|
|
|
|
if (is_string($domainName) && self::normalizedHost($domainName) === $host) {
|
|
return array_merge($defaults, $config);
|
|
}
|
|
}
|
|
|
|
return $defaults;
|
|
}
|
|
|
|
/**
|
|
* Kleingeschriebener Host ohne führendes "www.".
|
|
*/
|
|
private static function normalizedHost(string $host): string
|
|
{
|
|
$host = strtolower(trim($host));
|
|
|
|
return str_starts_with($host, 'www.') ? substr($host, 4) : $host;
|
|
}
|
|
|
|
public static function isBackendRequest(Request $request): bool
|
|
{
|
|
if ($request->routeIs(
|
|
'dashboard',
|
|
'login',
|
|
'register',
|
|
'password.*',
|
|
'verification.*',
|
|
'two-factor.*',
|
|
'magic-links.*',
|
|
'me.*',
|
|
'settings.*',
|
|
)) {
|
|
return true;
|
|
}
|
|
|
|
$backendPrefixes = [
|
|
'admin',
|
|
'customer',
|
|
'dashboard',
|
|
'login',
|
|
'register',
|
|
'forgot-password',
|
|
'reset-password',
|
|
'magic-login',
|
|
'user',
|
|
'settings',
|
|
'flux',
|
|
'livewire',
|
|
];
|
|
|
|
$path = trim($request->path(), '/');
|
|
|
|
foreach ($backendPrefixes as $prefix) {
|
|
if ($path === $prefix || str_starts_with($path, "{$prefix}/")) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static function usesWebAssets(string $assetsDir): bool
|
|
{
|
|
return $assetsDir === 'build/web';
|
|
}
|
|
|
|
public static function hotFilePath(string $assetsDir): string
|
|
{
|
|
return self::usesWebAssets($assetsDir)
|
|
? public_path('hot-web')
|
|
: public_path('hot-portal');
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $domainConfig
|
|
*/
|
|
public static function configureVite(array $domainConfig): void
|
|
{
|
|
$assetsDir = (string) ($domainConfig['assets_dir'] ?? 'build/portal');
|
|
|
|
Vite::useBuildDirectory($assetsDir);
|
|
Vite::useHotFile(self::hotFilePath($assetsDir));
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $domainConfig
|
|
*/
|
|
public static function staticAssetOrigin(array $domainConfig): string
|
|
{
|
|
return (string) ($domainConfig['url'] ?? config('app.url'));
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $domainConfig
|
|
*/
|
|
public static function viteDevServerUrl(array $domainConfig): string
|
|
{
|
|
if (isset($domainConfig['asset_url'])) {
|
|
return (string) $domainConfig['asset_url'];
|
|
}
|
|
|
|
$assetsDir = (string) ($domainConfig['assets_dir'] ?? 'build/portal');
|
|
|
|
return self::usesWebAssets($assetsDir)
|
|
? 'https://assets.pressekonto.test'
|
|
: 'https://assets.pressekonto.test';
|
|
}
|
|
|
|
public static function isViteDevServerRunning(string $assetsDir): bool
|
|
{
|
|
return is_file(self::hotFilePath($assetsDir));
|
|
}
|
|
}
|