1<?php 2 3declare(strict_types=1); 4 5/* 6 * This file is part of the TYPO3 CMS project. 7 * 8 * It is free software; you can redistribute it and/or modify it under 9 * the terms of the GNU General Public License, either version 2 10 * of the License, or any later version. 11 * 12 * For the full copyright and license information, please read the 13 * LICENSE.txt file that was distributed with this source code. 14 * 15 * The TYPO3 project - inspiring people to share! 16 */ 17 18namespace TYPO3\CMS\Core\Configuration\Loader; 19 20use Psr\EventDispatcher\EventDispatcherInterface; 21use TYPO3\CMS\Core\Configuration\Event\ModifyLoadedPageTsConfigEvent; 22use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser; 23use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; 24use TYPO3\CMS\Core\Utility\GeneralUtility; 25use TYPO3\CMS\Core\Utility\PathUtility; 26 27/** 28 * Traverses a root line of a pagetree up and includes all available TSconfig settings, including default 29 * setup. Then include lines are checked, and merged together into one string, ready to be parsed. 30 * 31 * Can be used in Frontend or Backend. 32 * 33 * Have a look at the PageTsConfigParser which can then parse (and cache) this information based on the. 34 * 35 * Currently, this accumulated information of the pages is NOT cached, as it would need to be tagged with any 36 * page, also including external files. 37 */ 38class PageTsConfigLoader 39{ 40 /** 41 * @var EventDispatcherInterface 42 */ 43 protected $eventDispatcher; 44 45 public function __construct(EventDispatcherInterface $eventDispatcher) 46 { 47 $this->eventDispatcher = $eventDispatcher; 48 } 49 50 /** 51 * Main method to get all PageTSconfig from the rootline including the defaultTSconfig settings. 52 * @param array $rootLine 53 * @return string 54 */ 55 public function load(array $rootLine): string 56 { 57 // Verifying includes, and melt the inclusions together into one string 58 $tsData = $this->collect($rootLine); 59 return implode("\n[GLOBAL]\n", $tsData); 60 } 61 62 /** 63 * Same as "load()" but returns an array of all parts. Only useful in the TYPO3 Backend for inspection purposes. 64 * 65 * @param array $rootLine 66 * @return array 67 * @internal 68 */ 69 public function collect(array $rootLine): array 70 { 71 $tsData = [ 72 'default' => $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'] ?? '' 73 ]; 74 foreach ($rootLine as $page) { 75 // Can happen when the rootline is given from BE context, we skip this 76 if ((int)$page['uid'] === 0) { 77 continue; 78 } 79 if (trim($page['tsconfig_includes'] ?? '')) { 80 $includeTsConfigFileList = GeneralUtility::trimExplode(',', $page['tsconfig_includes'], true); 81 // Traversing list 82 foreach ($includeTsConfigFileList as $key => $includeTsConfigFile) { 83 if (strpos($includeTsConfigFile, 'EXT:') === 0) { 84 [$includeTsConfigFileExtensionKey, $includeTsConfigFilename] = explode( 85 '/', 86 substr($includeTsConfigFile, 4), 87 2 88 ); 89 if ((string)$includeTsConfigFileExtensionKey !== '' 90 && ExtensionManagementUtility::isLoaded($includeTsConfigFileExtensionKey) 91 && (string)$includeTsConfigFilename !== '' 92 ) { 93 $extensionPath = ExtensionManagementUtility::extPath($includeTsConfigFileExtensionKey); 94 $includeTsConfigFileAndPath = PathUtility::getCanonicalPath($extensionPath . $includeTsConfigFilename); 95 if (strpos($includeTsConfigFileAndPath, $extensionPath) === 0 && file_exists($includeTsConfigFileAndPath)) { 96 $tsData['page_' . $page['uid'] . '_includes_' . $key] = (string)file_get_contents($includeTsConfigFileAndPath); 97 } 98 } 99 } 100 } 101 } 102 $tsData['page_' . $page['uid']] = $page['TSconfig'] ?? ''; 103 } 104 105 $event = $this->eventDispatcher->dispatch(new ModifyLoadedPageTsConfigEvent($tsData, $rootLine)); 106 107 // Apply includes 108 return TypoScriptParser::checkIncludeLines_array($event->getTsConfig()); 109 } 110} 111