packageManager)) ->withPrefix('usertsconfig-packages-strings') ->toString(); if ($cache) { $collectedUserTsConfigArrayFromCache = $cache->require($cacheIdentifier); if ($collectedUserTsConfigArrayFromCache) { $gotPackagesUserTsConfigFromCache = true; $collectedUserTsConfigArray = $collectedUserTsConfigArrayFromCache; } } if (!$gotPackagesUserTsConfigFromCache) { $event = $this->eventDispatcher->dispatch(new BeforeLoadedUserTsConfigEvent()); $collectedUserTsConfigArray = $event->getTsConfig(); foreach ($this->packageManager->getActivePackages() as $package) { $packagePath = $package->getPackagePath(); $tsConfigFile = null; if (file_exists($packagePath . 'Configuration/user.tsconfig')) { $tsConfigFile = $packagePath . 'Configuration/user.tsconfig'; } elseif (file_exists($packagePath . 'Configuration/User.tsconfig')) { $tsConfigFile = $packagePath . 'Configuration/User.tsconfig'; } if ($tsConfigFile) { $typoScriptString = @file_get_contents($tsConfigFile); if (!empty($typoScriptString)) { $collectedUserTsConfigArray['userTsConfig-package-' . $package->getPackageKey()] = $typoScriptString; } } } $cache?->set($cacheIdentifier, 'return unserialize(\'' . addcslashes(serialize($collectedUserTsConfigArray), '\'\\') . '\');'); } foreach ($collectedUserTsConfigArray as $key => $typoScriptString) { $includeTree->addChild($this->getTreeFromString((string)$key, $typoScriptString, $tokenizer, $cache)); } foreach ($backendUser->userGroupsUID as $groupId) { // Loop through all groups and add their 'TSconfig' fields if (!empty($backendUser->userGroups[$groupId]['TSconfig'] ?? '')) { $includeTree->addChild($this->getTreeFromString('userTsConfig-group-' . $groupId, $backendUser->userGroups[$groupId]['TSconfig'], $tokenizer, $cache)); } if (trim($backendUser->userGroups[$groupId]['tsconfig_includes'] ?? '')) { $includeTsConfigFileList = GeneralUtility::trimExplode(',', $backendUser->userGroups[$groupId]['tsconfig_includes'], true); foreach ($includeTsConfigFileList as $key => $includeTsConfigFile) { $content = $this->getContentOfTsconfigFile($includeTsConfigFile); if (!empty($content)) { $includeTree->addChild($this->getTreeFromString('userTsConfig-include-group' . $key, $content, $tokenizer, $cache)); } } } } if (!empty($backendUser->user['TSconfig'] ?? '')) { $includeTree->addChild($this->getTreeFromString('userTsConfig-user', $backendUser->user['TSconfig'], $tokenizer, $cache)); } if (trim($backendUser->user['tsconfig_includes'] ?? '')) { $includeTsConfigFileList = GeneralUtility::trimExplode(',', $backendUser->user['tsconfig_includes'], true); foreach ($includeTsConfigFileList as $key => $includeTsConfigFile) { $content = $this->getContentOfTsconfigFile($includeTsConfigFile); if (!empty($content)) { $includeTree->addChild($this->getTreeFromString('userTsConfig-include-user' . $key, $content, $tokenizer, $cache)); } } } return $includeTree; } public function getPagesTsConfigTree( array $rootLine, TokenizerInterface $tokenizer, ?PhpFrontend $cache = null ): RootInclude { $collectedPagesTsConfigArray = []; $collectedPagesTsConfigArray += $this->getPackagePageTsConfigTree($cache); // HEADS up: rootLine may be modified by getSitePagesTsConfigTree $collectedPagesTsConfigArray += $this->getSitePageTsConfigTree($rootLine, $cache); $collectedPagesTsConfigArray += $this->getRootlinePageTsConfigTree($rootLine, $cache); $event = $this->eventDispatcher->dispatch(new ModifyLoadedPageTsConfigEvent( array_map(static fn(array $descriptor): string => $descriptor['content'], $collectedPagesTsConfigArray), $rootLine )); $collectedPagesTsConfigContentArray = $event->getTsConfig(); foreach ($collectedPagesTsConfigContentArray as $key => $content) { $collectedPagesTsConfigArray[$key]['content'] = $content; } $includeTree = new RootInclude(); foreach ($collectedPagesTsConfigArray as $key => $descriptor) { $typoScriptString = $descriptor['content']; $filename = $descriptor['filename'] ?? null; $includeTree->addChild($this->getTreeFromString((string)$key, $typoScriptString, $tokenizer, $cache, $filename)); } return $includeTree; } private function getPackagePageTsConfigTree( ?PhpFrontend $cache = null ): array { $collectedPagesTsConfigArray = []; $gotPackagesPagesTsConfigFromCache = false; $cacheIdentifier = (new PackageDependentCacheIdentifier($this->packageManager)) ->withPrefix('pagestsconfig-packages-strings') ->toString(); if ($cache) { $collectedPagesTsConfigArrayFromCache = $cache->require($cacheIdentifier); if ($collectedPagesTsConfigArrayFromCache) { $gotPackagesPagesTsConfigFromCache = true; $collectedPagesTsConfigArray = $collectedPagesTsConfigArrayFromCache; } } if (!$gotPackagesPagesTsConfigFromCache) { $event = $this->eventDispatcher->dispatch(new BeforeLoadedPageTsConfigEvent()); $collectedPagesTsConfigArray = array_map(static fn(string $config): array => ['content' => $config, 'filename' => null], $event->getTsConfig()); foreach ($this->packageManager->getActivePackages() as $package) { $packagePath = $package->getPackagePath(); $tsConfigFile = null; if (file_exists($packagePath . 'Configuration/page.tsconfig')) { $tsConfigFile = $packagePath . 'Configuration/page.tsconfig'; } elseif (file_exists($packagePath . 'Configuration/Page.tsconfig')) { $tsConfigFile = $packagePath . 'Configuration/Page.tsconfig'; } if ($tsConfigFile) { $typoScriptString = @file_get_contents($tsConfigFile); if (!empty($typoScriptString)) { $collectedPagesTsConfigArray['pagesTsConfig-package-' . $package->getPackageKey()] = [ 'filename' => $tsConfigFile, 'content' => $typoScriptString, ]; } } } $cache?->set($cacheIdentifier, 'return unserialize(\'' . addcslashes(serialize($collectedPagesTsConfigArray), '\'\\') . '\');'); } return $collectedPagesTsConfigArray; } private function getSitePageTsConfigTree( array &$rootLine, ?PhpFrontend $cache = null ): array { $reverseRootLine = array_reverse($rootLine); $rootlineUntilSite = []; $rootSite = null; foreach ($reverseRootLine as $rootLineEntry) { array_unshift($rootlineUntilSite, $rootLineEntry); $uid = (int)($rootLineEntry['uid'] ?? 0); if ($uid === 0) { continue; } try { $site = $this->siteFinder->getSiteByRootPageId($uid); } catch (SiteNotFoundException) { continue; } if ($site->isTypoScriptRoot()) { $rootSite = $site; $rootLine = $rootlineUntilSite; break; } } if ($rootSite === null) { return []; } $cacheIdentifier = (new PackageDependentCacheIdentifier($this->packageManager)) ->withPrefix('pagestsconfig-site') ->withAdditionalHashedIdentifier($rootSite->getIdentifier()) ->toString(); $pageTsConfig = $cache?->require($cacheIdentifier) ?: null; if ($pageTsConfig === null) { $pageTsConfig = []; $sets = $this->setRegistry->getSets(...$rootSite->getSets()); foreach ($sets as $set) { if ($set->pagets === null) { continue; } $filename = GeneralUtility::getFileAbsFileName($set->pagets); if (!file_exists($filename)) { continue; } $content = @file_get_contents($filename); if (!empty($content)) { $pageTsConfig['pageTsConfig-set-' . str_replace('/', '-', $set->name)] = [ 'filename' => $filename, 'content' => $content, ]; } } $pageTsConfig['pageTsConfig-site-' . $rootSite->getIdentifier()] = [ 'filename' => GeneralUtility::getFileAbsFileName(Environment::getConfigPath() . '/sites/' . $rootSite->getIdentifier() . '/page.tsconfig'), 'content' => $rootSite->getTSconfig()->pageTSconfig ?? '', ]; $cache?->set($cacheIdentifier, 'return ' . var_export($pageTsConfig, true) . ';'); } return $pageTsConfig; } private function getRootlinePageTsConfigTree( array $rootLine, ?PhpFrontend $cache = null ): array { $collectedPagesTsConfigArray = []; foreach ($rootLine as $page) { if (empty($page['uid'])) { // Page 0 can happen when the rootline is given from BE context. It has not TSconfig. Skip this. continue; } if (trim($page['tsconfig_includes'] ?? '')) { $includeTsConfigFileList = GeneralUtility::trimExplode(',', $page['tsconfig_includes'], true); foreach ($includeTsConfigFileList as $key => $includeTsConfigFile) { $content = $this->getContentOfTsconfigFile($includeTsConfigFile); if (!empty($content)) { $collectedPagesTsConfigArray['pagesTsConfig-page-' . $page['uid'] . '-includes-' . $key] = [ 'content' => $content, ]; } } } if (!empty($page['TSconfig'])) { $collectedPagesTsConfigArray['pagesTsConfig-page-' . $page['uid'] . '-tsConfig'] = ['content' => $page['TSconfig']]; } } return $collectedPagesTsConfigArray; } private function getContentOfTsconfigFile(string $path): string { if (PathUtility::isExtensionPath($path)) { [$includeTsConfigFileExtensionKey, $includeTsConfigFilename] = explode('/', substr($path, 4), 2); if ($includeTsConfigFilename !== '' && $includeTsConfigFileExtensionKey !== '' && ExtensionManagementUtility::isLoaded($includeTsConfigFileExtensionKey) ) { $extensionPath = ExtensionManagementUtility::extPath($includeTsConfigFileExtensionKey); $includeTsConfigFileAndPath = PathUtility::getCanonicalPath($extensionPath . $includeTsConfigFilename); if (str_starts_with($includeTsConfigFileAndPath, $extensionPath) && file_exists($includeTsConfigFileAndPath)) { return (string)file_get_contents($includeTsConfigFileAndPath); } } } return ''; } private function getTreeFromString( string $name, string $typoScriptString, TokenizerInterface $tokenizer, ?PhpFrontend $cache = null, ?string $filename = null, ): TsConfigInclude { $lowercaseName = mb_strtolower($name); $identifier = (new PackageDependentCacheIdentifier($this->packageManager)) ->withPrefix($lowercaseName) ->withAdditionalHashedIdentifier($typoScriptString) ->toString(); if ($cache) { $includeNode = $cache->require($identifier); if ($includeNode instanceof TsConfigInclude) { return $includeNode; } } $includeNode = new TsConfigInclude(); $includeNode->setName($name); if ($filename !== null) { $includeNode->setPath($filename); } $includeNode->setLineStream($tokenizer->tokenize($typoScriptString)); $this->treeFromTokenStreamBuilder->buildTree($includeNode, 'tsconfig', $tokenizer); $cache?->set($identifier, 'return unserialize(\'' . addcslashes(serialize($includeNode), '\'\\') . '\');'); return $includeNode; } }