Lines
100.00%
27 / 27
Methods
100.00%
2 / 2
Classes
100.00%
1 / 1
| Name | Lines | Methods | CRAP | ||||
|---|---|---|---|---|---|---|---|
| locateConfigurationDirectory | 100.00% | 15 / 15 | 100.00% | 1 / 1 | 6 | ||
| extractTenantFromSubdomain | 100.00% | 12 / 12 | 100.00% | 1 / 1 | 6 | ||
| 24 | class MultisiteConfigurationLocator | |
| 25 | { | |
| 26 | public static function locateConfigurationDirectory(Request $request, string $configurationDirectory): ?string | |
| 27 | { | |
| 28 | $protocol = $request->isSecure() ? 'https' : 'http'; | |
| 29 | $host = $request->getHost(); | |
| 30 | $scriptName = $request->getScriptName(); | |
| 31 | ||
| 32 | $parsed = parse_url($protocol . '://' . $host . $scriptName); | |
| 33 | ||
| 34 | $parsedHost = (string) ($parsed['host'] ?? ''); | |
| 35 | if ($parsedHost !== '') { | |
| 36 | // 1. Try an exact hostname match (existing behavior) | |
| 37 | $configDir = rtrim($configurationDirectory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $parsedHost; | |
| 38 | ||
| 39 | if (is_dir($configDir)) { | |
| 40 | return $configDir; | |
| 41 | } | |
| 42 | ||
| 43 | // 2. Try subdomain-based tenant matching | |
| 44 | $tenantName = self::extractTenantFromSubdomain($parsedHost); | |
| 45 | if ($tenantName !== null) { | |
| 46 | $configDir = rtrim($configurationDirectory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $tenantName; | |
| 47 | ||
| 48 | if (is_dir($configDir)) { | |
| 49 | return $configDir; | |
| 50 | } | |
| 51 | } | |
| 52 | } | |
| 53 | ||
| 54 | return null; | |
| 55 | } | |
| 56 | ||
| 57 | /** | |
| 58 | * Extracts the tenant identifier from a subdomain pattern. | |
| 59 | * | |
| 60 | * Checks the PMF_MULTISITE_BASE_DOMAIN environment variable. If set, | |
| 61 | * extracts the subdomain part from hostnames matching {tenant}.{baseDomain}. | |
| 62 | * | |
| 63 | * Example: With PMF_MULTISITE_BASE_DOMAIN=faq.example.com, | |
| 64 | * the host "acme.faq.example.com" returns "acme". | |
| 65 | */ | |
| 66 | public static function extractTenantFromSubdomain(string $host): ?string | |
| 67 | { | |
| 68 | $host = strtolower($host); | |
| 69 | $baseDomain = getenv('PMF_MULTISITE_BASE_DOMAIN'); | |
| 70 | if ($baseDomain === false || $baseDomain === '') { | |
| 71 | return null; | |
| 72 | } | |
| 73 | ||
| 74 | $baseDomain = strtolower(ltrim($baseDomain, characters: '.')); | |
| 75 | $suffix = '.' . $baseDomain; | |
| 76 | ||
| 77 | if (!str_ends_with($host, $suffix)) { | |
| 78 | return null; | |
| 79 | } | |
| 80 | ||
| 81 | $tenant = strtolower(substr($host, offset: 0, length: -strlen($suffix))); | |
| 82 | if ($tenant === '' || str_contains($tenant, '.')) { | |
| 83 | return null; | |
| 84 | } | |
| 85 | ||
| 86 | return $tenant; | |
| 87 | } | |
| 88 | } |