17 use Psr\Log\LoggerAwareInterface;
18 use Psr\Log\LoggerAwareTrait;
19 use Symfony\Component\ExpressionLanguage\SyntaxError;
83 $this->expressionLanguageResolver = GeneralUtility::makeInstance(
86 $this->expressionLanguageResolverVariables
101 return GeneralUtility::makeInstance(Features::class)->isFeatureEnabled(
'TypoScript.strictSyntax');
188 [^\\[\\]] # any character except []
189 | (?1) # recursive subroutine 1 when brackets are around
196 $adjacentBrackets =
'/
200 [^\\[\\]] # any character except []
201 | (?1) # recursive subroutine 1 when brackets are around
205 (*SKIP) # avoid backtracking into completed bracket expressions
206 \\[ # match the following [
232 public function match($expression)
235 if ($this->simulateMatchResult) {
239 if (!empty($this->simulateMatchConditions)) {
240 return in_array($expression, $this->simulateMatchConditions);
243 if (!isset($this->pageId)) {
247 if (!isset($this->rootline)) {
253 if ($normalizedExpression[0] ===
'[' && substr($normalizedExpression, -1) ===
']') {
254 $innerExpression = substr($normalizedExpression, 1, -1);
255 $orParts = explode(
']||[', $innerExpression);
257 trigger_error(
'Multiple conditions blocks combined with AND, OR, && or || will be removed in TYPO3 v10.0, use the new expression language.', E_USER_DEPRECATED);
259 foreach ($orParts as $orPart) {
260 $andParts = explode(
']&&[', $orPart);
262 trigger_error(
'Multiple conditions blocks combined with AND, OR, && or || will be removed in TYPO3 v10.0, use the new expression language.', E_USER_DEPRECATED);
264 foreach ($andParts as $andPart) {
266 if (!is_bool($result)) {
270 if ($result ===
false) {
275 if ($result ===
true) {
290 $result = $this->expressionLanguageResolver->evaluate($expression);
291 if ($result !==
null) {
294 }
catch (MissingTsfeException $e) {
298 }
catch (SyntaxError $exception) {
300 $message =
'Expression could not be parsed, fallback kicks in.';
301 if (strpos($exception->getMessage(),
'Unexpected character "="') !==
false) {
302 $message .=
' It looks like an old condition with only one equal sign.';
307 [
'expression' => $expression]
309 }
catch (\Throwable $exception) {
319 $this->logger->error($exception->getMessage(), [
320 'expression' => $expression,
321 'exception' => $exception
323 if (TYPO3_MODE ===
'FE'
324 && $exception instanceof Exception
326 && strpos($exception->getMessage(),
'in_array() expects parameter 2 to be array') !==
false
328 throw new InvalidTypoScriptConditionException(
'Invalid expression in condition: [' . $expression .
']', 1536950931);
344 $keyParts = GeneralUtility::trimExplode(
'|', $key);
345 switch ($keyParts[0]) {
346 case 'applicationContext':
347 $values = GeneralUtility::trimExplode(
',', $value,
true);
348 $currentApplicationContext = GeneralUtility::getApplicationContext();
349 foreach ($values as $applicationContext) {
356 if (GeneralUtility::getIndpEnv(
'HTTP_ACCEPT_LANGUAGE') === $value) {
359 $values = GeneralUtility::trimExplode(
',', $value,
true);
360 foreach ($values as $test) {
362 if (preg_match(
'/^\\*.+\\*$/', $test)) {
363 $allLanguages = preg_split(
'/[,;]/', GeneralUtility::getIndpEnv(
'HTTP_ACCEPT_LANGUAGE'));
364 if (in_array(substr($test, 1, -1), $allLanguages)) {
367 } elseif (GeneralUtility::getIndpEnv(
'HTTP_ACCEPT_LANGUAGE') == $test) {
373 if ($value ===
'devIP') {
374 $value = trim(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'devIPmask']);
377 return (
bool)GeneralUtility::cmpIP(GeneralUtility::getIndpEnv(
'REMOTE_ADDR'), $value);
379 return (
bool)GeneralUtility::cmpFQDN(GeneralUtility::getIndpEnv(
'REMOTE_ADDR'), $value);
388 $theEvalTime =
$GLOBALS[
'SIM_EXEC_TIME'];
391 $theTestValue = date(
'H', $theEvalTime);
394 $theTestValue = date(
'i', $theEvalTime);
397 $theTestValue = date(
'm', $theEvalTime);
400 $theTestValue = date(
'Y', $theEvalTime);
403 $theTestValue = date(
'w', $theEvalTime);
406 $theTestValue = date(
'd', $theEvalTime);
409 $theTestValue = date(
'z', $theEvalTime);
415 $theTestValue = (int)$theTestValue;
417 $values = GeneralUtility::trimExplode(
',', $value,
true);
418 foreach ($values as $test) {
419 if (\
TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($test)) {
427 case 'compatVersion':
431 $values = GeneralUtility::trimExplode(
',', $value,
true);
432 foreach ($values as $test) {
433 if ($test ===
'*' || (
string)$this->
getUserId() === (
string)$test) {
437 } elseif ($value ===
'') {
444 $property = $keyParts[1];
445 if (!empty($page) && isset($page[$property]) && (
string)$page[$property] === (
string)$value) {
451 $values = GeneralUtility::trimExplode(
',', $value,
true);
452 foreach ($values as $test) {
453 $point = strcspn($test,
'!=<>');
454 $theVarName = substr($test, 0, $point);
456 $testValue = substr($test, $point);
463 $values = GeneralUtility::trimExplode(
',', $value,
true);
464 foreach ($values as $test) {
465 $point = strcspn($test,
'=');
466 $theVarName = substr($test, 0, $point);
468 $testValue = substr($test, $point + 1);
476 preg_match_all(
'/^\s*([^\(\s]+)\s*(?:\((.*)\))?\s*$/', $value, $matches);
477 $funcName = $matches[1][0];
479 if (is_callable($funcName) && call_user_func_array($funcName, $funcValues)) {
498 $conditionResult =
null;
500 list($conditionClassName, $conditionParameters) = GeneralUtility::trimExplode(
' ', $condition,
false, 2);
504 if (class_exists($conditionClassName)) {
507 $conditionObject = GeneralUtility::makeInstance($conditionClassName);
508 if (($conditionObject instanceof \
TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition) ===
false) {
509 throw new \TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException(
510 '"' . $conditionClassName .
'" is not a valid TypoScript Condition object.',
516 $conditionObject->setConditionMatcherInstance($this);
517 $conditionResult = $conditionObject->matchCondition($conditionParameters);
520 return $conditionResult;
533 $arguments = trim($arguments);
534 while ($arguments !==
'') {
535 if ($arguments[0] ===
',') {
537 $arguments = substr($arguments, 1);
539 $pos = strcspn($arguments,
',\'"');
542 $quote = $arguments[0];
543 $segment = preg_replace(
'/^(.*?[^\\\])' . $quote .
'.*$/',
'\1', substr($arguments, 1));
544 $segment = str_replace(
'\\' . $quote, $quote, $segment);
545 $result[] = $segment;
547 $arguments = substr($arguments, strlen($segment) + 2);
548 $offset = strpos($arguments,
',');
549 if ($offset ===
false) {
550 $offset = strlen($arguments);
552 $arguments = substr($arguments, $offset + 1);
554 $result[] = trim(substr($arguments, 0, $pos));
555 $arguments = substr($arguments, $pos + 1);
558 $arguments = trim($arguments);
573 $namespace = trim($vars[0]);
574 if (count($vars) === 1) {
576 } elseif ($namespace ===
'LIT') {
577 $value = trim($vars[1]);
579 $splitAgain = explode(
'|', $vars[1], 2);
580 $k = trim($splitAgain[0]);
582 switch ($namespace) {
584 $value = GeneralUtility::_GP($k);
587 $value = GeneralUtility::_GPmerged($k);
593 $value = GeneralUtility::getIndpEnv($k);
599 if (count($splitAgain) > 1) {
600 if (is_array($value) && trim($splitAgain[1]) !==
'') {
601 $value = $this->
getGlobal($splitAgain[1], $value);
621 if (preg_match(
'/^(!?=+|<=?|>=?)\\s*([^\\s]*)\\s*$/', $test, $matches)) {
622 $operator = $matches[1];
623 $rightValue = $matches[2];
626 return $leftValue >= (float)$rightValue;
629 return $leftValue <= (float)$rightValue;
635 $rightValueParts = GeneralUtility::trimExplode(
'|', $rightValue);
636 foreach ($rightValueParts as $rightValueSingle) {
637 if ($leftValue == (
float)$rightValueSingle) {
642 return $found ===
false;
645 return $leftValue < (float)$rightValue;
648 return $leftValue > (float)$rightValue;
655 $rightValueParts = GeneralUtility::trimExplode(
'|', $rightValue);
656 foreach ($rightValueParts as $rightValueSingle) {
657 if ($leftValue == $rightValueSingle) {
690 protected function getGlobal($var, $source =
null)
692 $vars = explode(
'|', $var);
695 $theVar = isset($source) ? ($source[$k] ??
null) : (
$GLOBALS[$k] ??
null);
696 for ($a = 1; $a < $c; $a++) {
697 if (!isset($theVar)) {
700 $key = trim($vars[$a]);
701 if (is_object($theVar)) {
702 $theVar = $theVar->{$key};
703 } elseif (is_array($theVar)) {
704 $theVar = $theVar[$key];
709 if (!is_array($theVar) && !is_object($theVar)) {
723 abstract protected function evaluateCondition($string);
738 abstract protected function getVariable($name);
746 abstract protected function getGroupList();
754 abstract protected function determinePageId();
762 abstract protected function getPage();
770 abstract protected function determineRootline();
778 abstract protected function getUserId();
786 abstract protected function isUserLoggedIn();