cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_core'); $this->populate(); } /** * Builds up all domain records from DB and all routes */ protected function populate() { if ($data = $this->cache->get($this->cacheIdentifier)) { // Due to the nature of PhpFrontend, the `groupedDomainsPerPage = json_decode($data, true); } else { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_domain'); $statement = $queryBuilder ->select('*') ->from('sys_domain') ->orderBy('sorting', 'ASC') ->execute(); while ($row = $statement->fetch()) { $row['domainName'] = rtrim($row['domainName'], '/'); $this->groupedDomainsPerPage[(int)$row['pid']][] = $row; } $this->cache->set($this->cacheIdentifier, json_encode($this->groupedDomainsPerPage)); } } /** * @return array */ public function getGroupedDomainsPerPage(): array { return $this->groupedDomainsPerPage ?? []; } /** * Obtains a sys_domain record that fits for a given page ID by traversing the rootline up and finding * a suitable page with sys_domain records. * As all sys_domains have been fetched already, the internal grouped list of sys_domains can be used directly. * * Usually used in the Frontend to find out the domain of a page to link to. * * Includes a runtime cache if a frontend request links to the same page multiple times. * * @param int $pageId Target page id * @param ServerRequestInterface|null $currentRequest if given, the domain record is marked with "isCurrentDomain" * @return array|null the sys_domain record if found */ public function matchPageId(int $pageId, ServerRequestInterface $currentRequest = null): ?array { // Using array_key_exists() here, nice $result can be NULL // (happens, if there's no domain records defined) if (array_key_exists($pageId, $this->domainDataCache)) { return $this->domainDataCache[$pageId]; } try { $this->domainDataCache[$pageId] = $this->resolveDomainEntry( $pageId, $currentRequest ); } catch (RootLineException $e) { $this->domainDataCache[$pageId] = null; } return $this->domainDataCache[$pageId]; } /** * Returns the full sys_domain record, based on a page record, which is assumed the "pid" of the sys_domain record. * Since ordering is taken into account, this is the first sys_domain record on that page Id. * * @param int $pageId * @return array|null */ public function matchRootPageId(int $pageId): ?array { return !empty($this->groupedDomainsPerPage[$pageId]) ? reset($this->groupedDomainsPerPage[$pageId]) : null; } /** * @param int $pageId * @param ServerRequestInterface|null $currentRequest * @return array|null */ protected function resolveDomainEntry(int $pageId, ?ServerRequestInterface $currentRequest): ?array { $rootLine = GeneralUtility::makeInstance(RootlineUtility::class, $pageId)->get(); // walk the rootline downwards from the target page // to the root page, until a domain record is found foreach ($rootLine as $pageInRootline) { $pidInRootline = (int)$pageInRootline['uid']; if (empty($this->groupedDomainsPerPage[$pidInRootline])) { continue; } $domainEntriesOfPage = $this->groupedDomainsPerPage[$pidInRootline]; foreach ($domainEntriesOfPage as $domainEntry) { if ($domainEntry['hidden']) { continue; } // When no currentRequest is given, let's take the first non-hidden sys_domain page if ($currentRequest === null) { return $domainEntry; } // Otherwise the check should match against the current domain (and set "isCurrentDomain") // Current domain is "forced", however, otherwise the first one is fine if ($this->domainNameMatchesCurrentRequest($domainEntry['domainName'], $currentRequest)) { $result = $domainEntry; $result['isCurrentDomain'] = true; return $result; } } } return null; } /** * Whether the given domain name (potentially including a path segment) matches currently requested host or * the host including the path segment * * @param string $domainName * @param ServerRequestInterface|null $request * @return bool */ protected function domainNameMatchesCurrentRequest($domainName, ServerRequestInterface $request): bool { /** @var NormalizedParams $normalizedParams */ $normalizedParams = $request->getAttribute('normalizedParams'); if (!($normalizedParams instanceof NormalizedParams)) { return false; } $currentDomain = $normalizedParams->getHttpHost(); // remove the script filename from the path segment. $currentPathSegment = trim(preg_replace('|/[^/]*$|', '', $normalizedParams->getScriptName())); return $currentDomain === $domainName || $currentDomain . $currentPathSegment === $domainName; } }