Expression.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. <?php
  2. /**
  3. * League.Uri (https://uri.thephpleague.com)
  4. *
  5. * (c) Ignace Nyamagana Butera <nyamsprod@gmail.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. declare(strict_types=1);
  11. namespace League\Uri\UriTemplate;
  12. use Deprecated;
  13. use League\Uri\Exceptions\SyntaxError;
  14. use Stringable;
  15. use function array_filter;
  16. use function array_map;
  17. use function array_unique;
  18. use function explode;
  19. use function implode;
  20. /**
  21. * @internal The class exposes the internal representation of an Expression and its usage
  22. * @link https://www.rfc-editor.org/rfc/rfc6570#section-2.2
  23. */
  24. final class Expression
  25. {
  26. /** @var array<VarSpecifier> */
  27. private readonly array $varSpecifiers;
  28. /** @var array<string> */
  29. public readonly array $variableNames;
  30. public readonly string $value;
  31. private function __construct(public readonly Operator $operator, VarSpecifier ...$varSpecifiers)
  32. {
  33. $this->varSpecifiers = $varSpecifiers;
  34. $this->variableNames = array_unique(
  35. array_map(
  36. static fn (VarSpecifier $varSpecifier): string => $varSpecifier->name,
  37. $varSpecifiers
  38. )
  39. );
  40. $this->value = '{'.$operator->value.implode(',', array_map(
  41. static fn (VarSpecifier $varSpecifier): string => $varSpecifier->toString(),
  42. $varSpecifiers
  43. )).'}';
  44. }
  45. /**
  46. * @throws SyntaxError if the expression is invalid
  47. */
  48. public static function new(Stringable|string $expression): self
  49. {
  50. $parts = Operator::parseExpression($expression);
  51. return new Expression($parts['operator'], ...array_map(
  52. static fn (string $varSpec): VarSpecifier => VarSpecifier::new($varSpec),
  53. explode(',', $parts['variables'])
  54. ));
  55. }
  56. /**
  57. * DEPRECATION WARNING! This method will be removed in the next major point release.
  58. *
  59. * @throws SyntaxError if the expression is invalid
  60. * @see Expression::new()
  61. *
  62. * @deprecated Since version 7.0.0
  63. * @codeCoverageIgnore
  64. */
  65. #[Deprecated(message:'use League\Uri\UriTemplate\Exppression::new() instead', since:'league/uri:7.0.0')]
  66. public static function createFromString(Stringable|string $expression): self
  67. {
  68. return self::new($expression);
  69. }
  70. public function expand(VariableBag $variables): string
  71. {
  72. $expanded = implode(
  73. $this->operator->separator(),
  74. array_filter(
  75. array_map(
  76. fn (VarSpecifier $varSpecifier): string => $this->operator->expand($varSpecifier, $variables),
  77. $this->varSpecifiers
  78. ),
  79. static fn ($value): bool => '' !== $value
  80. )
  81. );
  82. return match ('') {
  83. $expanded => '',
  84. default => $this->operator->first().$expanded,
  85. };
  86. }
  87. }