vendor/symfony/expression-language/Node/BinaryNode.php line 92

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\Node;
  11. use Symfony\Component\ExpressionLanguage\Compiler;
  12. use Symfony\Component\ExpressionLanguage\SyntaxError;
  13. /**
  14.  * @author Fabien Potencier <fabien@symfony.com>
  15.  *
  16.  * @internal
  17.  */
  18. class BinaryNode extends Node
  19. {
  20.     private const OPERATORS = [
  21.         '~' => '.',
  22.         'and' => '&&',
  23.         'or' => '||',
  24.     ];
  25.     private const FUNCTIONS = [
  26.         '**' => 'pow',
  27.         '..' => 'range',
  28.         'in' => 'in_array',
  29.         'not in' => '!in_array',
  30.     ];
  31.     public function __construct(string $operatorNode $leftNode $right)
  32.     {
  33.         parent::__construct(
  34.             ['left' => $left'right' => $right],
  35.             ['operator' => $operator]
  36.         );
  37.     }
  38.     public function compile(Compiler $compiler)
  39.     {
  40.         $operator $this->attributes['operator'];
  41.         if ('matches' == $operator) {
  42.             if ($this->nodes['right'] instanceof ConstantNode) {
  43.                 $this->evaluateMatches($this->nodes['right']->evaluate([], []), '');
  44.             }
  45.             $compiler
  46.                 ->raw('(static function ($regexp, $str) { set_error_handler(function ($t, $m) use ($regexp, $str) { throw new \Symfony\Component\ExpressionLanguage\SyntaxError(sprintf(\'Regexp "%s" passed to "matches" is not valid\', $regexp).substr($m, 12)); }); try { return preg_match($regexp, (string) $str); } finally { restore_error_handler(); } })(')
  47.                 ->compile($this->nodes['right'])
  48.                 ->raw(', ')
  49.                 ->compile($this->nodes['left'])
  50.                 ->raw(')')
  51.             ;
  52.             return;
  53.         }
  54.         if (isset(self::FUNCTIONS[$operator])) {
  55.             $compiler
  56.                 ->raw(sprintf('%s('self::FUNCTIONS[$operator]))
  57.                 ->compile($this->nodes['left'])
  58.                 ->raw(', ')
  59.                 ->compile($this->nodes['right'])
  60.                 ->raw(')')
  61.             ;
  62.             return;
  63.         }
  64.         if (isset(self::OPERATORS[$operator])) {
  65.             $operator self::OPERATORS[$operator];
  66.         }
  67.         $compiler
  68.             ->raw('(')
  69.             ->compile($this->nodes['left'])
  70.             ->raw(' ')
  71.             ->raw($operator)
  72.             ->raw(' ')
  73.             ->compile($this->nodes['right'])
  74.             ->raw(')')
  75.         ;
  76.     }
  77.     public function evaluate(array $functions, array $values)
  78.     {
  79.         $operator $this->attributes['operator'];
  80.         $left $this->nodes['left']->evaluate($functions$values);
  81.         if (isset(self::FUNCTIONS[$operator])) {
  82.             $right $this->nodes['right']->evaluate($functions$values);
  83.             if ('not in' === $operator) {
  84.                 return !\in_array($left$right);
  85.             }
  86.             $f self::FUNCTIONS[$operator];
  87.             return $f($left$right);
  88.         }
  89.         switch ($operator) {
  90.             case 'or':
  91.             case '||':
  92.                 return $left || $this->nodes['right']->evaluate($functions$values);
  93.             case 'and':
  94.             case '&&':
  95.                 return $left && $this->nodes['right']->evaluate($functions$values);
  96.         }
  97.         $right $this->nodes['right']->evaluate($functions$values);
  98.         switch ($operator) {
  99.             case '|':
  100.                 return $left $right;
  101.             case '^':
  102.                 return $left $right;
  103.             case '&':
  104.                 return $left $right;
  105.             case '==':
  106.                 return $left == $right;
  107.             case '===':
  108.                 return $left === $right;
  109.             case '!=':
  110.                 return $left != $right;
  111.             case '!==':
  112.                 return $left !== $right;
  113.             case '<':
  114.                 return $left $right;
  115.             case '>':
  116.                 return $left $right;
  117.             case '>=':
  118.                 return $left >= $right;
  119.             case '<=':
  120.                 return $left <= $right;
  121.             case 'not in':
  122.                 return !\in_array($left$right);
  123.             case 'in':
  124.                 return \in_array($left$right);
  125.             case '+':
  126.                 return $left $right;
  127.             case '-':
  128.                 return $left $right;
  129.             case '~':
  130.                 return $left.$right;
  131.             case '*':
  132.                 return $left $right;
  133.             case '/':
  134.                 if (== $right) {
  135.                     throw new \DivisionByZeroError('Division by zero.');
  136.                 }
  137.                 return $left $right;
  138.             case '%':
  139.                 if (== $right) {
  140.                     throw new \DivisionByZeroError('Modulo by zero.');
  141.                 }
  142.                 return $left $right;
  143.             case 'matches':
  144.                 return $this->evaluateMatches($right$left);
  145.         }
  146.     }
  147.     public function toArray()
  148.     {
  149.         return ['('$this->nodes['left'], ' '.$this->attributes['operator'].' '$this->nodes['right'], ')'];
  150.     }
  151.     private function evaluateMatches(string $regexp, ?string $str): int
  152.     {
  153.         set_error_handler(function ($t$m) use ($regexp) {
  154.             throw new SyntaxError(sprintf('Regexp "%s" passed to "matches" is not valid'$regexp).substr($m12));
  155.         });
  156.         try {
  157.             return preg_match($regexp, (string) $str);
  158.         } finally {
  159.             restore_error_handler();
  160.         }
  161.     }
  162. }