vendor/symfony/config/Definition/Builder/ExprBuilder.php line 239

  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\Config\Definition\Builder;
  11. use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
  12. /**
  13.  * This class builds an if expression.
  14.  *
  15.  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  16.  * @author Christophe Coevoet <stof@notk.org>
  17.  */
  18. class ExprBuilder
  19. {
  20.     public const TYPE_ANY 'any';
  21.     public const TYPE_STRING 'string';
  22.     public const TYPE_NULL 'null';
  23.     public const TYPE_ARRAY 'array';
  24.     protected $node;
  25.     public $allowedTypes;
  26.     public $ifPart;
  27.     public $thenPart;
  28.     public function __construct(NodeDefinition $node)
  29.     {
  30.         $this->node $node;
  31.     }
  32.     /**
  33.      * Marks the expression as being always used.
  34.      *
  35.      * @return $this
  36.      */
  37.     public function always(?\Closure $then null): static
  38.     {
  39.         $this->ifPart = static fn () => true;
  40.         $this->allowedTypes self::TYPE_ANY;
  41.         if (null !== $then) {
  42.             $this->thenPart $then;
  43.         }
  44.         return $this;
  45.     }
  46.     /**
  47.      * Sets a closure to use as tests.
  48.      *
  49.      * The default one tests if the value is true.
  50.      *
  51.      * @return $this
  52.      */
  53.     public function ifTrue(?\Closure $closure null): static
  54.     {
  55.         $this->ifPart $closure ?? static fn ($v) => true === $v;
  56.         $this->allowedTypes self::TYPE_ANY;
  57.         return $this;
  58.     }
  59.     /**
  60.      * Tests if the value is a string.
  61.      *
  62.      * @return $this
  63.      */
  64.     public function ifString(): static
  65.     {
  66.         $this->ifPart \is_string(...);
  67.         $this->allowedTypes self::TYPE_STRING;
  68.         return $this;
  69.     }
  70.     /**
  71.      * Tests if the value is null.
  72.      *
  73.      * @return $this
  74.      */
  75.     public function ifNull(): static
  76.     {
  77.         $this->ifPart \is_null(...);
  78.         $this->allowedTypes self::TYPE_NULL;
  79.         return $this;
  80.     }
  81.     /**
  82.      * Tests if the value is empty.
  83.      *
  84.      * @return $this
  85.      */
  86.     public function ifEmpty(): static
  87.     {
  88.         $this->ifPart = static fn ($v) => empty($v);
  89.         $this->allowedTypes self::TYPE_ANY;
  90.         return $this;
  91.     }
  92.     /**
  93.      * Tests if the value is an array.
  94.      *
  95.      * @return $this
  96.      */
  97.     public function ifArray(): static
  98.     {
  99.         $this->ifPart \is_array(...);
  100.         $this->allowedTypes self::TYPE_ARRAY;
  101.         return $this;
  102.     }
  103.     /**
  104.      * Tests if the value is in an array.
  105.      *
  106.      * @return $this
  107.      */
  108.     public function ifInArray(array $array): static
  109.     {
  110.         $this->ifPart = static fn ($v) => \in_array($v$arraytrue);
  111.         $this->allowedTypes self::TYPE_ANY;
  112.         return $this;
  113.     }
  114.     /**
  115.      * Tests if the value is not in an array.
  116.      *
  117.      * @return $this
  118.      */
  119.     public function ifNotInArray(array $array): static
  120.     {
  121.         $this->ifPart = static fn ($v) => !\in_array($v$arraytrue);
  122.         $this->allowedTypes self::TYPE_ANY;
  123.         return $this;
  124.     }
  125.     /**
  126.      * Transforms variables of any type into an array.
  127.      *
  128.      * @return $this
  129.      */
  130.     public function castToArray(): static
  131.     {
  132.         $this->ifPart = static fn ($v) => !\is_array($v);
  133.         $this->allowedTypes self::TYPE_ANY;
  134.         $this->thenPart = static fn ($v) => [$v];
  135.         return $this;
  136.     }
  137.     /**
  138.      * Sets the closure to run if the test pass.
  139.      *
  140.      * @return $this
  141.      */
  142.     public function then(\Closure $closure): static
  143.     {
  144.         $this->thenPart $closure;
  145.         return $this;
  146.     }
  147.     /**
  148.      * Sets a closure returning an empty array.
  149.      *
  150.      * @return $this
  151.      */
  152.     public function thenEmptyArray(): static
  153.     {
  154.         $this->thenPart = static fn () => [];
  155.         return $this;
  156.     }
  157.     /**
  158.      * Sets a closure marking the value as invalid at processing time.
  159.      *
  160.      * if you want to add the value of the node in your message just use a %s placeholder.
  161.      *
  162.      * @return $this
  163.      *
  164.      * @throws \InvalidArgumentException
  165.      */
  166.     public function thenInvalid(string $message): static
  167.     {
  168.         $this->thenPart = static fn ($v) => throw new \InvalidArgumentException(sprintf($messagejson_encode($v)));
  169.         return $this;
  170.     }
  171.     /**
  172.      * Sets a closure unsetting this key of the array at processing time.
  173.      *
  174.      * @return $this
  175.      *
  176.      * @throws UnsetKeyException
  177.      */
  178.     public function thenUnset(): static
  179.     {
  180.         $this->thenPart = static fn () => throw new UnsetKeyException('Unsetting key.');
  181.         return $this;
  182.     }
  183.     /**
  184.      * Returns the related node.
  185.      *
  186.      * @throws \RuntimeException
  187.      */
  188.     public function end(): NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition
  189.     {
  190.         if (null === $this->ifPart) {
  191.             throw new \RuntimeException('You must specify an if part.');
  192.         }
  193.         if (null === $this->thenPart) {
  194.             throw new \RuntimeException('You must specify a then part.');
  195.         }
  196.         return $this->node;
  197.     }
  198.     /**
  199.      * Builds the expressions.
  200.      *
  201.      * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build
  202.      */
  203.     public static function buildExpressions(array $expressions): array
  204.     {
  205.         foreach ($expressions as $k => $expr) {
  206.             if ($expr instanceof self) {
  207.                 $if $expr->ifPart;
  208.                 $then $expr->thenPart;
  209.                 $expressions[$k] = static fn ($v) => $if($v) ? $then($v) : $v;
  210.             }
  211.         }
  212.         return $expressions;
  213.     }
  214. }