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\ExpressionLanguage; 19 20use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; 21use Symfony\Component\ExpressionLanguage\ExpressionLanguage; 22use TYPO3\CMS\Core\Utility\GeneralUtility; 23 24/** 25 * Class Resolver 26 */ 27class Resolver 28{ 29 /** 30 * @var ProviderInterface 31 */ 32 protected $provider; 33 34 /** 35 * @var \Symfony\Component\ExpressionLanguage\ExpressionLanguage 36 */ 37 protected $expressionLanguage; 38 39 /** 40 * @var array 41 */ 42 public $expressionLanguageVariables = []; 43 44 /** 45 * @param string $context 46 * @param array $variables 47 */ 48 public function __construct(string $context, array $variables) 49 { 50 $functionProviderInstances = []; 51 $providers = GeneralUtility::makeInstance(ProviderConfigurationLoader::class)->getExpressionLanguageProviders()[$context] ?? []; 52 // Always add default provider 53 array_unshift($providers, DefaultProvider::class); 54 $providers = array_unique($providers); 55 $functionProviders = []; 56 $generalVariables = []; 57 foreach ($providers as $provider) { 58 /** @var ProviderInterface $providerInstance */ 59 $providerInstance = GeneralUtility::makeInstance($provider); 60 $functionProviders[] = $providerInstance->getExpressionLanguageProviders(); 61 $generalVariables[] = $providerInstance->getExpressionLanguageVariables(); 62 } 63 $functionProviders = array_merge(...$functionProviders); 64 $generalVariables = array_replace_recursive(...$generalVariables); 65 $this->expressionLanguageVariables = array_replace_recursive($generalVariables, $variables); 66 foreach ($functionProviders as $functionProvider) { 67 /** @var ExpressionFunctionProviderInterface[] $functionProviderInstances */ 68 $functionProviderInstances[] = GeneralUtility::makeInstance($functionProvider); 69 } 70 $this->expressionLanguage = new ExpressionLanguage(null, $functionProviderInstances); 71 } 72 73 /** 74 * Evaluate an expression. 75 * 76 * @param string $condition The expression to parse 77 * @return bool 78 */ 79 public function evaluate(string $condition): bool 80 { 81 // The TypoScript [ELSE] condition is not known by the Symfony Expression Language 82 // and must not be evaluated. If/else logic is handled in TypoScriptParser. 83 if (strtoupper($condition) === 'ELSE') { 84 return false; 85 } 86 87 return (bool)$this->expressionLanguage->evaluate($condition, $this->expressionLanguageVariables); 88 } 89 90 /** 91 * Compiles an expression source code. 92 * 93 * @param string $condition The expression to compile 94 * @return string 95 */ 96 public function compile(string $condition): string 97 { 98 return (string)$this->expressionLanguage->compile($condition, array_keys($this->expressionLanguageVariables)); 99 } 100} 101