Update website

This commit is contained in:
Guilhem Lavaux 2024-11-23 20:45:29 +01:00
parent 41ce1aa076
commit ea0eb1c6e0
4222 changed files with 721797 additions and 14 deletions

View file

@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Node;
use Symfony\Component\ExpressionLanguage\Compiler;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/
class ArgumentsNode extends ArrayNode
{
public function compile(Compiler $compiler)
{
$this->compileArguments($compiler, false);
}
public function toArray()
{
$array = [];
foreach ($this->getKeyValuePairs() as $pair) {
$array[] = $pair['value'];
$array[] = ', ';
}
array_pop($array);
return $array;
}
}

View file

@ -0,0 +1,118 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Node;
use Symfony\Component\ExpressionLanguage\Compiler;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/
class ArrayNode extends Node
{
protected $index;
public function __construct()
{
$this->index = -1;
}
public function addElement(Node $value, Node $key = null)
{
if (null === $key) {
$key = new ConstantNode(++$this->index);
}
array_push($this->nodes, $key, $value);
}
/**
* Compiles the node to PHP.
*/
public function compile(Compiler $compiler)
{
$compiler->raw('[');
$this->compileArguments($compiler);
$compiler->raw(']');
}
public function evaluate(array $functions, array $values)
{
$result = [];
foreach ($this->getKeyValuePairs() as $pair) {
$result[$pair['key']->evaluate($functions, $values)] = $pair['value']->evaluate($functions, $values);
}
return $result;
}
public function toArray()
{
$value = [];
foreach ($this->getKeyValuePairs() as $pair) {
$value[$pair['key']->attributes['value']] = $pair['value'];
}
$array = [];
if ($this->isHash($value)) {
foreach ($value as $k => $v) {
$array[] = ', ';
$array[] = new ConstantNode($k);
$array[] = ': ';
$array[] = $v;
}
$array[0] = '{';
$array[] = '}';
} else {
foreach ($value as $v) {
$array[] = ', ';
$array[] = $v;
}
$array[0] = '[';
$array[] = ']';
}
return $array;
}
protected function getKeyValuePairs()
{
$pairs = [];
foreach (array_chunk($this->nodes, 2) as $pair) {
$pairs[] = ['key' => $pair[0], 'value' => $pair[1]];
}
return $pairs;
}
protected function compileArguments(Compiler $compiler, bool $withKeys = true)
{
$first = true;
foreach ($this->getKeyValuePairs() as $pair) {
if (!$first) {
$compiler->raw(', ');
}
$first = false;
if ($withKeys) {
$compiler
->compile($pair['key'])
->raw(' => ')
;
}
$compiler->compile($pair['value']);
}
}
}

View file

@ -0,0 +1,187 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Node;
use Symfony\Component\ExpressionLanguage\Compiler;
use Symfony\Component\ExpressionLanguage\SyntaxError;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/
class BinaryNode extends Node
{
private const OPERATORS = [
'~' => '.',
'and' => '&&',
'or' => '||',
];
private const FUNCTIONS = [
'**' => 'pow',
'..' => 'range',
'in' => 'in_array',
'not in' => '!in_array',
];
public function __construct(string $operator, Node $left, Node $right)
{
parent::__construct(
['left' => $left, 'right' => $right],
['operator' => $operator]
);
}
public function compile(Compiler $compiler)
{
$operator = $this->attributes['operator'];
if ('matches' == $operator) {
if ($this->nodes['right'] instanceof ConstantNode) {
$this->evaluateMatches($this->nodes['right']->evaluate([], []), '');
}
$compiler
->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(); } })(')
->compile($this->nodes['right'])
->raw(', ')
->compile($this->nodes['left'])
->raw(')')
;
return;
}
if (isset(self::FUNCTIONS[$operator])) {
$compiler
->raw(sprintf('%s(', self::FUNCTIONS[$operator]))
->compile($this->nodes['left'])
->raw(', ')
->compile($this->nodes['right'])
->raw(')')
;
return;
}
if (isset(self::OPERATORS[$operator])) {
$operator = self::OPERATORS[$operator];
}
$compiler
->raw('(')
->compile($this->nodes['left'])
->raw(' ')
->raw($operator)
->raw(' ')
->compile($this->nodes['right'])
->raw(')')
;
}
public function evaluate(array $functions, array $values)
{
$operator = $this->attributes['operator'];
$left = $this->nodes['left']->evaluate($functions, $values);
if (isset(self::FUNCTIONS[$operator])) {
$right = $this->nodes['right']->evaluate($functions, $values);
if ('not in' === $operator) {
return !\in_array($left, $right);
}
$f = self::FUNCTIONS[$operator];
return $f($left, $right);
}
switch ($operator) {
case 'or':
case '||':
return $left || $this->nodes['right']->evaluate($functions, $values);
case 'and':
case '&&':
return $left && $this->nodes['right']->evaluate($functions, $values);
}
$right = $this->nodes['right']->evaluate($functions, $values);
switch ($operator) {
case '|':
return $left | $right;
case '^':
return $left ^ $right;
case '&':
return $left & $right;
case '==':
return $left == $right;
case '===':
return $left === $right;
case '!=':
return $left != $right;
case '!==':
return $left !== $right;
case '<':
return $left < $right;
case '>':
return $left > $right;
case '>=':
return $left >= $right;
case '<=':
return $left <= $right;
case 'not in':
return !\in_array($left, $right);
case 'in':
return \in_array($left, $right);
case '+':
return $left + $right;
case '-':
return $left - $right;
case '~':
return $left.$right;
case '*':
return $left * $right;
case '/':
if (0 == $right) {
throw new \DivisionByZeroError('Division by zero.');
}
return $left / $right;
case '%':
if (0 == $right) {
throw new \DivisionByZeroError('Modulo by zero.');
}
return $left % $right;
case 'matches':
return $this->evaluateMatches($right, $left);
}
}
public function toArray()
{
return ['(', $this->nodes['left'], ' '.$this->attributes['operator'].' ', $this->nodes['right'], ')'];
}
private function evaluateMatches(string $regexp, ?string $str): int
{
set_error_handler(function ($t, $m) use ($regexp) {
throw new 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();
}
}
}

View file

@ -0,0 +1,56 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Node;
use Symfony\Component\ExpressionLanguage\Compiler;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/
class ConditionalNode extends Node
{
public function __construct(Node $expr1, Node $expr2, Node $expr3)
{
parent::__construct(
['expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3]
);
}
public function compile(Compiler $compiler)
{
$compiler
->raw('((')
->compile($this->nodes['expr1'])
->raw(') ? (')
->compile($this->nodes['expr2'])
->raw(') : (')
->compile($this->nodes['expr3'])
->raw('))')
;
}
public function evaluate(array $functions, array $values)
{
if ($this->nodes['expr1']->evaluate($functions, $values)) {
return $this->nodes['expr2']->evaluate($functions, $values);
}
return $this->nodes['expr3']->evaluate($functions, $values);
}
public function toArray()
{
return ['(', $this->nodes['expr1'], ' ? ', $this->nodes['expr2'], ' : ', $this->nodes['expr3'], ')'];
}
}

View file

@ -0,0 +1,81 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Node;
use Symfony\Component\ExpressionLanguage\Compiler;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/
class ConstantNode extends Node
{
private $isIdentifier;
public function __construct($value, bool $isIdentifier = false)
{
$this->isIdentifier = $isIdentifier;
parent::__construct(
[],
['value' => $value]
);
}
public function compile(Compiler $compiler)
{
$compiler->repr($this->attributes['value']);
}
public function evaluate(array $functions, array $values)
{
return $this->attributes['value'];
}
public function toArray()
{
$array = [];
$value = $this->attributes['value'];
if ($this->isIdentifier) {
$array[] = $value;
} elseif (true === $value) {
$array[] = 'true';
} elseif (false === $value) {
$array[] = 'false';
} elseif (null === $value) {
$array[] = 'null';
} elseif (is_numeric($value)) {
$array[] = $value;
} elseif (!\is_array($value)) {
$array[] = $this->dumpString($value);
} elseif ($this->isHash($value)) {
foreach ($value as $k => $v) {
$array[] = ', ';
$array[] = new self($k);
$array[] = ': ';
$array[] = new self($v);
}
$array[0] = '{';
$array[] = '}';
} else {
foreach ($value as $v) {
$array[] = ', ';
$array[] = new self($v);
}
$array[0] = '[';
$array[] = ']';
}
return $array;
}
}

View file

@ -0,0 +1,67 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Node;
use Symfony\Component\ExpressionLanguage\Compiler;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/
class FunctionNode extends Node
{
public function __construct(string $name, Node $arguments)
{
parent::__construct(
['arguments' => $arguments],
['name' => $name]
);
}
public function compile(Compiler $compiler)
{
$arguments = [];
foreach ($this->nodes['arguments']->nodes as $node) {
$arguments[] = $compiler->subcompile($node);
}
$function = $compiler->getFunction($this->attributes['name']);
$compiler->raw($function['compiler'](...$arguments));
}
public function evaluate(array $functions, array $values)
{
$arguments = [$values];
foreach ($this->nodes['arguments']->nodes as $node) {
$arguments[] = $node->evaluate($functions, $values);
}
return $functions[$this->attributes['name']]['evaluator'](...$arguments);
}
public function toArray()
{
$array = [];
$array[] = $this->attributes['name'];
foreach ($this->nodes['arguments']->nodes as $node) {
$array[] = ', ';
$array[] = $node;
}
$array[1] = '(';
$array[] = ')';
return $array;
}
}

View file

@ -0,0 +1,114 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Node;
use Symfony\Component\ExpressionLanguage\Compiler;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/
class GetAttrNode extends Node
{
public const PROPERTY_CALL = 1;
public const METHOD_CALL = 2;
public const ARRAY_CALL = 3;
public function __construct(Node $node, Node $attribute, ArrayNode $arguments, int $type)
{
parent::__construct(
['node' => $node, 'attribute' => $attribute, 'arguments' => $arguments],
['type' => $type]
);
}
public function compile(Compiler $compiler)
{
switch ($this->attributes['type']) {
case self::PROPERTY_CALL:
$compiler
->compile($this->nodes['node'])
->raw('->')
->raw($this->nodes['attribute']->attributes['value'])
;
break;
case self::METHOD_CALL:
$compiler
->compile($this->nodes['node'])
->raw('->')
->raw($this->nodes['attribute']->attributes['value'])
->raw('(')
->compile($this->nodes['arguments'])
->raw(')')
;
break;
case self::ARRAY_CALL:
$compiler
->compile($this->nodes['node'])
->raw('[')
->compile($this->nodes['attribute'])->raw(']')
;
break;
}
}
public function evaluate(array $functions, array $values)
{
switch ($this->attributes['type']) {
case self::PROPERTY_CALL:
$obj = $this->nodes['node']->evaluate($functions, $values);
if (!\is_object($obj)) {
throw new \RuntimeException(sprintf('Unable to get property "%s" of non-object "%s".', $this->nodes['attribute']->dump(), $this->nodes['node']->dump()));
}
$property = $this->nodes['attribute']->attributes['value'];
return $obj->$property;
case self::METHOD_CALL:
$obj = $this->nodes['node']->evaluate($functions, $values);
if (!\is_object($obj)) {
throw new \RuntimeException(sprintf('Unable to call method "%s" of non-object "%s".', $this->nodes['attribute']->dump(), $this->nodes['node']->dump()));
}
if (!\is_callable($toCall = [$obj, $this->nodes['attribute']->attributes['value']])) {
throw new \RuntimeException(sprintf('Unable to call method "%s" of object "%s".', $this->nodes['attribute']->attributes['value'], get_debug_type($obj)));
}
return $toCall(...array_values($this->nodes['arguments']->evaluate($functions, $values)));
case self::ARRAY_CALL:
$array = $this->nodes['node']->evaluate($functions, $values);
if (!\is_array($array) && !$array instanceof \ArrayAccess) {
throw new \RuntimeException(sprintf('Unable to get an item of non-array "%s".', $this->nodes['node']->dump()));
}
return $array[$this->nodes['attribute']->evaluate($functions, $values)];
}
}
public function toArray()
{
switch ($this->attributes['type']) {
case self::PROPERTY_CALL:
return [$this->nodes['node'], '.', $this->nodes['attribute']];
case self::METHOD_CALL:
return [$this->nodes['node'], '.', $this->nodes['attribute'], '(', $this->nodes['arguments'], ')'];
case self::ARRAY_CALL:
return [$this->nodes['node'], '[', $this->nodes['attribute'], ']'];
}
}
}

View file

@ -0,0 +1,45 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Node;
use Symfony\Component\ExpressionLanguage\Compiler;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/
class NameNode extends Node
{
public function __construct(string $name)
{
parent::__construct(
[],
['name' => $name]
);
}
public function compile(Compiler $compiler)
{
$compiler->raw('$'.$this->attributes['name']);
}
public function evaluate(array $functions, array $values)
{
return $values[$this->attributes['name']];
}
public function toArray()
{
return [$this->attributes['name']];
}
}

View file

@ -0,0 +1,113 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Node;
use Symfony\Component\ExpressionLanguage\Compiler;
/**
* Represents a node in the AST.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Node
{
public $nodes = [];
public $attributes = [];
/**
* @param array $nodes An array of nodes
* @param array $attributes An array of attributes
*/
public function __construct(array $nodes = [], array $attributes = [])
{
$this->nodes = $nodes;
$this->attributes = $attributes;
}
/**
* @return string
*/
public function __toString()
{
$attributes = [];
foreach ($this->attributes as $name => $value) {
$attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true)));
}
$repr = [str_replace('Symfony\Component\ExpressionLanguage\Node\\', '', static::class).'('.implode(', ', $attributes)];
if (\count($this->nodes)) {
foreach ($this->nodes as $node) {
foreach (explode("\n", (string) $node) as $line) {
$repr[] = ' '.$line;
}
}
$repr[] = ')';
} else {
$repr[0] .= ')';
}
return implode("\n", $repr);
}
public function compile(Compiler $compiler)
{
foreach ($this->nodes as $node) {
$node->compile($compiler);
}
}
public function evaluate(array $functions, array $values)
{
$results = [];
foreach ($this->nodes as $node) {
$results[] = $node->evaluate($functions, $values);
}
return $results;
}
public function toArray()
{
throw new \BadMethodCallException(sprintf('Dumping a "%s" instance is not supported yet.', static::class));
}
public function dump()
{
$dump = '';
foreach ($this->toArray() as $v) {
$dump .= \is_scalar($v) ? $v : $v->dump();
}
return $dump;
}
protected function dumpString(string $value)
{
return sprintf('"%s"', addcslashes($value, "\0\t\"\\"));
}
protected function isHash(array $value)
{
$expectedKey = 0;
foreach ($value as $key => $val) {
if ($key !== $expectedKey++) {
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,66 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Node;
use Symfony\Component\ExpressionLanguage\Compiler;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal
*/
class UnaryNode extends Node
{
private const OPERATORS = [
'!' => '!',
'not' => '!',
'+' => '+',
'-' => '-',
];
public function __construct(string $operator, Node $node)
{
parent::__construct(
['node' => $node],
['operator' => $operator]
);
}
public function compile(Compiler $compiler)
{
$compiler
->raw('(')
->raw(self::OPERATORS[$this->attributes['operator']])
->compile($this->nodes['node'])
->raw(')')
;
}
public function evaluate(array $functions, array $values)
{
$value = $this->nodes['node']->evaluate($functions, $values);
switch ($this->attributes['operator']) {
case 'not':
case '!':
return !$value;
case '-':
return -$value;
}
return $value;
}
public function toArray(): array
{
return ['(', $this->attributes['operator'].' ', $this->nodes['node'], ')'];
}
}