presseportale/app/Support/DomainAssetContext.php
Kevin Adametz 090a893cc6 PM-Vorschau: echtes Portal-Design, Direkt-Button und Portal-Switch
Der Vorschau-Link (/pm-vorschau/{token}) renderte eine schlichte
Standalone-Seite, die dem spaeteren Erscheinungsbild nicht entsprach.
Jetzt rendert er die echte Detailseite (web.release-detail) im Theme
des Zielportals:

- Controller wendet Domain-/Theme-Konfig des Zielportals an (Sprache
  der PM, Links zeigen auf die Portal-Domain), kein Hit-Zaehler
- Gelbes Vorschau-Banner mit Status und Link-Gueltigkeit; noindex per
  Meta-Tag + X-Robots-Tag-Header, Canonical entfaellt bei noindex
  (neue robots-Section im Web-Layout)
- Teilen-Buttons teilen den Vorschau-Link selbst (oeffentliche URL
  existiert vor Veroeffentlichung noch nicht)
- PMs fuer beide Portale: ?portal=... waehlt die Ansicht, Umschalter
  im Banner; im Kundenpanel je Portal ein Vorschau-Button, sonst ein
  einzelner "Vorschau oeffnen"-Button (Link-Feld jetzt kopierbar)
- Alte press-release-preview-View entfernt

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 13:11:57 +00:00

176 lines
5.1 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]);
}
$portalHost = (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;
}
if (($config['domain_name'] ?? null) === $host) {
return array_merge($defaults, $config);
}
}
return $defaults;
}
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));
}
}