272 lines
No EOL
7.7 KiB
PHP
272 lines
No EOL
7.7 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\UserShop;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Config;
|
|
|
|
/**
|
|
* Domain Service - Centralized domain and subdomain management
|
|
*
|
|
* This service provides a centralized way to handle domain resolution,
|
|
* subdomain validation, and domain-specific configuration management.
|
|
*/
|
|
class DomainService
|
|
{
|
|
private const CACHE_TTL = 3600; // 1 hour
|
|
private const FIXED_SUBDOMAINS = ['my', 'in', 'checkout'];
|
|
|
|
private array $domainConfig;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->domainConfig = $this->loadDomainConfiguration();
|
|
}
|
|
|
|
/**
|
|
* Load domain configuration from config files
|
|
*/
|
|
private function loadDomainConfiguration(): array
|
|
{
|
|
return [
|
|
'main_domain' => config('app.domain'),
|
|
'main_tld' => config('app.tld_care'),
|
|
'shop_tld' => config('app.tld_shop'),
|
|
'protocol' => config('app.protocol'),
|
|
'subdomains' => [
|
|
'crm' => config('app.pre_url_crm', 'my.'),
|
|
'portal' => config('app.pre_url_portal', 'in.'),
|
|
'checkout' => config('app.pre_url_checkout', 'checkout.'),
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Determine the type of subdomain
|
|
*/
|
|
public function getSubdomainType(string $subdomain): string
|
|
{
|
|
// Check if it's a fixed subdomain
|
|
if (in_array($subdomain, self::FIXED_SUBDOMAINS)) {
|
|
return match($subdomain) {
|
|
'my' => 'crm',
|
|
'in' => 'portal',
|
|
'checkout' => 'checkout',
|
|
default => 'unknown'
|
|
};
|
|
}
|
|
|
|
// Check if it's a valid user shop
|
|
if ($this->isValidUserShop($subdomain)) {
|
|
return 'user-shop';
|
|
}
|
|
|
|
return 'unknown';
|
|
}
|
|
|
|
/**
|
|
* Check if a subdomain represents a valid user shop
|
|
*/
|
|
public function isValidUserShop(string $slug): bool
|
|
{
|
|
$cacheKey = "user_shop_valid_{$slug}";
|
|
|
|
return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($slug) {
|
|
$userShop = UserShop::where('slug', $slug)->first();
|
|
|
|
if (!$userShop) {
|
|
return false;
|
|
}
|
|
|
|
if (!$userShop->active) {
|
|
return false;
|
|
}
|
|
|
|
if (!$userShop->user) {
|
|
return false;
|
|
}
|
|
|
|
if (!$userShop->user->isActiveShop()) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get user shop by slug with caching
|
|
*/
|
|
public function getUserShop(string $slug): ?UserShop
|
|
{
|
|
if (!$this->isValidUserShop($slug)) {
|
|
return null;
|
|
}
|
|
|
|
$cacheKey = "user_shop_{$slug}";
|
|
|
|
return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($slug) {
|
|
return UserShop::where('slug', $slug)
|
|
->with('user')
|
|
->first();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Parse domain from request and determine context
|
|
*/
|
|
public function parseDomain(string $host): array
|
|
{
|
|
$parts = explode('.', $host);
|
|
|
|
// Handle different TLD scenarios
|
|
if (count($parts) < 2) {
|
|
return [
|
|
'type' => 'invalid',
|
|
'domain' => $host,
|
|
'subdomain' => null,
|
|
'tld' => null
|
|
];
|
|
}
|
|
|
|
// Extract TLD and domain
|
|
$tld = '.' . end($parts);
|
|
$domain = $parts[count($parts) - 2];
|
|
|
|
// Check for subdomain
|
|
$subdomain = null;
|
|
if (count($parts) > 2) {
|
|
$subdomain = $parts[0];
|
|
}
|
|
|
|
// Determine domain type
|
|
$type = $this->determineDomainType($domain, $subdomain, $tld);
|
|
|
|
return [
|
|
'type' => $type,
|
|
'domain' => $domain,
|
|
'subdomain' => $subdomain,
|
|
'tld' => $tld,
|
|
'full_domain' => $host
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Determine domain type based on domain, subdomain, and TLD
|
|
*/
|
|
private function determineDomainType(string $domain, ?string $subdomain, string $tld): string
|
|
{
|
|
// Check if it's the main domain
|
|
if ($domain === $this->domainConfig['main_domain']) {
|
|
if ($subdomain === null) {
|
|
// Main domain without subdomain
|
|
if ($tld === $this->domainConfig['shop_tld']) {
|
|
return 'main-shop'; // mivita.shop
|
|
}
|
|
return 'main'; // mivita.care
|
|
}
|
|
|
|
// Main domain with subdomain
|
|
return $this->getSubdomainType($subdomain);
|
|
}
|
|
|
|
return 'unknown';
|
|
}
|
|
|
|
/**
|
|
* Build URL for specific domain type
|
|
*/
|
|
public function buildUrl(string $type, ?string $path = null, ?string $slug = null): string
|
|
{
|
|
$base = $this->domainConfig['protocol'];
|
|
|
|
switch ($type) {
|
|
case 'main':
|
|
$base .= $this->domainConfig['main_domain'] . $this->domainConfig['main_tld'];
|
|
break;
|
|
|
|
case 'main-shop':
|
|
$base .= $this->domainConfig['main_domain'] . $this->domainConfig['shop_tld'];
|
|
break;
|
|
|
|
case 'crm':
|
|
$base .= rtrim($this->domainConfig['subdomains']['crm'], '.') .
|
|
$this->domainConfig['main_domain'] . $this->domainConfig['main_tld'];
|
|
break;
|
|
|
|
case 'portal':
|
|
$base .= rtrim($this->domainConfig['subdomains']['portal'], '.') .
|
|
$this->domainConfig['main_domain'] . $this->domainConfig['main_tld'];
|
|
break;
|
|
|
|
case 'checkout':
|
|
$base .= rtrim($this->domainConfig['subdomains']['checkout'], '.') .
|
|
$this->domainConfig['main_domain'] . $this->domainConfig['main_tld'];
|
|
break;
|
|
|
|
case 'user-shop':
|
|
if (!$slug) {
|
|
throw new \InvalidArgumentException('Slug required for user-shop URLs');
|
|
}
|
|
$base .= $slug . '.' . $this->domainConfig['main_domain'] . $this->domainConfig['main_tld'];
|
|
break;
|
|
|
|
default:
|
|
throw new \InvalidArgumentException("Unknown domain type: {$type}");
|
|
}
|
|
|
|
if ($path) {
|
|
$base .= '/' . ltrim($path, '/');
|
|
}
|
|
|
|
return $base;
|
|
}
|
|
|
|
/**
|
|
* Get domain configuration
|
|
*/
|
|
public function getDomainConfiguration(): array
|
|
{
|
|
return $this->domainConfig;
|
|
}
|
|
|
|
/**
|
|
* Clear user shop cache
|
|
*/
|
|
public function clearUserShopCache(string $slug): void
|
|
{
|
|
Cache::forget("user_shop_valid_{$slug}");
|
|
Cache::forget("user_shop_{$slug}");
|
|
}
|
|
|
|
/**
|
|
* Get default user shop for main domain (fallback)
|
|
*/
|
|
public function getDefaultUserShop(): ?UserShop
|
|
{
|
|
return $this->getUserShop('aloevera'); // Current hardcoded fallback
|
|
}
|
|
|
|
/**
|
|
* Validate domain configuration
|
|
*/
|
|
public function validateConfiguration(): array
|
|
{
|
|
$errors = [];
|
|
|
|
if (empty($this->domainConfig['main_domain'])) {
|
|
$errors[] = 'Main domain not configured';
|
|
}
|
|
|
|
if (empty($this->domainConfig['main_tld'])) {
|
|
$errors[] = 'Main TLD not configured';
|
|
}
|
|
|
|
if (empty($this->domainConfig['protocol'])) {
|
|
$errors[] = 'Protocol not configured';
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
} |