mivita/app/Http/Middleware/SubdomainResolver.php
2025-10-20 17:42:08 +02:00

255 lines
8 KiB
PHP

<?php
namespace App\Http\Middleware;
use App\Domain\EarlyDomainParser;
use App\Models\UserShop;
use App\Services\Util;
use Closure;
use Config;
use Session;
/**
* Lightweight subdomain resolution middleware
*
* Uses config/domains.php for domain configuration and provides
* simple, working subdomain handling without session timing issues.
*/
class SubdomainResolver
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Skip for API and asset requests
if (!$this->shouldProcess($request)) {
return $next($request);
}
// Parse domain information using config/domains.php
$host = $request->getHost();
$domainInfo = EarlyDomainParser::parseDomain($host);
Session::put('domainInfo', $domainInfo);
\Log::info('domainInfo', $domainInfo);
// Route to appropriate handler based on domain type
return match ($domainInfo['type']) {
'user-shop' => $this->handleUserShop($request, $next, $domainInfo),
'main-shop' => $this->handleMainShop($request, $next, $domainInfo),
'main' => $this->handleMainCare($request, $next, $domainInfo),
'crm' => $this->handleCrm($request, $next, $domainInfo),
'portal' => $this->handlePortal($request, $next, $domainInfo),
'checkout' => $this->handleCheckout($request, $next, $domainInfo),
default => $this->handleUnknownDomain($request, $domainInfo),
};
}
/**
* Handle user shop subdomain (e.g., user.mivita.care)
*/
private function handleUserShop($request, Closure $next, array $domainInfo)
{
$subdomain = $domainInfo['subdomain'];
$userShop = UserShop::where('slug', $subdomain)->first();
// Remove subdomain parameter from route
if ($request->route('subdomain')) {
$request->route()->forgetParameter('subdomain');
}
if (!$userShop) {
return $this->handleUnknownDomain($request, $domainInfo);
}
// Validate shop status
if (!$userShop->active || !$userShop->user || !$userShop->user->isActiveShop()) {
//hier ein routing zu shop???
abort(503, 'Shop temporarily unavailable');
}
$host = $this->getHost($domainInfo);
// Configure session domain based on domain config
$this->configureSessionDomain($host);
// Set up application context
$this->setupUserShopContext($userShop, $subdomain, $host);
return $next($request);
}
/**
* Handle main shop domain (e.g., mivita.shop)
*/
private function handleMainShop($request, Closure $next, array $domainInfo)
{
// Load default shop from domain config
$defaultShop = isset($domainInfo['default_user_shop']) ? $domainInfo['default_user_shop'] : 'aloevera';
$userShop = UserShop::where('slug', $defaultShop)->first();
// Configure session domain based on domain config, not getHost only for care domains
$host = isset($domainInfo['host']) ? $domainInfo['host'] : config('app.domain') . config('app.tld_shop');
Config::set('session.domain', '.' . $host);
if ($userShop) {
\Session::put('user_shop', $userShop);
\Session::put('user_shop_domain', config('app.protocol') . $host);
Util::setPostRoute('user/');
Config::set('app.url', $host);
}
return $next($request);
}
/**
* Handle main care domain (e.g., mivita.care)
*/
private function handleMainCare($request, Closure $next, array $domainInfo)
{
// Configure session domain based on domain config
$host = $this->getHost($domainInfo);
$host = isset($domainInfo['host']) ? $domainInfo['host'] : config('app.domain') . config('app.tld_care');
$this->configureSessionDomain($host);
// Clear any existing shop session data, not needed for main care domain
Session::forget('user_shop');
Session::forget('user_shop_domain');
// Set app URL
Config::set('app.url', $host);
return $next($request);
}
/**
* Handle CRM domain (e.g., my.mivita.care)
*/
private function handleCrm($request, Closure $next, array $domainInfo)
{
// Configure session domain for CRM
$host = $this->getHost($domainInfo);
$this->configureSessionDomain($host);
// Clear shop data for CRM , not needed for crm domain
Session::forget('user_shop');
Session::forget('user_shop_domain');
// Set app URL
Config::set('app.url', $host);
\Log::info('Session all', Session::all());
return $next($request);
}
/**
* Handle Portal domain (e.g., in.mivita.care)
*/
private function handlePortal($request, Closure $next, array $domainInfo)
{
// Configure session domain for Portal
$host = $this->getHost($domainInfo);
$this->configureSessionDomain($host);
// Don't clear user_shop - checkout needs to know which shop
// Session::forget('user_shop');
// Session::forget('user_shop_domain');
// Set app URL
Config::set('app.url', $host);
return $next($request);
}
/**
* Handle Checkout domain (e.g., checkout.mivita.care)
*/
private function handleCheckout($request, Closure $next, array $domainInfo)
{
// Configure session domain for Checkout
$host = $this->getHost($domainInfo);
$this->configureSessionDomain($host);
// Keep existing shop session data for checkout
// Don't clear user_shop - checkout needs to know which shop
// Set app URL
Config::set('app.url', $host);
return $next($request);
}
/**
* Handle unknown domains
*/
private function handleUnknownDomain($request, array $domainInfo)
{
// Redirect to main domain
$mainDomain = config('domains.domains.main.host');
$mainUrl = config('domains.protocol') . $mainDomain;
return redirect()->away($mainUrl, 301);
}
/**
* Set up user shop context in session and config
*/
private function setupUserShopContext(UserShop $userShop, ?string $subdomain = null, string $host = '')
{
// Put shop data in session
Session::put('user_shop', $userShop);
// Build shop domain URL using protocol from config
$shopDomain = config('domains.protocol') . $host;
//$shopDomain = config('app.protocol').$user_shop->slug.".".config('app.domain').config('app.tld_care'));
Session::put('user_shop_domain', $shopDomain);
// Set app URL for URL generation
Config::set('app.url', rtrim($shopDomain, '/'));
// Set post route for compatibility
Util::setPostRoute('user/');
}
/**
* Configure session domain based on host
*/
private function configureSessionDomain(string $host): void
{
Config::set('session.domain', '.' . config('app.domain') . config('app.tld_care'));
}
/**
* Get host from domain info
*/
private function getHost(array $domainInfo): string
{
if (isset($domainInfo['host'])) {
return $domainInfo['host'];
}
abort(503, 'Host not found in domain info');
//throw new \Exception('Host not found in domain info');
}
/**
* Check if request should be processed by this middleware
*/
private function shouldProcess($request): bool
{
// Skip API requests
if ($request->is('api/*')) {
return false;
}
// Skip asset requests
if ($request->isMethod('GET') && preg_match('/\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$/i', $request->path())) {
return false;
}
// Skip Laravel internal requests
if ($request->is('_debugbar/*')) {
return false;
}
return true;
}
}