diff --git a/src/Bundle/DependencyInjection/SyliusResourceExtension.php b/src/Bundle/DependencyInjection/SyliusResourceExtension.php index ba3c013c6..44befcbbd 100644 --- a/src/Bundle/DependencyInjection/SyliusResourceExtension.php +++ b/src/Bundle/DependencyInjection/SyliusResourceExtension.php @@ -21,6 +21,8 @@ use Sylius\Bundle\ResourceBundle\Form\Type\DefaultResourceType; use Sylius\Bundle\ResourceBundle\SyliusResourceBundle; use Sylius\Component\Resource\Factory\FactoryInterface as LegacyFactoryInterface; +use Sylius\Resource\Annotation\AsExpressionProvider; +use Sylius\Resource\Annotation\AsExpressionVariables; use Sylius\Resource\Factory\Factory; use Sylius\Resource\Factory\FactoryInterface; use Sylius\Resource\Metadata\AsResource; @@ -33,6 +35,7 @@ use Sylius\Resource\Twig\Context\Factory\ContextFactoryInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Extension\Extension; @@ -100,6 +103,20 @@ public function load(array $configs, ContainerBuilder $container): void $container->addObjectResource(DoctrineORMDriver::class); $container->addObjectResource(DoctrineODMDriver::class); $container->addObjectResource(DoctrinePHPCRDriver::class); + + $container->registerAttributeForAutoconfiguration( + AsExpressionVariables::class, + static function (ChildDefinition $definition, AsExpressionVariables $attribute, \Reflector $reflector): void { + $definition->addTag(sprintf(AsExpressionVariables::BASE_SERVICE_TAG, $attribute->name)); + }, + ); + + $container->registerAttributeForAutoconfiguration( + AsExpressionProvider::class, + static function (ChildDefinition $definition, AsExpressionProvider $attribute, \Reflector $reflector): void { + $definition->addTag(sprintf(AsExpressionProvider::BASE_SERVICE_TAG, $attribute->name)); + }, + ); } public function getConfiguration(array $config, ContainerBuilder $container): Configuration diff --git a/src/Bundle/Resources/config/services/expression_language.xml b/src/Bundle/Resources/config/services/expression_language.xml index a061f1dee..9458eca8b 100644 --- a/src/Bundle/Resources/config/services/expression_language.xml +++ b/src/Bundle/Resources/config/services/expression_language.xml @@ -13,48 +13,77 @@ - - - + + + - - - - + + - - - - - + + - - + + - - + + - - + + - + + + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Bundle/Resources/config/services/routing.xml b/src/Bundle/Resources/config/services/routing.xml index 567598b92..4000bf092 100644 --- a/src/Bundle/Resources/config/services/routing.xml +++ b/src/Bundle/Resources/config/services/routing.xml @@ -113,7 +113,7 @@ - + diff --git a/src/Bundle/Resources/config/services/state.xml b/src/Bundle/Resources/config/services/state.xml index a6af7a29b..d6835f1f7 100644 --- a/src/Bundle/Resources/config/services/state.xml +++ b/src/Bundle/Resources/config/services/state.xml @@ -40,7 +40,7 @@ - + diff --git a/src/Component/src/Annotation/AsExpressionProvider.php b/src/Component/src/Annotation/AsExpressionProvider.php new file mode 100644 index 000000000..d265a4724 --- /dev/null +++ b/src/Component/src/Annotation/AsExpressionProvider.php @@ -0,0 +1,25 @@ + $value) { - $arguments[$key] = $this->argumentParser->parseExpression($value); + $arguments[$key] = $this->expressionEvaluator->evaluateExpression($value); } return $arguments; diff --git a/src/Component/src/Symfony/ExpressionLanguage/ArgumentParser.php b/src/Component/src/Symfony/ExpressionLanguage/ExpressionEvaluator.php similarity index 76% rename from src/Component/src/Symfony/ExpressionLanguage/ArgumentParser.php rename to src/Component/src/Symfony/ExpressionLanguage/ExpressionEvaluator.php index 66e1c2d3f..e9754c90f 100644 --- a/src/Component/src/Symfony/ExpressionLanguage/ArgumentParser.php +++ b/src/Component/src/Symfony/ExpressionLanguage/ExpressionEvaluator.php @@ -18,7 +18,7 @@ /** * @experimental */ -final class ArgumentParser implements ArgumentParserInterface +final class ExpressionEvaluator implements ExpressionEvaluatorInterface { public function __construct( private ExpressionLanguage $expressionLanguage, @@ -26,12 +26,12 @@ public function __construct( ) { } - public function parseExpression(string $expression, array $variables = []): mixed + public function evaluateExpression(string $expression, array $variables = []): mixed { return $this->expressionLanguage->evaluate( $expression, array_merge( - $this->variablesCollection->getVariables(), + $this->variablesCollection->getCollection(), $variables, ), ); diff --git a/src/Component/src/Symfony/ExpressionLanguage/ArgumentParserInterface.php b/src/Component/src/Symfony/ExpressionLanguage/ExpressionEvaluatorInterface.php similarity index 71% rename from src/Component/src/Symfony/ExpressionLanguage/ArgumentParserInterface.php rename to src/Component/src/Symfony/ExpressionLanguage/ExpressionEvaluatorInterface.php index 7b428b94c..9b6f5bf13 100644 --- a/src/Component/src/Symfony/ExpressionLanguage/ArgumentParserInterface.php +++ b/src/Component/src/Symfony/ExpressionLanguage/ExpressionEvaluatorInterface.php @@ -16,7 +16,7 @@ /** * @experimental */ -interface ArgumentParserInterface +interface ExpressionEvaluatorInterface { - public function parseExpression(string $expression, array $variables = []): mixed; + public function evaluateExpression(string $expression, array $variables = []): mixed; } diff --git a/src/Component/src/Symfony/ExpressionLanguage/ExpressionLanguageFactory.php b/src/Component/src/Symfony/ExpressionLanguage/ExpressionLanguageFactory.php new file mode 100644 index 000000000..8f8eece9b --- /dev/null +++ b/src/Component/src/Symfony/ExpressionLanguage/ExpressionLanguageFactory.php @@ -0,0 +1,41 @@ + $providers */ + public function __construct(private $providers) + { + Assert::allIsInstanceOf($this->providers, ExpressionFunctionProviderInterface::class); + } + + public function __invoke(): ExpressionLanguage + { + $expressionLanguage = new ExpressionLanguage(); + + foreach ($this->providers as $provider) { + $expressionLanguage->registerProvider($provider); + } + + return $expressionLanguage; + } +} diff --git a/src/Component/src/Symfony/ExpressionLanguage/RequestVariables.php b/src/Component/src/Symfony/ExpressionLanguage/RequestVariables.php index 92f021a4c..e659a06d3 100644 --- a/src/Component/src/Symfony/ExpressionLanguage/RequestVariables.php +++ b/src/Component/src/Symfony/ExpressionLanguage/RequestVariables.php @@ -18,13 +18,13 @@ /** * @experimental */ -final class RequestVariables implements VariablesInterface +final class RequestVariables implements VariablesCollectionInterface { public function __construct(private RequestStack $requestStack) { } - public function getVariables(): array + public function getCollection(): array { return [ 'request' => $this->requestStack->getCurrentRequest(), diff --git a/src/Component/src/Symfony/ExpressionLanguage/TokenVariables.php b/src/Component/src/Symfony/ExpressionLanguage/TokenVariables.php index ca9303388..ffaabc026 100644 --- a/src/Component/src/Symfony/ExpressionLanguage/TokenVariables.php +++ b/src/Component/src/Symfony/ExpressionLanguage/TokenVariables.php @@ -19,13 +19,13 @@ /** * @experimental */ -final class TokenVariables implements VariablesInterface +final class TokenVariables implements VariablesCollectionInterface { public function __construct(private ?TokenStorageInterface $tokenStorage = null) { } - public function getVariables(): array + public function getCollection(): array { if (null === $this->tokenStorage) { throw new \LogicException('The "symfony/security-bundle" must be installed and configured to use the "token" & "user" attribute. Try running "composer require symfony/security-bundle"'); diff --git a/src/Component/src/Symfony/ExpressionLanguage/VariablesCollection.php b/src/Component/src/Symfony/ExpressionLanguage/VariablesCollection.php deleted file mode 100644 index f4d9a36d0..000000000 --- a/src/Component/src/Symfony/ExpressionLanguage/VariablesCollection.php +++ /dev/null @@ -1,39 +0,0 @@ - $iterator */ - public function __construct(private iterable $iterator) - { - Assert::allIsInstanceOf($this->iterator, VariablesInterface::class); - } - - public function getVariables(): array - { - $variables = []; - - foreach ($this->iterator as $variable) { - $variables = array_merge($variables, $variable->getVariables()); - } - - return $variables; - } -} diff --git a/src/Component/src/Symfony/ExpressionLanguage/VariablesCollectionAggregate.php b/src/Component/src/Symfony/ExpressionLanguage/VariablesCollectionAggregate.php new file mode 100644 index 000000000..5ced69746 --- /dev/null +++ b/src/Component/src/Symfony/ExpressionLanguage/VariablesCollectionAggregate.php @@ -0,0 +1,38 @@ + $variablesCollection */ + public function __construct(private $variablesCollection) + { + Assert::allIsInstanceOf($this->variablesCollection, VariablesCollectionInterface::class); + } + + public function getCollection(): array + { + $collections = []; + foreach ($this->variablesCollection as $collection) { + $collections[] = $collection->getCollection(); + } + + return array_merge(...$collections); + } +} diff --git a/src/Component/src/Symfony/ExpressionLanguage/VariablesCollectionInterface.php b/src/Component/src/Symfony/ExpressionLanguage/VariablesCollectionInterface.php index 4cfc326bb..763e9c89e 100644 --- a/src/Component/src/Symfony/ExpressionLanguage/VariablesCollectionInterface.php +++ b/src/Component/src/Symfony/ExpressionLanguage/VariablesCollectionInterface.php @@ -18,5 +18,8 @@ */ interface VariablesCollectionInterface { - public function getVariables(): array; + /** + * @return array + */ + public function getCollection(): array; } diff --git a/src/Component/src/Symfony/ExpressionLanguage/VariablesInterface.php b/src/Component/src/Symfony/ExpressionLanguage/VariablesInterface.php deleted file mode 100644 index 2a41bd3e9..000000000 --- a/src/Component/src/Symfony/ExpressionLanguage/VariablesInterface.php +++ /dev/null @@ -1,22 +0,0 @@ - $value) { - $arguments[$key] = $this->argumentParser->parseExpression($value); + $arguments[$key] = $this->expressionEvaluator->evaluateExpression($value); } return $arguments; diff --git a/src/Component/src/Symfony/Routing/RedirectHandler.php b/src/Component/src/Symfony/Routing/RedirectHandler.php index 7ddec7dcd..e720e4aa6 100644 --- a/src/Component/src/Symfony/Routing/RedirectHandler.php +++ b/src/Component/src/Symfony/Routing/RedirectHandler.php @@ -17,7 +17,7 @@ use Sylius\Resource\Metadata\DeleteOperationInterface; use Sylius\Resource\Metadata\HttpOperation; use Sylius\Resource\Metadata\ResourceMetadata; -use Sylius\Resource\Symfony\ExpressionLanguage\ArgumentParserInterface; +use Sylius\Resource\Symfony\ExpressionLanguage\ExpressionEvaluatorInterface; use Sylius\Resource\Symfony\Routing\Factory\RouteName\OperationRouteNameFactoryInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; @@ -31,7 +31,7 @@ final class RedirectHandler implements RedirectHandlerInterface { public function __construct( private RouterInterface $router, - private ArgumentParserInterface $argumentParser, + private ExpressionEvaluatorInterface $expressionEvaluator, private OperationRouteNameFactoryInterface $operationRouteNameFactory, ) { } @@ -108,7 +108,7 @@ private function parseResourceValues(ResourceMetadata $resource, array $paramete $variables[$resourceName] = $data; } - $parameters[$key] = $this->argumentParser->parseExpression($value, $variables); + $parameters[$key] = $this->expressionEvaluator->evaluateExpression($value, $variables); } return $parameters;