‪TYPO3CMS  ‪main
SysTemplateTreeBuilder.php
Go to the documentation of this file.
1 <?php
2 
3 declare(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 
19 
26 use TYPO3\CMS\Core\Package\PackageManager;
45 
74 {
81  private array ‪$includedSysTemplateUids = [];
82 
84  private string ‪$type;
85 
87  private ?‪PhpFrontend ‪$cache = null;
88 
89  private bool ‪$enableStaticMagicIncludes = false;
90 
91  public function ‪__construct(
92  private readonly ‪ConnectionPool $connectionPool,
93  private readonly PackageManager $packageManager,
94  private readonly ‪Context $context,
95  private readonly ‪TreeFromLineStreamBuilder $treeFromTokenStreamBuilder,
96  private readonly ‪SetRegistry $setRegistry,
97  ) {}
98 
103  string ‪$type,
104  array $sysTemplateRows,
106  ?‪SiteInterface $site = null,
108  ): ‪RootInclude {
109  if (!in_array(‪$type, ['constants', 'setup'], true)) {
110  throw new \RuntimeException('type must be either constants or setup', 1653737656);
111  }
112  $this->tokenizer = ‪$tokenizer;
113  $this->cache = ‪$cache;
114  $this->type = ‪$type;
115  $this->includedSysTemplateUids = [];
116 
117  $rootNode = new ‪RootInclude();
118 
119  $siteIsTypoScriptRoot = $site instanceof ‪Site ? $site->‪isTypoScriptRoot() : false;
120  if ($siteIsTypoScriptRoot) {
121  $this->enableStaticMagicIncludes = false;
122  $cacheIdentifier = 'site-template-' . $this->type . '-' . $site->getIdentifier();
123  $includeNode = $this->cache?->require($cacheIdentifier) ?: null;
124  $includeNode ??= $this->‪createSiteTemplateInclude($site, $cacheIdentifier);
125  $rootNode->addChild($includeNode);
126  }
127 
128  if (empty($sysTemplateRows)) {
129  return $rootNode;
130  }
131 
132  $this->enableStaticMagicIncludes = true;
133  // Convenience code: Usually, at least one sys_template records needs to have 'clear' set. This resets
134  // the AST and triggers inclusion of "globals" TypoScript. When integrators missed to set the clear flags,
135  // important globals TypoScript is not loaded, leading to pretty hard to find issues in Frontend
136  // rendering. Since the details of the 'clear' flags are rather complex anyway, this code scans the given
137  // sys_template records if the flag is set somewhere and if not, actively sets it dynamically for the
138  // first templates. As a result, integrators do not need to think about the 'clear' flags at all for
139  // simple instances, it 'just works'.
140  $atLeastOneSysTemplateRowHasClearFlag = $siteIsTypoScriptRoot;
141  if (!$atLeastOneSysTemplateRowHasClearFlag) {
142  foreach ($sysTemplateRows as $sysTemplateRow) {
143  if (($this->type === 'constants' && $sysTemplateRow['clear'] & 1) || ($this->type === 'setup' && $sysTemplateRow['clear'] & 2)) {
144  $atLeastOneSysTemplateRowHasClearFlag = true;
145  break;
146  }
147  }
148  $firstRow = reset($sysTemplateRows);
149  $firstRow['clear'] = $this->type === 'constants' ? 1 : 2;
150  $sysTemplateRows[array_key_first($sysTemplateRows)] = $firstRow;
151  }
152 
153  foreach ($sysTemplateRows as $sysTemplateRow) {
154  $cacheIdentifier = 'sys-template-' . $this->type . '-' . $this->‪getSysTemplateRowIdentifier($sysTemplateRow, $site);
155  if ($this->cache) {
156  // Get from cache if possible
157  $includeNode = $this->cache->require($cacheIdentifier);
158  if ($includeNode) {
159  $rootNode->addChild($includeNode);
160  continue;
161  }
162  }
163  $includeNode = new ‪SysTemplateInclude();
164  $name = '[sys_template:' . $sysTemplateRow['uid'] . '] ' . $sysTemplateRow['title'];
165  $includeNode->setName($name);
166  $includeNode->setPid((int)$sysTemplateRow['pid']);
167  if ($this->type === 'constants') {
168  $includeNode->setLineStream($this->tokenizer->tokenize($sysTemplateRow['constants'] ?? ''));
169  } else {
170  $includeNode->setLineStream($this->tokenizer->tokenize($sysTemplateRow['config'] ?? ''));
171  }
172  if ($sysTemplateRow['root']) {
173  $includeNode->setRoot(true);
174  }
175  $clear = $sysTemplateRow['clear'];
176  if (($this->type === 'constants' && $clear & 1) || ($this->type === 'setup' && $clear & 2)) {
177  $includeNode->setClear(true);
178  }
179  $this->‪handleSysTemplateRecordInclude($includeNode, $sysTemplateRow, $site);
180  $this->treeFromTokenStreamBuilder->buildTree($includeNode, $this->type, $this->tokenizer);
181  $this->cache?->set($cacheIdentifier, $this->‪prepareNodeForCache($includeNode));
182  $rootNode->addChild($includeNode);
183  }
184 
185  return $rootNode;
186  }
187 
189  ‪Site $site,
190  string $cacheIdentifier
192  $includeNode = new ‪SiteTemplateInclude();
193  $includeNode->setRoot(true);
194  $includeNode->setClear(true);
195 
196  $this->‪addScopedStaticsFromGlobals($includeNode, 'siteSets');
197  $this->‪addContentRenderingFromGlobals($includeNode, 'TYPO3_CONF_VARS defaultContentRendering');
198 
199  $sets = $this->setRegistry->getSets(...$site->getSets());
200  if (count($sets) > 0) {
201  $includeSetInclude = new ‪IncludeStaticFileFileInclude();
202  $includeSetInclude->setName('site:' . $site->‪getIdentifier() . ':sets');
203  $includeSetInclude->setPath('site:' . $site->‪getIdentifier() . '/');
204  foreach ($sets as $set) {
205  $this->‪handleSetInclude($includeSetInclude, rtrim($set->typoscript, '/') . '/', 'set:' . $set->name);
206  }
207  $includeNode->addChild($includeSetInclude);
208  }
209 
210  if ($this->type === 'constants') {
211  $this->‪addDefaultTypoScriptConstantsFromSite($includeNode, $site);
212  }
213 
214  $siteTypoScript = $site->‪getTypoScript();
215  $content = $this->type === 'constants' ? $siteTypoScript?->constants : $siteTypoScript?->setup;
216  if ($content !== null) {
217  $includeNode->setLineStream($this->tokenizer->tokenize($content));
218  $this->treeFromTokenStreamBuilder->buildTree($includeNode, $this->type, $this->tokenizer, false);
219  }
220 
221  $includeNode->setName(sprintf(
222  '[site:%s%s] %s',
223  $site->‪getIdentifier(),
224  $content === null ? '' : '/' . $this->type . '.typoscript',
225  $site->‪getConfiguration()['websiteTitle'] ?? ''
226  ));
227 
228  $this->cache?->set($cacheIdentifier, $this->‪prepareNodeForCache($includeNode));
229 
230  return $includeNode;
231  }
232 
233  private function ‪handleSetInclude(‪IncludeInterface $parentNode, string $path, string $label): void
234  {
235  $path = GeneralUtility::getFileAbsFileName($path);
236 
237  // '/.../my_extension/Configuration/TypoScript/MyStaticInclude/include_static_file.txt'
238  $includeStaticFileFileIncludePath = $path . 'include_static_file.txt';
239  if (file_exists($path . 'include_static_file.txt')) {
240  $includeStaticFileFileInclude = new ‪IncludeStaticFileFileInclude();
241  //$name = 'EXT:' . $extensionKey . '/' . $pathSegmentWithAppendedSlash . 'include_static_file.txt';
242  //$includeStaticFileFileInclude->setName($name);
243  $includeStaticFileFileInclude->setName($label . ':include_static_file.txt');
244  $includeStaticFileFileInclude->setPath($path . 'include_static_file.txt');
245  $parentNode->‪addChild($includeStaticFileFileInclude);
246  $includeStaticFileFileIncludeContent = (string)file_get_contents($includeStaticFileFileIncludePath);
247  // @todo: There is no array_unique() for DB based include_static_file content?!
248  $includeStaticFileFileIncludeArray = array_unique(‪GeneralUtility::trimExplode(',', $includeStaticFileFileIncludeContent, true));
249  foreach ($includeStaticFileFileIncludeArray as $includeStaticFileFileIncludeString) {
250  $this->‪handleSingleIncludeStaticFile($includeStaticFileFileInclude, $includeStaticFileFileIncludeString);
251  }
252  }
253 
254  $fileName = $path . $this->type . '.typoscript';
255  if (file_exists($fileName)) {
256  $fileContent = file_get_contents($fileName);
257  $fileNode = new ‪FileInclude();
258  $fileNode->setName($label . ':' . $this->type . '.typoscript');
259  $fileNode->setPath($fileName);
260  $fileNode->setLineStream($this->tokenizer->tokenize($fileContent));
261  $this->treeFromTokenStreamBuilder->buildTree($fileNode, $this->type, $this->tokenizer, false);
262  $parentNode->‪addChild($fileNode);
263  }
264  }
265 
269  private function ‪handleSysTemplateRecordInclude(‪IncludeInterface $parentNode, array $row, ?‪SiteInterface $site): void
270  {
271  $this->includedSysTemplateUids[] = (int)$row['uid'];
272 
273  $isRoot = (bool)$row['root'];
274  $clearConstants = (int)$row['clear'] & 1;
275  $clearSetup = (int)$row['clear'] & 2;
276  $staticFileMode = (int)($row['static_file_mode']);
277  $includeStaticAfterBasedOn = (bool)$row['includeStaticAfterBasedOn'];
278 
279  if ($this->type === 'constants' && $clearConstants) {
280  $this->‪addDefaultTypoScriptFromGlobals($parentNode);
281  $this->‪addDefaultTypoScriptConstantsFromSite($parentNode, $site);
282  }
283  if ($this->type === 'setup' && $clearSetup) {
284  $this->‪addDefaultTypoScriptFromGlobals($parentNode);
285  }
286  if ($staticFileMode === 3 && $isRoot) {
287  $this->‪addExtensionStatics($parentNode);
288  }
289  if (!$includeStaticAfterBasedOn) {
290  $this->‪handleIncludeStaticFileArray($parentNode, (string)$row['include_static_file']);
291  }
292  if (!empty($row['basedOn'])) {
293  $this->‪handleIncludeBasedOnTemplates($parentNode, (string)$row['basedOn'], $site);
294  }
295  if ($includeStaticAfterBasedOn) {
296  $this->‪handleIncludeStaticFileArray($parentNode, (string)$row['include_static_file']);
297  }
298  if ($staticFileMode === 1 || ($staticFileMode === 0 && $isRoot)) {
299  $this->‪addExtensionStatics($parentNode);
300  }
301  }
302 
316  private function ‪handleIncludeStaticFileArray(‪IncludeInterface $parentNode, string $includeStaticFileString): void
317  {
318  $includeStaticFileIncludeArray = ‪GeneralUtility::trimExplode(',', $includeStaticFileString, true);
319  foreach ($includeStaticFileIncludeArray as $includeStaticFile) {
320  $cacheIdentifier = preg_replace('/[^[:alnum:]]/u', '-', mb_strtolower($includeStaticFile)) . '-' . ‪$this->type;
321  if ($this->cache) {
322  $node = $this->cache->require($cacheIdentifier);
323  if ($node) {
324  $parentNode->‪addChild($node);
325  continue;
326  }
327  }
329  $node->setName($includeStaticFile);
330  $this->‪handleSingleIncludeStaticFile($node, $includeStaticFile);
331  $this->cache?->set($cacheIdentifier, $this->‪prepareNodeForCache($node));
332  $parentNode->‪addChild($node);
333  }
334  }
335 
341  private function ‪handleIncludeBasedOnTemplates(‪IncludeInterface $parentNode, string $basedOnList, ?‪SiteInterface $site): void
342  {
343  $basedOnTemplateUids = ‪GeneralUtility::intExplode(',', $basedOnList, true);
344  // Filter uids that have been handled already.
345  $basedOnTemplateUids = array_diff($basedOnTemplateUids, $this->includedSysTemplateUids);
346  if (empty($basedOnTemplateUids)) {
347  return;
348  }
349 
350  $basedOnTemplateRows = $this->‪getBasedOnSysTemplateRowsFromDatabase($basedOnTemplateUids);
351 
352  foreach ($basedOnTemplateUids as $basedOnTemplateUid) {
353  if (is_array($basedOnTemplateRows[$basedOnTemplateUid] ?? false)) {
354  $sysTemplateRow = $basedOnTemplateRows[$basedOnTemplateUid];
355  $this->includedSysTemplateUids[] = (int)$sysTemplateRow['uid'];
356  $includeNode = new ‪SysTemplateInclude();
357  $name = '[sys_template:' . $sysTemplateRow['uid'] . '] ' . $sysTemplateRow['title'];
358  $includeNode->setName($name);
359  $includeNode->setPid((int)$sysTemplateRow['pid']);
360  if ($this->type === 'constants') {
361  $includeNode->setLineStream($this->tokenizer->tokenize($sysTemplateRow['constants'] ?? ''));
362  } else {
363  $includeNode->setLineStream($this->tokenizer->tokenize($sysTemplateRow['config'] ?? ''));
364  }
365  $this->treeFromTokenStreamBuilder->buildTree($includeNode, $this->type, $this->tokenizer);
366  if ($sysTemplateRow['root']) {
367  $includeNode->setRoot(true);
368  }
369  $clear = $sysTemplateRow['clear'];
370  if (($this->type === 'constants' && $clear & 1)
371  || ($this->type === 'setup' && $clear & 2)
372  ) {
373  $includeNode->setClear(true);
374  }
375  $parentNode->‪addChild($includeNode);
376  $this->‪handleSysTemplateRecordInclude($includeNode, $sysTemplateRow, $site);
377  }
378  }
379  }
380 
389  private function ‪handleSingleIncludeStaticFile(‪IncludeInterface $parentNode, $includeStaticFileString): void
390  {
391  if (!‪PathUtility::isExtensionPath($includeStaticFileString)) {
392  // Must start with 'EXT:'
393  throw new \RuntimeException(
394  'Single include_static_file does not start with "EXT:": ' . $includeStaticFileString,
395  1651137904
396  );
397  }
398 
399  // Cut off 'EXT:'
400  $includeStaticFileWithoutExt = substr($includeStaticFileString, 4);
401  $includeStaticFileExtKeyAndPath = ‪GeneralUtility::trimExplode('/', $includeStaticFileWithoutExt, true, 2);
402  if (empty($includeStaticFileExtKeyAndPath[0]) || empty($includeStaticFileExtKeyAndPath[1])) {
403  throw new \RuntimeException(
404  'Syntax of static includes is "EXT:extension_key/Path". Usually enforced as such by ExtensionManagementUtility::addStaticFile',
405  1651138603
406  );
407  }
408  $extensionKey = $includeStaticFileExtKeyAndPath[0];
409  if (!‪ExtensionManagementUtility::isLoaded($extensionKey)) {
410  return;
411  }
412  // example: '/.../my_extension/Configuration/TypoScript/MyStaticInclude/'
413  $pathSegmentWithAppendedSlash = rtrim($includeStaticFileExtKeyAndPath[1]) . '/';
414  $path = ‪ExtensionManagementUtility::extPath($extensionKey, $pathSegmentWithAppendedSlash);
415 
416  // '/.../my_extension/Configuration/TypoScript/MyStaticInclude/include_static_file.txt'
417  $includeStaticFileFileIncludePath = $path . 'include_static_file.txt';
418  if (file_exists($path . 'include_static_file.txt')) {
419  $includeStaticFileFileInclude = new ‪IncludeStaticFileFileInclude();
420  $name = 'EXT:' . $extensionKey . '/' . $pathSegmentWithAppendedSlash . 'include_static_file.txt';
421  $includeStaticFileFileInclude->setName($name);
422  $includeStaticFileFileInclude->setPath($includeStaticFileString);
423  $parentNode->‪addChild($includeStaticFileFileInclude);
424  $includeStaticFileFileIncludeContent = (string)file_get_contents($includeStaticFileFileIncludePath);
425  // @todo: There is no array_unique() for DB based include_static_file content?!
426  $includeStaticFileFileIncludeArray = array_unique(‪GeneralUtility::trimExplode(',', $includeStaticFileFileIncludeContent, true));
427  foreach ($includeStaticFileFileIncludeArray as $includeStaticFileFileIncludeString) {
428  $this->‪handleSingleIncludeStaticFile($includeStaticFileFileInclude, $includeStaticFileFileIncludeString);
429  }
430  }
431 
432  $extensions = ['.typoscript', '.ts', '.txt'];
433  foreach ($extensions as $extension) {
434  // '/.../my_extension/Configuration/TypoScript/MyStaticInclude/[constants|setup]' plus one of the allowed extensions like '.typoscript'
435  $fileName = $path . $this->type . $extension;
436  if (file_exists($fileName)) {
437  $fileContent = file_get_contents($fileName);
438  $fileNode = new ‪FileInclude();
439  $name = 'EXT:' . $extensionKey . '/' . $pathSegmentWithAppendedSlash . $this->type . $extension;
440  $fileNode->setName($name);
441  $fileNode->setPath($name);
442  $fileNode->setLineStream($this->tokenizer->tokenize($fileContent));
443  $this->treeFromTokenStreamBuilder->buildTree($fileNode, $this->type, $this->tokenizer);
444  $parentNode->‪addChild($fileNode);
445  }
446  }
447 
448  if ($this->enableStaticMagicIncludes) {
449  $extensionKeyWithoutUnderscores = str_replace('_', '', $extensionKey);
450  $this->‪addStaticMagicFromGlobals($parentNode, $extensionKeyWithoutUnderscores . '/' . $pathSegmentWithAppendedSlash);
451  }
452  }
453 
458  private function ‪addExtensionStatics(‪IncludeInterface $parentNode): void
459  {
460  foreach ($this->packageManager->getActivePackages() as $package) {
461  $extensionKey = $package->getPackageKey();
462  $extensionKeyWithoutUnderscores = str_replace('_', '', $extensionKey);
463  $file = $package->getPackagePath() . 'ext_typoscript_' . $this->type . '.typoscript';
464  if (file_exists($file)) {
465  ‪$identifier = preg_replace('/[^[:alnum:]]/u', '-', 'ext-' . $extensionKey . '-ext-typoscript-' . $this->type . '-typoscript');
466  if ($this->cache) {
467  $node = $this->cache->require(‪$identifier);
468  if ($node) {
469  $parentNode->‪addChild($node);
470  continue;
471  }
472  }
473  $fileContent = file_get_contents($file);
474  $this->‪addStaticMagicFromGlobals($parentNode, $extensionKeyWithoutUnderscores);
475  $node = new ‪ExtensionStaticInclude();
476  $node->setName('EXT:' . $extensionKey . '/ext_typoscript_' . $this->type . '.typoscript');
477  $node->setPath('EXT:' . $extensionKey . '/ext_typoscript_' . $this->type . '.typoscript');
478  $node->setLineStream($this->tokenizer->tokenize($fileContent));
479  $this->treeFromTokenStreamBuilder->buildTree($node, $this->type, $this->tokenizer);
480  $this->cache?->set(‪$identifier, $this->‪prepareNodeForCache($node));
481  $parentNode->‪addChild($node);
482  }
483  }
484  }
485 
490  private function ‪addDefaultTypoScriptFromGlobals(‪IncludeInterface $parentConstantNode): void
491  {
492  $defaultTypoScriptConstants = ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . ‪$this->type] ?? '';
493  if (!empty($defaultTypoScriptConstants)) {
494  $cacheIdentifier = 'globals-defaulttyposcript-' . $this->type . '-' . hash('xxh3', $defaultTypoScriptConstants);
495  if ($this->cache) {
496  $node = $this->cache->require($cacheIdentifier);
497  if ($node) {
498  $parentConstantNode->‪addChild($node);
499  return;
500  }
501  }
502  $node = new ‪DefaultTypoScriptInclude();
503  $node->setName('TYPO3_CONF_VARS[\'FE\'][\'defaultTypoScript_' . $this->type . '\']');
504  $node->setLineStream($this->tokenizer->tokenize($defaultTypoScriptConstants));
505  $this->treeFromTokenStreamBuilder->buildTree($node, $this->type, $this->tokenizer);
506  $this->cache?->set($cacheIdentifier, $this->prepareNodeForCache($node));
507  $parentConstantNode->addChild($node);
508  }
509  }
510 
514  private function addDefaultTypoScriptConstantsFromSite(IncludeInterface $parentConstantNode, ?SiteInterface $site): void
515  {
516  if (!$site instanceof Site) {
517  return;
518  }
519  $siteConstants = '';
520  $siteSettings = $site->getSettings();
521  if ($siteSettings->isEmpty()) {
522  return;
523  }
524  $cacheIdentifier = 'site-constants-' . hash('xxh3', json_encode($siteSettings, JSON_THROW_ON_ERROR));
525  if ($this->cache) {
526  $node = $this->cache->require($cacheIdentifier);
527  if ($node) {
528  $parentConstantNode->addChild($node);
529  return;
530  }
531  }
532  $siteSettings = $siteSettings->getAllFlat();
533  foreach ($siteSettings as $nodeIdentifier => $value) {
534  $siteConstants .= $nodeIdentifier . ' = ' . $value . LF;
535  }
536  $node = new SiteInclude();
537  $node->setName('‪Site constants settings of site "' . $site->getIdentifier() . '"');
538  $node->setLineStream($this->tokenizer->tokenize($siteConstants));
539  $this->cache?->set($cacheIdentifier, $this->prepareNodeForCache($node));
540  $parentConstantNode->addChild($node);
541  }
542 
543  private function addScopedStaticsFromGlobals(IncludeInterface $parentNode, string $identifier): void
544  {
545  // defaultTypoScript_constants.' or defaultTypoScript_setup.'
546  $source = $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $this->type . '.'][$identifier] ?? null;
547  if (!empty($source)) {
548  $node = new DefaultTypoScriptMagicKeyInclude();
549  $node->setName('TYPO3_CONF_VARS globals_defaultTypoScript_' . $this->type . '.' . $identifier);
550  $node->setLineStream($this->tokenizer->tokenize($source));
551  $this->treeFromTokenStreamBuilder->buildTree($node, $this->type, $this->tokenizer);
552  $parentNode->addChild($node);
553  }
554  }
555 
556  private function addContentRenderingFromGlobals(IncludeInterface $parentNode, string $name): void
557  {
558  $source = $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $this->type . '.']['defaultContentRendering'] ?? null;
559  if (!empty($source)) {
560  $node = new DefaultTypoScriptMagicKeyInclude();
561  $node->setName($name);
562  $node->setLineStream($this->tokenizer->tokenize($source));
563  $this->treeFromTokenStreamBuilder->buildTree($node, $this->type, $this->tokenizer);
564  $parentNode->addChild($node);
565  }
566  }
567 
572  private function addStaticMagicFromGlobals(IncludeInterface $parentNode, string $identifier): void
573  {
574  $this->addScopedStaticsFromGlobals($parentNode, $identifier);
575  // If this is a template of type "default content rendering", see if other extensions have added their TypoScript that should be included.
576  if (in_array($identifier, $GLOBALS['TYPO3_CONF_VARS']['FE']['contentRenderingTemplates'], true)) {
577  $this->addContentRenderingFromGlobals($parentNode, 'TYPO3_CONF_VARS defaultContentRendering ' . $this->type . ' for ' . $identifier);
578  }
579  }
580 
587  private function getBasedOnSysTemplateRowsFromDatabase(array $basedOnTemplateUids): array
588  {
589  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_template');
590  $queryBuilder->setRestrictions($this->getSysTemplateQueryRestrictionContainer());
591  $basedOnTemplateRows = $queryBuilder
592  ->select('*')
593  ->from('sys_template')
594  ->where(
595  $queryBuilder->expr()->in(
596  'uid',
597  $queryBuilder->createNamedParameter($basedOnTemplateUids, Connection::PARAM_INT_ARRAY)
598  )
599  )
600  ->executeQuery()
601  ->fetchAllAssociative();
602  return array_combine(array_column($basedOnTemplateRows, 'uid'), $basedOnTemplateRows);
603  }
604 
619  private function getSysTemplateRowIdentifier(array $sysTemplateRow, ?SiteInterface $site): string
620  {
621  $siteIdentifier = 'dummy';
622  if ($this->type === 'constants' && ((int)$sysTemplateRow['clear'] & 1) && $site !== null) {
623  $siteIdentifier = $site->getIdentifier();
624  }
625  $cacheRelevantSysTemplateRowValues = [
626  'root' => (int)$sysTemplateRow['root'],
627  'clear' => (int)$sysTemplateRow['clear'],
628  'include_static_file' => (string)$sysTemplateRow['include_static_file'],
629  'constants' => (string)$sysTemplateRow['constants'],
630  'config' => (string)$sysTemplateRow['config'],
631  'basedOn' => (string)$sysTemplateRow['basedOn'],
632  'includeStaticAfterBasedOn' => (int)$sysTemplateRow['includeStaticAfterBasedOn'],
633  'static_file_mode' => (int)$sysTemplateRow['static_file_mode'],
634  'siteIdentifier' => $siteIdentifier,
635  ];
636  return hash('xxh3', json_encode($cacheRelevantSysTemplateRowValues, JSON_THROW_ON_ERROR));
637  }
638 
639  private function prepareNodeForCache(IncludeInterface $node): string
640  {
641  return 'return unserialize(\'' . addcslashes(serialize($node), '\'\\') . '\');';
642  }
643 
649  {
650  $restrictionContainer = GeneralUtility::makeInstance(DefaultRestrictionContainer::class);
651  if ($this->context->getPropertyFromAspect('visibility', 'includeHiddenContent', false)) {
652  $restrictionContainer->removeByType(HiddenRestriction::class);
653  }
654  return $restrictionContainer;
655  }
656 }
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\IncludeStaticFileFileInclude
Definition: IncludeStaticFileFileInclude.php:26
‪TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction
Definition: HiddenRestriction.php:27
‪TYPO3\CMS\Core\Site\Entity\SiteInterface
Definition: SiteInterface.php:26
‪TYPO3\CMS\Core\Utility\PathUtility\isExtensionPath
‪static isExtensionPath(string $path)
Definition: PathUtility.php:117
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:27
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\addScopedStaticsFromGlobals
‪addScopedStaticsFromGlobals(IncludeInterface $parentNode, string $identifier)
Definition: SysTemplateTreeBuilder.php:543
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\$cache
‪PhpFrontend $cache
Definition: SysTemplateTreeBuilder.php:87
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\$type
‪string $type
Definition: SysTemplateTreeBuilder.php:84
‪TYPO3\CMS\Core\TypoScript\IncludeTree
‪TYPO3\CMS\Core\Cache\Frontend\PhpFrontend
Definition: PhpFrontend.php:25
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\SiteTemplateInclude
Definition: SiteTemplateInclude.php:27
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\ExtensionStaticInclude
Definition: ExtensionStaticInclude.php:26
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\IncludeInterface\addChild
‪addChild(IncludeInterface $node)
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\addExtensionStatics
‪addExtensionStatics(IncludeInterface $parentNode)
Definition: SysTemplateTreeBuilder.php:458
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\prepareNodeForCache
‪prepareNodeForCache(IncludeInterface $node)
Definition: SysTemplateTreeBuilder.php:639
‪TYPO3\CMS\Core\TypoScript\IncludeTree\TreeFromLineStreamBuilder
Definition: TreeFromLineStreamBuilder.php:58
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\handleSysTemplateRecordInclude
‪handleSysTemplateRecordInclude(IncludeInterface $parentNode, array $row, ?SiteInterface $site)
Definition: SysTemplateTreeBuilder.php:269
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\createSiteTemplateInclude
‪createSiteTemplateInclude(Site $site, string $cacheIdentifier)
Definition: SysTemplateTreeBuilder.php:188
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\addDefaultTypoScriptFromGlobals
‪addDefaultTypoScriptFromGlobals(IncludeInterface $parentConstantNode)
Definition: SysTemplateTreeBuilder.php:490
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\addContentRenderingFromGlobals
‪addContentRenderingFromGlobals(IncludeInterface $parentNode, string $name)
Definition: SysTemplateTreeBuilder.php:556
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static isLoaded(string $key)
Definition: ExtensionManagementUtility.php:55
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:42
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\handleIncludeBasedOnTemplates
‪handleIncludeBasedOnTemplates(IncludeInterface $parentNode, string $basedOnList, ?SiteInterface $site)
Definition: SysTemplateTreeBuilder.php:341
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:32
‪TYPO3\CMS\Core\Site\Set\SetRegistry
Definition: SetRegistry.php:30
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static extPath(string $key, string $script='')
Definition: ExtensionManagementUtility.php:82
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\SiteInclude
Definition: SiteInclude.php:25
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\IncludeInterface
Definition: IncludeInterface.php:39
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\handleIncludeStaticFileArray
‪handleIncludeStaticFileArray(IncludeInterface $parentNode, string $includeStaticFileString)
Definition: SysTemplateTreeBuilder.php:316
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\FileInclude
Definition: FileInclude.php:28
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\handleSingleIncludeStaticFile
‪handleSingleIncludeStaticFile(IncludeInterface $parentNode, $includeStaticFileString)
Definition: SysTemplateTreeBuilder.php:389
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\getTreeBySysTemplateRowsAndSite
‪getTreeBySysTemplateRowsAndSite(string $type, array $sysTemplateRows, TokenizerInterface $tokenizer, ?SiteInterface $site=null, PhpFrontend $cache=null)
Definition: SysTemplateTreeBuilder.php:102
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\IncludeStaticFileDatabaseInclude
Definition: IncludeStaticFileDatabaseInclude.php:27
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\getSysTemplateRowIdentifier
‪getSysTemplateRowIdentifier(array $sysTemplateRow, ?SiteInterface $site)
Definition: SysTemplateTreeBuilder.php:619
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\$tokenizer
‪TokenizerInterface $tokenizer
Definition: SysTemplateTreeBuilder.php:86
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\DefaultTypoScriptMagicKeyInclude
Definition: DefaultTypoScriptMagicKeyInclude.php:26
‪TYPO3\CMS\Core\Site\Entity\Site\getTypoScript
‪getTypoScript()
Definition: Site.php:334
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\addDefaultTypoScriptConstantsFromSite
‪addDefaultTypoScriptConstantsFromSite(IncludeInterface $parentConstantNode, ?SiteInterface $site)
Definition: SysTemplateTreeBuilder.php:514
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\handleSetInclude
‪handleSetInclude(IncludeInterface $parentNode, string $path, string $label)
Definition: SysTemplateTreeBuilder.php:233
‪TYPO3\CMS\Core\Site\Entity\Site\isTypoScriptRoot
‪isTypoScriptRoot()
Definition: Site.php:329
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\$includedSysTemplateUids
‪array $includedSysTemplateUids
Definition: SysTemplateTreeBuilder.php:81
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\$enableStaticMagicIncludes
‪bool $enableStaticMagicIncludes
Definition: SysTemplateTreeBuilder.php:89
‪TYPO3\CMS\Core\Site\Entity\Site\getConfiguration
‪getConfiguration()
Definition: Site.php:316
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\getBasedOnSysTemplateRowsFromDatabase
‪getBasedOnSysTemplateRowsFromDatabase(array $basedOnTemplateUids)
Definition: SysTemplateTreeBuilder.php:587
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\__construct
‪__construct(private readonly ConnectionPool $connectionPool, private readonly PackageManager $packageManager, private readonly Context $context, private readonly TreeFromLineStreamBuilder $treeFromTokenStreamBuilder, private readonly SetRegistry $setRegistry,)
Definition: SysTemplateTreeBuilder.php:91
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\DefaultTypoScriptInclude
Definition: DefaultTypoScriptInclude.php:26
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\RootInclude
Definition: RootInclude.php:27
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\TypoScript\Tokenizer\TokenizerInterface
Definition: TokenizerInterface.php:40
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\getSysTemplateQueryRestrictionContainer
‪getSysTemplateQueryRestrictionContainer()
Definition: SysTemplateTreeBuilder.php:648
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static list< int > intExplode(string $delimiter, string $string, bool $removeEmptyValues=false)
Definition: GeneralUtility.php:756
‪TYPO3\CMS\Core\TypoScript\IncludeTree\IncludeNode\SysTemplateInclude
Definition: SysTemplateInclude.php:26
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder
Definition: SysTemplateTreeBuilder.php:74
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateTreeBuilder\addStaticMagicFromGlobals
‪addStaticMagicFromGlobals(IncludeInterface $parentNode, string $identifier)
Definition: SysTemplateTreeBuilder.php:572
‪TYPO3\CMS\Core\Site\Entity\Site\getIdentifier
‪getIdentifier()
Definition: Site.php:185
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode(string $delim, string $string, bool $removeEmptyValues=false, int $limit=0)
Definition: GeneralUtility.php:822
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Core\Database\Query\Restriction\DefaultRestrictionContainer
Definition: DefaultRestrictionContainer.php:24