mivita/dev/subdomain-optimization/DomainResolver.php
2025-08-12 18:01:59 +02:00

261 lines
No EOL
8.2 KiB
PHP

<?php
namespace App\Http\Middleware;
use App\Domain\DomainContext;
use App\Services\DomainService;
use App\Services\Util;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Session;
/**
* Enhanced Domain Resolver Middleware
*
* This middleware replaces the current Subdomain middleware with a more
* robust, maintainable solution that properly handles all domain types.
*/
class DomainResolver
{
private DomainService $domainService;
public function __construct(DomainService $domainService)
{
$this->domainService = $domainService;
}
/**
* Handle an incoming request
*/
public function handle(Request $request, Closure $next)
{
// Parse the domain from the request
$host = $request->getHost();
$domainInfo = $this->domainService->parseDomain($host);
// Create domain context
$context = $this->createDomainContext($request, $domainInfo);
// Handle unknown domains
if ($context->isUnknownDomain()) {
return $this->handleUnknownDomain($request, $context);
}
// Set up the application context
$this->setupApplicationContext($request, $context);
// Store context in the application container
app()->instance('domain.context', $context);
return $next($request);
}
/**
* Create domain context from parsed domain information
*/
private function createDomainContext(Request $request, array $domainInfo): DomainContext
{
$userShop = null;
// Load user shop for user-shop domains
if ($domainInfo['type'] === 'user-shop' && $domainInfo['subdomain']) {
$userShop = $this->domainService->getUserShop($domainInfo['subdomain']);
// If user shop is invalid, mark as unknown
if (!$userShop) {
$domainInfo['type'] = 'unknown';
}
}
// Handle main-shop domain with default shop
if ($domainInfo['type'] === 'main-shop') {
$userShop = $this->domainService->getDefaultUserShop();
}
return DomainContext::fromDomainInfo($domainInfo, $userShop);
}
/**
* Handle unknown or invalid domains
*/
private function handleUnknownDomain(Request $request, DomainContext $context)
{
// Log the invalid domain attempt
\Log::warning('Unknown domain accessed', [
'host' => $request->getHost(),
'domain_info' => $context->toArray(),
'user_agent' => $request->userAgent(),
'ip' => $request->ip()
]);
// Redirect to main domain
$mainUrl = $this->domainService->buildUrl('main');
return redirect($mainUrl, 301);
}
/**
* Set up application context based on domain
*/
private function setupApplicationContext(Request $request, DomainContext $context): void
{
switch ($context->type) {
case 'user-shop':
$this->setupUserShopContext($request, $context);
break;
case 'main-shop':
$this->setupMainShopContext($request, $context);
break;
case 'crm':
$this->setupCrmContext($request, $context);
break;
case 'portal':
$this->setupPortalContext($request, $context);
break;
case 'checkout':
$this->setupCheckoutContext($request, $context);
break;
case 'main':
$this->setupMainContext($request, $context);
break;
}
// Set up common configurations
$this->setupCommonContext($request, $context);
}
/**
* Set up context for user shop domains
*/
private function setupUserShopContext(Request $request, DomainContext $context): void
{
if (!$context->userShop) {
return;
}
// Set up session data (maintaining compatibility with current implementation)
Session::put('user_shop', $context->userShop);
Session::put('user_shop_domain', $context->fullDomain);
// Set dynamic URL configuration
Config::set('app.url', $context->fullDomain);
// Set route prefix for utilities (maintaining compatibility)
Util::setPostRoute('user/');
// Remove subdomain parameter from route (maintaining compatibility)
if ($request->route() && $request->route()->hasParameter('subdomain')) {
$request->route()->forgetParameter('subdomain');
}
}
/**
* Set up context for main shop domain (mivita.shop)
*/
private function setupMainShopContext(Request $request, DomainContext $context): void
{
if (!$context->userShop) {
return;
}
// Set up session data similar to user shops
Session::put('user_shop', $context->userShop);
Session::put('user_shop_domain', $context->fullDomain);
// Set dynamic URL configuration
Config::set('app.url', $context->fullDomain);
// Set route prefix
Util::setPostRoute('user/');
}
/**
* Set up context for CRM domain (my.mivita.care)
*/
private function setupCrmContext(Request $request, DomainContext $context): void
{
// Set up CRM-specific configurations
Config::set('app.url', $context->fullDomain);
// Set session domain for cross-subdomain compatibility
Config::set('session.domain', '.' . $context->domain . $context->tld);
}
/**
* Set up context for portal domain (in.mivita.care)
*/
private function setupPortalContext(Request $request, DomainContext $context): void
{
// Set up portal-specific configurations
Config::set('app.url', $context->fullDomain);
// Set session domain for cross-subdomain compatibility
Config::set('session.domain', '.' . $context->domain . $context->tld);
}
/**
* Set up context for checkout domain (checkout.mivita.care)
*/
private function setupCheckoutContext(Request $request, DomainContext $context): void
{
// Set up checkout-specific configurations
Config::set('app.url', $context->fullDomain);
// Set session domain for cross-subdomain compatibility
Config::set('session.domain', '.' . $context->domain . $context->tld);
}
/**
* Set up context for main domain (mivita.care)
*/
private function setupMainContext(Request $request, DomainContext $context): void
{
// Set up main domain configurations
Config::set('app.url', $context->fullDomain);
}
/**
* Set up common context configurations
*/
private function setupCommonContext(Request $request, DomainContext $context): void
{
// Set up view namespace if applicable
if ($namespace = $context->getViewNamespace()) {
// This could be used by view composers or other components
Config::set('view.domain_namespace', $namespace);
}
// Set up any domain-specific cache prefixes
if ($context->isUserShopDomain()) {
Config::set('cache.prefix', config('cache.prefix') . '_' . $context->getUserShopSlug());
}
// Set up CSRF token domain
if (in_array($context->type, ['crm', 'portal', 'checkout'])) {
Config::set('session.same_site', 'lax');
}
}
/**
* Validate that the domain is properly configured for this request
*/
private function validateDomainConfiguration(DomainContext $context): bool
{
$errors = $this->domainService->validateConfiguration();
if (!empty($errors)) {
\Log::error('Domain configuration errors', [
'errors' => $errors,
'context' => $context->toArray()
]);
return false;
}
return true;
}
}