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

344 lines
No EOL
10 KiB
PHP

<?php
namespace App\Providers;
use App\Domain\DomainContext;
use App\Services\DomainService;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
/**
* Enhanced Route Service Provider
*
* This service provider implements the new domain-aware routing system
* that loads routes based on the current domain context.
*/
class RouteServiceProvider extends ServiceProvider
{
/**
* The path to the "home" route for your application.
*/
public const HOME = '/home';
/**
* Define your route model bindings, pattern filters, etc.
*/
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
// Load API routes first (domain-independent)
Route::prefix('api')
->middleware('api')
->group(base_path('routes/api.php'));
// Load web routes with domain awareness
Route::middleware('web')
->group(function () {
$this->loadDomainAwareRoutes();
});
});
}
/**
* Load routes based on current domain context
*/
protected function loadDomainAwareRoutes(): void
{
// Try to get domain context (might not be available during route caching)
$domainContext = $this->getDomainContext();
// Load shared routes first (always available)
$this->loadSharedRoutes();
// Load domain-specific routes if context is available
if ($domainContext) {
$this->loadDomainSpecificRoutes($domainContext);
} else {
// Fallback: load all routes for route caching or when context is unavailable
$this->loadAllRoutes();
}
}
/**
* Get current domain context
*/
protected function getDomainContext(): ?DomainContext
{
try {
return app('domain.context');
} catch (\Exception $e) {
// Context not available (e.g., during route caching)
return null;
}
}
/**
* Load shared routes that are available across all domains
*/
protected function loadSharedRoutes(): void
{
// Legal pages (datenschutz, impressum, agb)
Route::group([], base_path('routes/shared/legal.php'));
// Common functionality (health checks, modals, etc.)
Route::group([], base_path('routes/shared/common.php'));
}
/**
* Load routes specific to the current domain
*/
protected function loadDomainSpecificRoutes(DomainContext $context): void
{
match($context->type) {
'main' => $this->loadMainDomainRoutes(),
'main-shop' => $this->loadShopDomainRoutes(),
'crm' => $this->loadCrmDomainRoutes(),
'portal' => $this->loadPortalDomainRoutes(),
'checkout' => $this->loadCheckoutDomainRoutes(),
'user-shop' => $this->loadUserShopDomainRoutes(),
default => null // Unknown domains are handled by middleware
};
}
/**
* Load all routes (fallback for route caching)
*/
protected function loadAllRoutes(): void
{
// Load all domain-specific routes
$this->loadMainDomainRoutes();
$this->loadShopDomainRoutes();
$this->loadCrmDomainRoutes();
$this->loadPortalDomainRoutes();
$this->loadCheckoutDomainRoutes();
$this->loadUserShopDomainRoutes();
}
/**
* Load main domain routes (mivita.care)
*/
protected function loadMainDomainRoutes(): void
{
Route::group([
'middleware' => ['domain.resolver'],
'domain' => $this->getMainDomain(),
], base_path('routes/domains/main.php'));
}
/**
* Load shop domain routes (mivita.shop)
*/
protected function loadShopDomainRoutes(): void
{
Route::group([
'middleware' => ['domain.resolver'],
'domain' => $this->getShopDomain(),
], base_path('routes/domains/shop.php'));
}
/**
* Load CRM domain routes (my.mivita.care)
*/
protected function loadCrmDomainRoutes(): void
{
Route::group([
'middleware' => ['domain.resolver'],
'domain' => $this->getCrmDomain(),
], base_path('routes/domains/subdomains/crm.php'));
}
/**
* Load portal domain routes (in.mivita.care)
*/
protected function loadPortalDomainRoutes(): void
{
Route::group([
'middleware' => ['domain.resolver'],
'domain' => $this->getPortalDomain(),
], base_path('routes/domains/subdomains/portal.php'));
}
/**
* Load checkout domain routes (checkout.mivita.care)
*/
protected function loadCheckoutDomainRoutes(): void
{
Route::group([
'middleware' => ['domain.resolver'],
'domain' => $this->getCheckoutDomain(),
], base_path('routes/domains/subdomains/checkout.php'));
}
/**
* Load user shop domain routes ({slug}.mivita.care)
*/
protected function loadUserShopDomainRoutes(): void
{
Route::group([
'middleware' => ['domain.resolver'],
'domain' => $this->getUserShopDomain(),
], base_path('routes/domains/subdomains/user-shops.php'));
}
/**
* Get main domain pattern
*/
protected function getMainDomain(): string
{
$domain = config('app.domain', 'mivita');
$tld = config('app.tld_care', '.care');
return $domain . $tld;
}
/**
* Get shop domain pattern
*/
protected function getShopDomain(): string
{
$domain = config('app.domain', 'mivita');
$tld = config('app.tld_shop', '.shop');
return $domain . $tld;
}
/**
* Get CRM domain pattern
*/
protected function getCrmDomain(): string
{
$subdomain = rtrim(config('app.pre_url_crm', 'my.'), '.');
$domain = config('app.domain', 'mivita');
$tld = config('app.tld_care', '.care');
return $subdomain . '.' . $domain . $tld;
}
/**
* Get portal domain pattern
*/
protected function getPortalDomain(): string
{
$subdomain = rtrim(config('app.pre_url_portal', 'in.'), '.');
$domain = config('app.domain', 'mivita');
$tld = config('app.tld_care', '.care');
return $subdomain . '.' . $domain . $tld;
}
/**
* Get checkout domain pattern
*/
protected function getCheckoutDomain(): string
{
$subdomain = rtrim(config('app.pre_url_checkout', 'checkout.'), '.');
$domain = config('app.domain', 'mivita');
$tld = config('app.tld_care', '.care');
return $subdomain . '.' . $domain . $tld;
}
/**
* Get user shop domain pattern (wildcard subdomain)
*/
protected function getUserShopDomain(): string
{
$domain = config('app.domain', 'mivita');
$tld = config('app.tld_care', '.care');
return '{subdomain}.' . $domain . $tld;
}
/**
* Configure the rate limiters for the application
*/
protected function configureRateLimiting()
{
// API rate limiting
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
// Domain-specific rate limiting
RateLimiter::for('crm', function (Request $request) {
return Limit::perMinute(120)->by($request->user()?->id ?: $request->ip());
});
RateLimiter::for('portal', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
RateLimiter::for('checkout', function (Request $request) {
return Limit::perMinute(30)->by($request->ip());
});
RateLimiter::for('user-shop', function (Request $request) {
return Limit::perMinute(100)->by($request->ip());
});
// Login rate limiting
RateLimiter::for('login', function (Request $request) {
return [
Limit::perMinute(5)->by($request->email . $request->ip()),
Limit::perMinute(10)->by($request->ip()),
];
});
}
/**
* Get route caching path based on domain
*/
public function getCachedRoutesPath()
{
// Use different cache files for different environments
$environment = app()->environment();
return $this->app->bootstrapPath("cache/routes-v7-{$environment}.php");
}
/**
* Determine if routes are cached
*/
public function routesAreCached()
{
return $this->app->routesAreCached();
}
/**
* Load the cached routes for the application
*/
public function loadCachedRoutes()
{
$this->app->booted(function () {
require $this->getCachedRoutesPath();
});
}
/**
* Register domain-specific route macros
*/
protected function registerRouteMacros(): void
{
// Macro for domain-aware redirects
Route::macro('domainRedirect', function (string $domainType, string $path = '/', int $status = 302) {
return function () use ($domainType, $path, $status) {
$domainService = app(DomainService::class);
$url = $domainService->buildUrl($domainType, $path);
return redirect($url, $status);
};
});
// Macro for user shop routes
Route::macro('userShop', function (callable $callback) {
return Route::group([
'middleware' => ['domain.resolver', 'user-shop.validate'],
], $callback);
});
// Macro for CRM routes
Route::macro('crm', function (callable $callback) {
return Route::group([
'middleware' => ['domain.resolver', 'auth'],
'prefix' => '',
], $callback);
});
}
}