vendor/symfony/expression-language/ExpressionLanguage.php line 64

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\ExpressionLanguage;
  11. use Psr\Cache\CacheItemPoolInterface;
  12. use Symfony\Component\Cache\Adapter\ArrayAdapter;
  13. /**
  14.  * Allows to compile and evaluate expressions written in your own DSL.
  15.  *
  16.  * @author Fabien Potencier <fabien@symfony.com>
  17.  */
  18. class ExpressionLanguage
  19. {
  20.     private $cache;
  21.     private $lexer;
  22.     private $parser;
  23.     private $compiler;
  24.     protected $functions = [];
  25.     /**
  26.      * @param ExpressionFunctionProviderInterface[] $providers
  27.      */
  28.     public function __construct(CacheItemPoolInterface $cache null, array $providers = [])
  29.     {
  30.         $this->cache $cache ?: new ArrayAdapter();
  31.         $this->registerFunctions();
  32.         foreach ($providers as $provider) {
  33.             $this->registerProvider($provider);
  34.         }
  35.     }
  36.     /**
  37.      * Compiles an expression source code.
  38.      *
  39.      * @param Expression|string $expression The expression to compile
  40.      * @param array             $names      An array of valid names
  41.      *
  42.      * @return string The compiled PHP source code
  43.      */
  44.     public function compile($expression$names = [])
  45.     {
  46.         return $this->getCompiler()->compile($this->parse($expression$names)->getNodes())->getSource();
  47.     }
  48.     /**
  49.      * Evaluate an expression.
  50.      *
  51.      * @param Expression|string $expression The expression to compile
  52.      * @param array             $values     An array of values
  53.      *
  54.      * @return mixed The result of the evaluation of the expression
  55.      */
  56.     public function evaluate($expression$values = [])
  57.     {
  58.         return $this->parse($expressionarray_keys($values))->getNodes()->evaluate($this->functions$values);
  59.     }
  60.     /**
  61.      * Parses an expression.
  62.      *
  63.      * @param Expression|string $expression The expression to parse
  64.      * @param array             $names      An array of valid names
  65.      *
  66.      * @return ParsedExpression A ParsedExpression instance
  67.      */
  68.     public function parse($expression$names)
  69.     {
  70.         if ($expression instanceof ParsedExpression) {
  71.             return $expression;
  72.         }
  73.         asort($names);
  74.         $cacheKeyItems = [];
  75.         foreach ($names as $nameKey => $name) {
  76.             $cacheKeyItems[] = \is_int($nameKey) ? $name $nameKey.':'.$name;
  77.         }
  78.         $cacheItem $this->cache->getItem(rawurlencode($expression.'//'.implode('|'$cacheKeyItems)));
  79.         if (null === $parsedExpression $cacheItem->get()) {
  80.             $nodes $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names);
  81.             $parsedExpression = new ParsedExpression((string) $expression$nodes);
  82.             $cacheItem->set($parsedExpression);
  83.             $this->cache->save($cacheItem);
  84.         }
  85.         return $parsedExpression;
  86.     }
  87.     /**
  88.      * Registers a function.
  89.      *
  90.      * @param string   $name      The function name
  91.      * @param callable $compiler  A callable able to compile the function
  92.      * @param callable $evaluator A callable able to evaluate the function
  93.      *
  94.      * @throws \LogicException when registering a function after calling evaluate(), compile() or parse()
  95.      *
  96.      * @see ExpressionFunction
  97.      */
  98.     public function register($name, callable $compiler, callable $evaluator)
  99.     {
  100.         if (null !== $this->parser) {
  101.             throw new \LogicException('Registering functions after calling evaluate(), compile() or parse() is not supported.');
  102.         }
  103.         $this->functions[$name] = ['compiler' => $compiler'evaluator' => $evaluator];
  104.     }
  105.     public function addFunction(ExpressionFunction $function)
  106.     {
  107.         $this->register($function->getName(), $function->getCompiler(), $function->getEvaluator());
  108.     }
  109.     public function registerProvider(ExpressionFunctionProviderInterface $provider)
  110.     {
  111.         foreach ($provider->getFunctions() as $function) {
  112.             $this->addFunction($function);
  113.         }
  114.     }
  115.     protected function registerFunctions()
  116.     {
  117.         $this->addFunction(ExpressionFunction::fromPhp('constant'));
  118.     }
  119.     private function getLexer(): Lexer
  120.     {
  121.         if (null === $this->lexer) {
  122.             $this->lexer = new Lexer();
  123.         }
  124.         return $this->lexer;
  125.     }
  126.     private function getParser(): Parser
  127.     {
  128.         if (null === $this->parser) {
  129.             $this->parser = new Parser($this->functions);
  130.         }
  131.         return $this->parser;
  132.     }
  133.     private function getCompiler(): Compiler
  134.     {
  135.         if (null === $this->compiler) {
  136.             $this->compiler = new Compiler($this->functions);
  137.         }
  138.         return $this->compiler->reset();
  139.     }
  140. }