ExpressionFunction.php 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. /**
  12. * Represents a function that can be used in an expression.
  13. *
  14. * A function is defined by two PHP callables. The callables are used
  15. * by the language to compile and/or evaluate the function.
  16. *
  17. * The "compiler" function is used at compilation time and must return a
  18. * PHP representation of the function call (it receives the function
  19. * arguments as arguments).
  20. *
  21. * The "evaluator" function is used for expression evaluation and must return
  22. * the value of the function call based on the values defined for the
  23. * expression (it receives the values as a first argument and the function
  24. * arguments as remaining arguments).
  25. *
  26. * @author Fabien Potencier <fabien@symfony.com>
  27. */
  28. class ExpressionFunction
  29. {
  30. private $name;
  31. private $compiler;
  32. private $evaluator;
  33. /**
  34. * @param string $name The function name
  35. * @param callable $compiler A callable able to compile the function
  36. * @param callable $evaluator A callable able to evaluate the function
  37. */
  38. public function __construct(string $name, callable $compiler, callable $evaluator)
  39. {
  40. $this->name = $name;
  41. $this->compiler = $compiler;
  42. $this->evaluator = $evaluator;
  43. }
  44. public function getName()
  45. {
  46. return $this->name;
  47. }
  48. public function getCompiler()
  49. {
  50. return $this->compiler;
  51. }
  52. public function getEvaluator()
  53. {
  54. return $this->evaluator;
  55. }
  56. /**
  57. * Creates an ExpressionFunction from a PHP function name.
  58. *
  59. * @param string|null $expressionFunctionName The expression function name (default: same than the PHP function name)
  60. *
  61. * @return self
  62. *
  63. * @throws \InvalidArgumentException if given PHP function name does not exist
  64. * @throws \InvalidArgumentException if given PHP function name is in namespace
  65. * and expression function name is not defined
  66. */
  67. public static function fromPhp(string $phpFunctionName, string $expressionFunctionName = null)
  68. {
  69. $phpFunctionName = ltrim($phpFunctionName, '\\');
  70. if (!\function_exists($phpFunctionName)) {
  71. throw new \InvalidArgumentException(sprintf('PHP function "%s" does not exist.', $phpFunctionName));
  72. }
  73. $parts = explode('\\', $phpFunctionName);
  74. if (!$expressionFunctionName && \count($parts) > 1) {
  75. throw new \InvalidArgumentException(sprintf('An expression function name must be defined when PHP function "%s" is namespaced.', $phpFunctionName));
  76. }
  77. $compiler = function (...$args) use ($phpFunctionName) {
  78. return sprintf('\%s(%s)', $phpFunctionName, implode(', ', $args));
  79. };
  80. $evaluator = function ($p, ...$args) use ($phpFunctionName) {
  81. return $phpFunctionName(...$args);
  82. };
  83. return new self($expressionFunctionName ?: end($parts), $compiler, $evaluator);
  84. }
  85. }