‪TYPO3CMS  10.4
PageTsConfigParser.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 
25 
33 {
37  protected ‪$typoScriptParser;
38 
42  protected ‪$cache;
43 
45  {
46  $this->typoScriptParser = ‪$typoScriptParser;
47  $this->cache = ‪$cache;
48  }
49 
63  public function ‪parse(string $content, ‪ConditionMatcherInterface $matcher, ?‪Site $site = null): array
64  {
65  if ($site) {
66  $siteSettings = $site->getConfiguration()['settings'] ?? [];
67  if (!empty($siteSettings)) {
68  $siteSettings = ‪ArrayUtility::flattenPlain($siteSettings);
69  }
70  if (!empty($siteSettings)) {
71  // Recursive substitution of site settings (up to 10 nested levels)
72  // note: this code is more or less a duplicate of \TYPO3\CMS\Core\TypoScript\TemplateService::substituteConstants
73  for ($i = 0; $i < 10; $i++) {
74  $beforeSubstitution = $content;
75  $content = preg_replace_callback(
76  '/\\{\\$(.[^}]*)\\}/',
77  function (array $matches) use ($siteSettings): string {
78  return isset($siteSettings[$matches[1]]) && !is_array($siteSettings[$matches[1]])
79  ? (string)$siteSettings[$matches[1]] : $matches[0];
80  },
81  $content
82  );
83  if ($beforeSubstitution === $content) {
84  break;
85  }
86  }
87  }
88  }
89 
90  $hashOfContent = md5('PAGES:' . $content);
91  $cachedContent = $this->cache->get($hashOfContent);
92  // Something about this content has been cached before, lets verify the matchings, if they also apply
93  if (is_array($cachedContent) && is_array($cachedContent[0])) {
94  // Cache entry found, see if the "matching" section matches with the matcher
95  $storedData = $cachedContent[0];
96  $storedMD5 = $cachedContent[1];
97  $storedData['match'] = $this->‪matching($storedData['sections'] ?? [], $matcher);
98  $hashOfDataWithMatches = md5(json_encode($storedData));
99  // The matches are the same, so nothing to do here
100  if ($hashOfDataWithMatches === $storedMD5) {
101  $result = $storedData['TSconfig'];
102  } else {
103  // Create a hash out of the content-hash PLUS the matching information and try again
104  $shash = md5($hashOfDataWithMatches . $hashOfContent);
105  $storedData = $this->cache->get($shash);
106  if (is_array($storedData)) {
107  $result = $storedData['TSconfig'];
108  } else {
109  // Create a new content with the matcher, and cache it as a new entry
110  $parsedAndMatchedData = $this->‪parseAndMatch($content, $matcher);
111  // Now store the full data from the parser (with matches)
112  $this->cache->set($shash, $parsedAndMatchedData, ['pageTSconfig'], 0);
113  $result = $parsedAndMatchedData['TSconfig'];
114  }
115  }
116  return $result;
117  }
118 
119  // Nothing found in cache for this content string, let's do everything.
120  $parsedAndMatchedData = $this->‪parseAndMatch($content, $matcher);
121  // ALL parts, including the matching part is cached.
122  $md5 = md5(json_encode($parsedAndMatchedData));
123  $this->cache->set($hashOfContent, [$parsedAndMatchedData, $md5], ['pageTSconfig'], 0);
124  return $parsedAndMatchedData['TSconfig'];
125  }
126 
134  protected function ‪parseAndMatch(string $content, ConditionMatcherInterface $matcher): array
135  {
136  $this->typoScriptParser->parse($content, $matcher);
137  return [
138  'TSconfig' => $this->typoScriptParser->setup,
139  'sections' => $this->typoScriptParser->sections,
140  'match' => $this->typoScriptParser->sectionsMatch
141  ];
142  }
143 
151  protected function ‪matching(array $sectionsToMatch, ConditionMatcherInterface $matcher): array
152  {
153  $matches = [];
154  foreach ($sectionsToMatch ?? [] as $key => $pre) {
155  if ($matcher->match($pre)) {
156  $matches[$key] = $pre;
157  }
158  }
159  return $matches;
160  }
161 }
‪TYPO3\CMS\Core\Configuration\Parser\PageTsConfigParser\parse
‪array parse(string $content, ConditionMatcherInterface $matcher, ?Site $site=null)
Definition: PageTsConfigParser.php:61
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser
Definition: TypoScriptParser.php:37
‪TYPO3\CMS\Core\Configuration\Parser\PageTsConfigParser\$typoScriptParser
‪TypoScriptParser $typoScriptParser
Definition: PageTsConfigParser.php:36
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:40
‪TYPO3\CMS\Core\Configuration\Parser\PageTsConfigParser\$cache
‪FrontendInterface $cache
Definition: PageTsConfigParser.php:40
‪TYPO3\CMS\Core\Configuration\Parser\PageTsConfigParser\matching
‪array matching(array $sectionsToMatch, ConditionMatcherInterface $matcher)
Definition: PageTsConfigParser.php:149
‪TYPO3\CMS\Core\Utility\ArrayUtility\flattenPlain
‪static array flattenPlain(array $array)
Definition: ArrayUtility.php:515
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\ConditionMatcherInterface
Definition: ConditionMatcherInterface.php:24
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\ConditionMatcherInterface\match
‪bool match($expression)
‪TYPO3\CMS\Core\Configuration\Parser\PageTsConfigParser\parseAndMatch
‪array parseAndMatch(string $content, ConditionMatcherInterface $matcher)
Definition: PageTsConfigParser.php:132
‪TYPO3\CMS\Core\Configuration\Parser\PageTsConfigParser
Definition: PageTsConfigParser.php:33
‪TYPO3\CMS\Core\Configuration\Parser\PageTsConfigParser\__construct
‪__construct(TypoScriptParser $typoScriptParser, FrontendInterface $cache)
Definition: PageTsConfigParser.php:42
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪TYPO3\CMS\Core\Configuration\Parser
Definition: PageTsConfigParser.php:18