‪TYPO3CMS  10.4
AbstractConditionMatcher.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\Log\LoggerAwareInterface;
19 use Psr\Log\LoggerAwareTrait;
20 use Symfony\Component\ExpressionLanguage\SyntaxError;
26 
33 abstract class ‪AbstractConditionMatcher implements LoggerAwareInterface, ‪ConditionMatcherInterface
34 {
35  use LoggerAwareTrait;
36 
42  protected ‪$pageId;
43 
49  protected ‪$rootline;
50 
57  protected ‪$simulateMatchResult = false;
58 
66 
71 
76 
77  protected function ‪initializeExpressionLanguageResolver(): void
78  {
80  $this->expressionLanguageResolver = GeneralUtility::makeInstance(
81  Resolver::class,
82  'typoscript',
83  $this->expressionLanguageResolverVariables
84  );
85  }
86 
87  protected function ‪updateExpressionLanguageVariables(): void
88  {
89  // deliberately empty and not "abstract" due to backwards compatibility
90  // implement this method in derived classes
91  }
92 
98  public function ‪setPageId(‪$pageId)
99  {
100  if (is_int(‪$pageId) && ‪$pageId > 0) {
101  $this->pageId = ‪$pageId;
102  }
104  }
105 
111  public function ‪getPageId()
112  {
113  return ‪$this->pageId;
114  }
115 
121  public function ‪setRootline(array ‪$rootline)
122  {
123  if (!empty(‪$rootline)) {
124  $this->rootline = ‪$rootline;
125  }
127  }
128 
134  public function ‪getRootline()
135  {
136  return ‪$this->rootline;
137  }
138 
145  {
146  if (is_bool(‪$simulateMatchResult)) {
147  $this->simulateMatchResult = ‪$simulateMatchResult;
148  }
149  }
150 
157  {
158  $this->simulateMatchConditions = ‪$simulateMatchConditions;
159  }
160 
167  public function ‪match($expression): bool
168  {
169  // Return directly if result should be simulated:
170  if ($this->simulateMatchResult) {
172  }
173  // Return directly if matching for specific condition is simulated only:
174  if (!empty($this->simulateMatchConditions)) {
175  return in_array($expression, $this->simulateMatchConditions, true);
176  }
177  $result = false;
178  // First and last character must be square brackets:
179  if (strpos($expression, '[') === 0 && substr($expression, -1) === ']') {
180  $innerExpression = substr($expression, 1, -1);
181  $result = $this->‪evaluateExpression($innerExpression);
182  }
183  return $result;
184  }
185 
190  protected function ‪evaluateExpression(string $expression): bool
191  {
192  // The TypoScript [ELSE] condition is not known by the Symfony Expression Language
193  // and must not be evaluated. If/else logic is handled in TypoScriptParser.
194  if (strtoupper($expression) === 'ELSE') {
195  return false;
196  }
197 
198  try {
199  return $this->expressionLanguageResolver->evaluate($expression);
200  } catch (MissingTsfeException $e) {
201  // TSFE is not available in the current context (e.g. TSFE in BE context),
202  // we set all conditions false for this case.
203  return false;
204  } catch (SyntaxError $exception) {
205  $message = 'Expression could not be parsed.';
206  $this->logger->error($message, ['expression' => $expression]);
207  } catch (\Throwable $exception) {
208  // The following error handling is required to mitigate a missing type check
209  // in the Symfony Expression Language handling. In case a condition
210  // use "in" or "not in" check in combination with a non array a PHP Warning
211  // is thrown. Example: [1 in "foo"] or ["bar" in "foo,baz"]
212  // This conditions are wrong for sure, but they will break the complete installation
213  // including the backend. To mitigate the problem we do the following:
214  // 1) In FE an InvalidTypoScriptConditionException is thrown (if strictSyntax is enabled)
215  // 2) In FE silent catch this error and log it (if strictSyntax is disabled)
216  // 3) In BE silent catch this error and log it, but never break the backend.
217  $this->logger->error($exception->getMessage(), [
218  'expression' => $expression,
219  'exception' => $exception
220  ]);
221  if (TYPO3_MODE === 'FE'
222  && $exception instanceof Exception
223  && strpos($exception->getMessage(), 'in_array() expects parameter 2 to be array') !== false
224  ) {
225  throw new InvalidTypoScriptConditionException('Invalid expression in condition: [' . $expression . ']', 1536950931);
226  }
227  }
228  return false;
229  }
230 }
‪TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException
Definition: InvalidTypoScriptConditionException.php:26
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\setRootline
‪setRootline(array $rootline)
Definition: AbstractConditionMatcher.php:115
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\match
‪bool match($expression)
Definition: AbstractConditionMatcher.php:161
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\$simulateMatchResult
‪bool $simulateMatchResult
Definition: AbstractConditionMatcher.php:54
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\$pageId
‪int $pageId
Definition: AbstractConditionMatcher.php:41
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\getPageId
‪int getPageId()
Definition: AbstractConditionMatcher.php:105
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\$simulateMatchConditions
‪array $simulateMatchConditions
Definition: AbstractConditionMatcher.php:61
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\evaluateExpression
‪bool evaluateExpression(string $expression)
Definition: AbstractConditionMatcher.php:184
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\setSimulateMatchResult
‪setSimulateMatchResult($simulateMatchResult)
Definition: AbstractConditionMatcher.php:138
‪TYPO3\CMS\Core\Exception\MissingTsfeException
Definition: MissingTsfeException.php:21
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher
Definition: AbstractConditionMatcher.php:34
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\$rootline
‪array $rootline
Definition: AbstractConditionMatcher.php:47
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\ConditionMatcherInterface
Definition: ConditionMatcherInterface.php:24
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\setSimulateMatchConditions
‪setSimulateMatchConditions(array $simulateMatchConditions)
Definition: AbstractConditionMatcher.php:150
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\getRootline
‪array getRootline()
Definition: AbstractConditionMatcher.php:128
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\updateExpressionLanguageVariables
‪updateExpressionLanguageVariables()
Definition: AbstractConditionMatcher.php:81
‪TYPO3\CMS\Core\Error\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\initializeExpressionLanguageResolver
‪initializeExpressionLanguageResolver()
Definition: AbstractConditionMatcher.php:71
‪TYPO3\CMS\Core\ExpressionLanguage\Resolver
Definition: Resolver.php:27
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\$expressionLanguageResolverVariables
‪array $expressionLanguageResolverVariables
Definition: AbstractConditionMatcher.php:69
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\$expressionLanguageResolver
‪Resolver $expressionLanguageResolver
Definition: AbstractConditionMatcher.php:65
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching
Definition: AbstractCondition.php:16
‪TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher\setPageId
‪setPageId($pageId)
Definition: AbstractConditionMatcher.php:92