From 9f7ef9f05e13a1fb6d41e86f6430ee691c440360 Mon Sep 17 00:00:00 2001 From: clementzarch Date: Thu, 8 Jun 2023 17:30:53 +0200 Subject: [PATCH 1/5] SQL lookup may return false. in that case, dont try to merge this result with the line --- src/Builder/AlternativeLookup.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Builder/AlternativeLookup.php b/src/Builder/AlternativeLookup.php index e094a00..de41d47 100644 --- a/src/Builder/AlternativeLookup.php +++ b/src/Builder/AlternativeLookup.php @@ -120,7 +120,14 @@ public function getNode(): Node ...array_filter( [ $this->getAlternativeLookupNode(), - $this->merge?->getNode(), + new Node\Stmt\If_( + cond: new Node\Expr\Variable('lookup'), + subNodes: [ + 'stmts' => [ + $this->merge?->getNode(), + ], + ] + ), new Node\Stmt\Return_( new Node\Expr\Variable('output') ), From 1f4b3b3ef49ad8d93767f2bce917e69556d456fe Mon Sep 17 00:00:00 2001 From: clementzarch Date: Tue, 13 Jun 2023 14:48:04 +0200 Subject: [PATCH 2/5] fix deprecation notice with nullable logger --- src/Builder/ConditionalLookup.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Builder/ConditionalLookup.php b/src/Builder/ConditionalLookup.php index 2d62d27..8f749c8 100644 --- a/src/Builder/ConditionalLookup.php +++ b/src/Builder/ConditionalLookup.php @@ -7,7 +7,6 @@ use Kiboko\Contract\Configurator\StepBuilderInterface; use Kiboko\Contract\Mapping\CompiledMapperInterface; use PhpParser\Node; -use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; final class ConditionalLookup implements StepBuilderInterface @@ -188,7 +187,8 @@ class: new Node\Name\FullyQualified(NullLogger::class) default: new Node\Expr\ConstFetch( name: new Node\Name(name: 'null'), ), - type: new Node\Name\FullyQualified(LoggerInterface::class) + type: new Node\NullableType(\Psr\Log\LoggerInterface::class), + flags: Node\Stmt\Class_::MODIFIER_PRIVATE ), ], ], From b5f38e053d56e42989fc29e7009a95466ecf899c Mon Sep 17 00:00:00 2001 From: clementzarch Date: Mon, 19 Jun 2023 14:34:50 +0200 Subject: [PATCH 3/5] add option "from" to allow to bind multiple parameters even if their number is unknown, interpret expressions in "query" when reading the configuration --- composer.json | 2 +- src/Builder/AlternativeLookup.php | 253 +++++++++++++++++------------- src/Configuration/Extractor.php | 10 +- src/Configuration/Loader.php | 14 +- src/Configuration/Lookup.php | 14 +- src/Configuration/Parameters.php | 15 +- src/Factory/Lookup.php | 13 ++ 7 files changed, 201 insertions(+), 120 deletions(-) diff --git a/composer.json b/composer.json index bc633db..b4d905b 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ }, "extra": { "branch-alias": { - "dev-main": "0.4.x-dev" + "dev-main": "0.5.x-dev" }, "gyroscops": { "plugins": ["Kiboko\\Plugin\\SQL\\Service"] diff --git a/src/Builder/AlternativeLookup.php b/src/Builder/AlternativeLookup.php index e094a00..54eb595 100644 --- a/src/Builder/AlternativeLookup.php +++ b/src/Builder/AlternativeLookup.php @@ -11,7 +11,7 @@ final class AlternativeLookup implements StepBuilderInterface { - /** @var array */ + /** @var array */ private array $parameters = []; private ?Builder $merge = null; @@ -34,71 +34,78 @@ public function withState(Node\Expr $state): StepBuilderInterface return $this; } - public function addStringParam(int|string $key, Node\Expr $param): StepBuilderInterface + public function addStringParam(int|string $key, Node\Expr $param, null|bool $iterable = false): StepBuilderInterface { $this->parameters[$key] = [ 'value' => $param, 'type' => 'string', + 'iterable' => $iterable, ]; return $this; } - public function addIntegerParam(int|string $key, Node\Expr $param): StepBuilderInterface + public function addIntegerParam(int|string $key, Node\Expr $param, null|bool $iterable = false): StepBuilderInterface { $this->parameters[$key] = [ 'value' => $param, 'type' => 'integer', + 'iterable' => $iterable, ]; return $this; } - public function addBooleanParam(int|string $key, Node\Expr $param): StepBuilderInterface + public function addBooleanParam(int|string $key, Node\Expr $param, null|bool $iterable = false): StepBuilderInterface { $this->parameters[$key] = [ 'value' => $param, 'type' => 'boolean', + 'iterable' => $iterable, ]; return $this; } - public function addDateParam(int|string $key, Node\Expr $param): self + public function addDateParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self { $this->parameters[$key] = [ 'value' => $param, 'type' => 'date', + 'iterable' => $iterable, ]; return $this; } - public function addDateTimeParam(int|string $key, Node\Expr $param): self + public function addDateTimeParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self { $this->parameters[$key] = [ 'value' => $param, 'type' => 'datetime', + 'iterable' => $iterable, ]; return $this; } - public function addJSONParam(int|string $key, Node\Expr $param): self + public function addJSONParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self { $this->parameters[$key] = [ 'value' => $param, 'type' => 'json', + 'iterable' => $iterable, ]; return $this; } - public function addBinaryParam(int|string $key, Node\Expr $param): self + public function addBinaryParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self { $this->parameters[$key] = [ 'value' => $param, 'type' => 'binary', + 'iterable' => $iterable, ]; return $this; @@ -151,7 +158,7 @@ public function getAlternativeLookupNode(): Node ), ), ), - ...$this->compileParameters(), + ...$this->getParameters(), new Node\Stmt\Expression( expr: new Node\Expr\MethodCall( var: new Node\Expr\Variable('stmt'), @@ -163,7 +170,7 @@ public function getAlternativeLookupNode(): Node var: new Node\Expr\Variable('data'), expr: new Node\Expr\MethodCall( var: new Node\Expr\Variable('stmt'), - name: new Node\Identifier('fetch'), + name: new Node\Identifier('fetchAll'), args: [ new Node\Arg( new Node\Expr\ClassConstFetch( @@ -233,121 +240,141 @@ class: new Node\Name\FullyQualified('PDO'), ))->getNode(); } - public function compileParameters(): iterable + public function getParameters(): iterable { foreach ($this->parameters as $key => $parameter) { - yield match ($parameter['type']) { - 'datetime' => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('stmt'), - name: new Node\Identifier('bindValue'), - args: [ - new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) - ), - new Node\Arg( - value: new Node\Expr\StaticCall( - class: new Node\Name('DateTimeImmutable'), - name: new Node\Name('createFromFormat'), - args: [ - new Node\Arg( - value: new Node\Scalar\String_('YYYY-MM-DD HH:MI:SS') - ), - new Node\Arg( - value: $parameter['value'] - ), - ], + if (\array_key_exists('iterable', $parameter) && true === $parameter['iterable']) { + yield new Node\Stmt\Foreach_( + expr: $parameter['value'], + valueVar: new Node\Expr\Variable('value'), + subNodes: [ + 'keyVar' => new Node\Expr\Variable('key'), + 'stmts' => [ + $this->compileParameters( + new Node\Arg( + new Node\Expr\BinaryOp\Concat( + new Node\Scalar\String_($key.'_'), + new Node\Expr\Variable('key'), + ) ), + [ + 'type' => $parameter['type'], + 'value' => new Node\Expr\Variable('value'), + ] ), - $this->compileParameterType($parameter), ], - ), - ), - 'date' => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('stmt'), - name: new Node\Identifier('bindValue'), - args: [ - new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) - ), - new Node\Arg( - value: new Node\Expr\StaticCall( - class: new Node\Name('DateTimeImmutable'), - name: new Node\Name('createFromFormat'), - args: [ - new Node\Arg( - value: new Node\Scalar\String_('YYYY-MM-DD') - ), - new Node\Arg( - value: $parameter['value'] - ), - ], - ), + ] + ); + } else { + yield $this->compileParameters($key, $parameter); + } + } + } + + private function compileParameters(int|string|Node\Arg $key, array $parameter): Node\Stmt\Expression + { + return match ($parameter['type']) { + 'datetime' => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('stmt'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + value: new Node\Expr\StaticCall( + class: new Node\Name('DateTimeImmutable'), + name: new Node\Name('createFromFormat'), + args: [ + new Node\Arg( + value: new Node\Scalar\String_('YYYY-MM-DD HH:MI:SS') + ), + new Node\Arg( + value: $parameter['value'] + ), + ], ), - $this->compileParameterType($parameter), - ], - ), + ), + $this->compileParameterType($parameter), + ], ), - 'json' => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('stmt'), - name: new Node\Identifier('bindValue'), - args: [ - new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) - ), - new Node\Arg( - new Node\Expr\FuncCall( - name: new Node\Name('json_decode'), - args: [ - new Node\Arg( - value: $parameter['value'] - ), - ], - ), + ), + 'date' => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('stmt'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + value: new Node\Expr\StaticCall( + class: new Node\Name('DateTimeImmutable'), + name: new Node\Name('createFromFormat'), + args: [ + new Node\Arg( + value: new Node\Scalar\String_('YYYY-MM-DD') + ), + new Node\Arg( + value: $parameter['value'] + ), + ], ), - $this->compileParameterType($parameter), - ], - ), + ), + $this->compileParameterType($parameter), + ], ), - default => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('stmt'), - name: new Node\Identifier('bindValue'), - args: [ - new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) - ), - new Node\Arg( - $parameter['value'] + ), + 'json' => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('stmt'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + new Node\Expr\FuncCall( + name: new Node\Name('json_decode'), + args: [ + new Node\Arg( + value: $parameter['value'] + ), + ], ), - $this->compileParameterType($parameter), - ], - ), + ), + $this->compileParameterType($parameter), + ], + ), + ), + default => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('stmt'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + $parameter['value'] + ), + $this->compileParameterType($parameter), + ], ), - }; + ), + }; + } + + private function compileParameterKey(int|string|Node\Arg $key): Node\Arg + { + if (\is_string($key)) { + return new Node\Arg( + new Node\Scalar\Encapsed([ + new Node\Scalar\EncapsedStringPart(':'), + new Node\Scalar\EncapsedStringPart($key), + ]) + ); + } + if ($key instanceof Node\Arg) { + return $key; } + + return new Node\Arg( + new Node\Scalar\LNumber($key) + ); } private function compileParameterType(array $parameter): Node\Arg diff --git a/src/Configuration/Extractor.php b/src/Configuration/Extractor.php index 3255b1f..4a31f9a 100644 --- a/src/Configuration/Extractor.php +++ b/src/Configuration/Extractor.php @@ -7,6 +7,9 @@ use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; +use function Kiboko\Component\SatelliteToolbox\Configuration\asExpression; +use function Kiboko\Component\SatelliteToolbox\Configuration\isExpression; + final class Extractor implements ConfigurationInterface { public function getConfigTreeBuilder(): TreeBuilder @@ -15,7 +18,12 @@ public function getConfigTreeBuilder(): TreeBuilder /* @phpstan-ignore-next-line */ $builder->getRootNode() - ->append((new Query())->getConfigTreeBuilder()->getRootNode()) + ->append((new Query())->getConfigTreeBuilder()->getRootNode() + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ) ->append((new Parameters())->getConfigTreeBuilder()->getRootNode()) ; diff --git a/src/Configuration/Loader.php b/src/Configuration/Loader.php index 79c60e3..52b7538 100644 --- a/src/Configuration/Loader.php +++ b/src/Configuration/Loader.php @@ -35,7 +35,12 @@ public function getConfigTreeBuilder(): TreeBuilder return $data; }) ->end() - ->append((new Query())->getConfigTreeBuilder()->getRootNode()) + ->append((new Query())->getConfigTreeBuilder()->getRootNode() + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ) ->append((new Parameters())->getConfigTreeBuilder()->getRootNode()) ->children() ->append((new FastMap\Configuration('merge'))->getConfigTreeBuilder()->getRootNode()) @@ -66,7 +71,12 @@ private function getConditionalTreeBuilder(): TreeBuilder ->then(asExpression()) ->end() ->end() - ->append((new Query())->getConfigTreeBuilder()->getRootNode()) + ->append((new Query())->getConfigTreeBuilder()->getRootNode() + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ) ->append((new Parameters())->getConfigTreeBuilder()->getRootNode()) ->append((new FastMap\Configuration('merge'))->getConfigTreeBuilder()->getRootNode()) ->end() diff --git a/src/Configuration/Lookup.php b/src/Configuration/Lookup.php index 531cb4a..7e7bb39 100644 --- a/src/Configuration/Lookup.php +++ b/src/Configuration/Lookup.php @@ -35,7 +35,12 @@ public function getConfigTreeBuilder(): TreeBuilder return $data; }) ->end() - ->append((new Query())->getConfigTreeBuilder()->getRootNode()) + ->append((new Query())->getConfigTreeBuilder()->getRootNode() + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ) ->append((new Parameters())->getConfigTreeBuilder()->getRootNode()) ->children() ->append((new FastMap\Configuration('merge'))->getConfigTreeBuilder()->getRootNode()) @@ -66,7 +71,12 @@ private function getConditionalTreeBuilder(): TreeBuilder ->then(asExpression()) ->end() ->end() - ->append((new Query())->getConfigTreeBuilder()->getRootNode()) + ->append((new Query())->getConfigTreeBuilder()->getRootNode() + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ) ->append((new Parameters())->getConfigTreeBuilder()->getRootNode()) ->append((new FastMap\Configuration('merge'))->getConfigTreeBuilder()->getRootNode()) ->end() diff --git a/src/Configuration/Parameters.php b/src/Configuration/Parameters.php index 80d6b27..e9f271e 100644 --- a/src/Configuration/Parameters.php +++ b/src/Configuration/Parameters.php @@ -9,6 +9,7 @@ use function Kiboko\Component\SatelliteToolbox\Configuration\asExpression; use function Kiboko\Component\SatelliteToolbox\Configuration\isExpression; +use function Kiboko\Component\SatelliteToolbox\Configuration\mutuallyExclusiveFields; class Parameters implements ConfigurationInterface { @@ -24,9 +25,21 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->useAttributeAsKey('key', false) ->arrayPrototype() + ->validate() + ->always(mutuallyExclusiveFields('value', 'from')) + ->end() + ->validate() + ->ifTrue(fn (array $data) => !\array_key_exists('value', $data) && !\array_key_exists('from', $data)) + ->thenInvalid('Your configuration should either contain the "value" or the "from" key.') + ->end() ->children() ->scalarNode('value') - ->isRequired() + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ->end() + ->scalarNode('from') ->validate() ->ifTrue(isExpression()) ->then(asExpression()) diff --git a/src/Factory/Lookup.php b/src/Factory/Lookup.php index f30159a..166fe58 100644 --- a/src/Factory/Lookup.php +++ b/src/Factory/Lookup.php @@ -127,34 +127,47 @@ public function compile(array $config): SQL\Factory\Repository\Lookup if (\array_key_exists('parameters', $alternative)) { foreach ($alternative['parameters'] as $key => $parameter) { + $isIterable = false; + if (\array_key_exists('from', $parameter) && isset($parameter['from'])) { + $parameter['value'] = $parameter['from']; + $isIterable = true; + } + match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { 'integer' => $alternativeBuilder->addIntegerParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), + $isIterable, ), 'boolean' => $alternativeBuilder->addBooleanParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), + $isIterable, ), 'date' => $alternativeBuilder->addDateParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), + $isIterable, ), 'datetime' => $alternativeBuilder->addDateTimeParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), + $isIterable, ), 'json' => $alternativeBuilder->addJSONParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), + $isIterable, ), 'binary' => $alternativeBuilder->addBinaryParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), + $isIterable, ), default => $alternativeBuilder->addStringParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), + $isIterable, ), }; } From 9b1a3222de088f6d47bcea6effb9ba0e8e58dee3 Mon Sep 17 00:00:00 2001 From: clementzarch Date: Wed, 21 Jun 2023 12:02:32 +0200 Subject: [PATCH 4/5] handle iterable parameters for Lookup, Loader, Conditional Loader, don't do a fetchAll, the user should CONCAT if there are multiple results --- src/Builder/AlternativeLoader.php | 288 +++++++++++++++++++---------- src/Builder/AlternativeLookup.php | 147 ++++++++++----- src/Builder/Loader.php | 289 ++++++++++++++++++++---------- src/Factory/Loader.php | 164 ++++++++++++----- src/Factory/Lookup.php | 167 +++++++++++------ 5 files changed, 712 insertions(+), 343 deletions(-) diff --git a/src/Builder/AlternativeLoader.php b/src/Builder/AlternativeLoader.php index 0a9336e..dc7a326 100644 --- a/src/Builder/AlternativeLoader.php +++ b/src/Builder/AlternativeLoader.php @@ -11,6 +11,8 @@ final class AlternativeLoader implements StepBuilderInterface { /** @var array */ private array $parameters = []; + /** @var array */ + private array $parametersLists = []; public function __construct(private readonly Node\Expr $query) { @@ -101,6 +103,76 @@ public function addBinaryParam(int|string $key, Node\Expr $param): self return $this; } + public function addStringParamList(int|string $key, Node\Expr $param): StepBuilderInterface + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'string', + ]; + + return $this; + } + + public function addIntegerParamList(int|string $key, Node\Expr $param): StepBuilderInterface + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'integer', + ]; + + return $this; + } + + public function addBooleanParamList(int|string $key, Node\Expr $param): StepBuilderInterface + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'boolean', + ]; + + return $this; + } + + public function addDateParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'date', + ]; + + return $this; + } + + public function addDateTimeParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'datetime', + ]; + + return $this; + } + + public function addJSONParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'json', + ]; + + return $this; + } + + public function addBinaryParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'binary', + ]; + + return $this; + } + public function getNode(): Node { return new Node\Stmt\Expression( @@ -126,7 +198,7 @@ public function getNode(): Node ) ) ), - ...$this->compileParameters(), + ...$this->getParameters(), new Node\Stmt\Expression( expr: new Node\Expr\MethodCall( var: new Node\Expr\Variable('statement'), @@ -147,115 +219,135 @@ public function getNode(): Node ); } - public function compileParameters(): iterable + public function getParameters(): iterable { foreach ($this->parameters as $key => $parameter) { - yield match ($parameter['type']) { - 'datetime' => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('statement'), - name: new Node\Identifier('bindValue'), - args: [ + yield $this->compileParameter($key, $parameter); + } + + foreach ($this->parametersLists as $key => $parameter) { + yield new Node\Stmt\Foreach_( + expr: $parameter['value'], + valueVar: new Node\Expr\Variable('value'), + subNodes: [ + 'keyVar' => new Node\Expr\Variable('key'), + 'stmts' => [ + $this->compileParameter( new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) + new Node\Expr\BinaryOp\Concat( + new Node\Scalar\String_($key.'_'), + new Node\Expr\Variable('key'), + ) ), - new Node\Arg( - value: new Node\Expr\MethodCall( - var: $parameter['value'], - name: new Node\Name('format'), - args: [ - new Node\Arg( - value: new Node\Scalar\String_('YYYY-MM-DD HH:MI:SS') - ), - ], - ), + [ + 'type' => $parameter['type'], + 'value' => new Node\Expr\Variable('value'), + ] + ), + ], + ] + ); + } + } + + public function compileParameter(int|string|Node\Arg $key, array $parameter): Node\Stmt\Expression + { + return match ($parameter['type']) { + 'datetime' => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('statement'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + value: new Node\Expr\MethodCall( + var: $parameter['value'], + name: new Node\Name('format'), + args: [ + new Node\Arg( + value: new Node\Scalar\String_('YYYY-MM-DD HH:MI:SS') + ), + ], ), - $this->compileParameterType($parameter), - ], - ), + ), + $this->compileParameterType($parameter), + ], ), - 'date' => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('statement'), - name: new Node\Identifier('bindValue'), - args: [ - new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) - ), - new Node\Arg( - value: new Node\Expr\MethodCall( - var: $parameter['value'], - name: new Node\Name('format'), - args: [ - new Node\Arg( - value: new Node\Scalar\String_('YYYY-MM-DD') - ), - ], - ), + ), + 'date' => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('statement'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + value: new Node\Expr\MethodCall( + var: $parameter['value'], + name: new Node\Name('format'), + args: [ + new Node\Arg( + value: new Node\Scalar\String_('YYYY-MM-DD') + ), + ], ), - $this->compileParameterType($parameter), - ], - ), + ), + $this->compileParameterType($parameter), + ], ), - 'json' => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('statement'), - name: new Node\Identifier('bindValue'), - args: [ - new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) - ), - new Node\Arg( - new Node\Expr\FuncCall( - name: new Node\Name('json_encode'), - args: [ - new Node\Arg( - value: $parameter['value'] - ), - ], - ), + ), + 'json' => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('statement'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + new Node\Expr\FuncCall( + name: new Node\Name('json_encode'), + args: [ + new Node\Arg( + value: $parameter['value'] + ), + ], ), - $this->compileParameterType($parameter), - ], - ), + ), + $this->compileParameterType($parameter), + ], ), - default => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('statement'), - name: new Node\Identifier('bindValue'), - args: [ - new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) - ), - new Node\Arg( - $parameter['value'] - ), - $this->compileParameterType($parameter), - ], - ), + ), + default => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('statement'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + $parameter['value'] + ), + $this->compileParameterType($parameter), + ], ), - }; + ), + }; + } + + private function compileParameterKey(int|string|Node\Arg $key): Node\Arg + { + if (\is_string($key)) { + return new Node\Arg( + new Node\Scalar\Encapsed([ + new Node\Scalar\EncapsedStringPart(':'), + new Node\Scalar\EncapsedStringPart($key), + ]) + ); } + if ($key instanceof Node\Arg) { + return $key; + } + + return new Node\Arg( + new Node\Scalar\LNumber($key) + ); } private function compileParameterType(array $parameter): Node\Arg diff --git a/src/Builder/AlternativeLookup.php b/src/Builder/AlternativeLookup.php index 9046013..69b6154 100644 --- a/src/Builder/AlternativeLookup.php +++ b/src/Builder/AlternativeLookup.php @@ -11,8 +11,10 @@ final class AlternativeLookup implements StepBuilderInterface { - /** @var array */ + /** @var array */ private array $parameters = []; + /** @var array */ + private array $parametersLists = []; private ?Builder $merge = null; public function __construct(private readonly Node\Expr $query) @@ -34,78 +36,71 @@ public function withState(Node\Expr $state): StepBuilderInterface return $this; } - public function addStringParam(int|string $key, Node\Expr $param, null|bool $iterable = false): StepBuilderInterface + public function addStringParam(int|string $key, Node\Expr $param): StepBuilderInterface { $this->parameters[$key] = [ 'value' => $param, 'type' => 'string', - 'iterable' => $iterable, ]; return $this; } - public function addIntegerParam(int|string $key, Node\Expr $param, null|bool $iterable = false): StepBuilderInterface + public function addIntegerParam(int|string $key, Node\Expr $param): StepBuilderInterface { $this->parameters[$key] = [ 'value' => $param, 'type' => 'integer', - 'iterable' => $iterable, ]; return $this; } - public function addBooleanParam(int|string $key, Node\Expr $param, null|bool $iterable = false): StepBuilderInterface + public function addBooleanParam(int|string $key, Node\Expr $param): StepBuilderInterface { $this->parameters[$key] = [ 'value' => $param, 'type' => 'boolean', - 'iterable' => $iterable, ]; return $this; } - public function addDateParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self + public function addDateParam(int|string $key, Node\Expr $param): self { $this->parameters[$key] = [ 'value' => $param, 'type' => 'date', - 'iterable' => $iterable, ]; return $this; } - public function addDateTimeParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self + public function addDateTimeParam(int|string $key, Node\Expr $param): self { $this->parameters[$key] = [ 'value' => $param, 'type' => 'datetime', - 'iterable' => $iterable, ]; return $this; } - public function addJSONParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self + public function addJSONParam(int|string $key, Node\Expr $param): self { $this->parameters[$key] = [ 'value' => $param, 'type' => 'json', - 'iterable' => $iterable, ]; return $this; } - public function addBinaryParam(int|string $key, Node\Expr $param, null|bool $iterable = false): self + public function addBinaryParam(int|string $key, Node\Expr $param): self { $this->parameters[$key] = [ 'value' => $param, 'type' => 'binary', - 'iterable' => $iterable, ]; return $this; @@ -118,6 +113,76 @@ public function withMerge(Builder $merge): self return $this; } + public function addStringParamList(int|string $key, Node\Expr $param): StepBuilderInterface + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'string', + ]; + + return $this; + } + + public function addIntegerParamList(int|string $key, Node\Expr $param): StepBuilderInterface + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'integer', + ]; + + return $this; + } + + public function addBooleanParamList(int|string $key, Node\Expr $param): StepBuilderInterface + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'boolean', + ]; + + return $this; + } + + public function addDateParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'date', + ]; + + return $this; + } + + public function addDateTimeParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'datetime', + ]; + + return $this; + } + + public function addJSONParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'json', + ]; + + return $this; + } + + public function addBinaryParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'binary', + ]; + + return $this; + } + public function getNode(): Node { return (new IsolatedValueAppendingBuilder( @@ -177,7 +242,7 @@ public function getAlternativeLookupNode(): Node var: new Node\Expr\Variable('data'), expr: new Node\Expr\MethodCall( var: new Node\Expr\Variable('stmt'), - name: new Node\Identifier('fetchAll'), + name: new Node\Identifier('fetch'), args: [ new Node\Arg( new Node\Expr\ClassConstFetch( @@ -250,35 +315,35 @@ class: new Node\Name\FullyQualified('PDO'), public function getParameters(): iterable { foreach ($this->parameters as $key => $parameter) { - if (\array_key_exists('iterable', $parameter) && true === $parameter['iterable']) { - yield new Node\Stmt\Foreach_( - expr: $parameter['value'], - valueVar: new Node\Expr\Variable('value'), - subNodes: [ - 'keyVar' => new Node\Expr\Variable('key'), - 'stmts' => [ - $this->compileParameters( - new Node\Arg( - new Node\Expr\BinaryOp\Concat( - new Node\Scalar\String_($key.'_'), - new Node\Expr\Variable('key'), - ) - ), - [ - 'type' => $parameter['type'], - 'value' => new Node\Expr\Variable('value'), - ] + yield $this->compileParameter($key, $parameter); + } + + foreach ($this->parametersLists as $key => $parameter) { + yield new Node\Stmt\Foreach_( + expr: $parameter['value'], + valueVar: new Node\Expr\Variable('value'), + subNodes: [ + 'keyVar' => new Node\Expr\Variable('key'), + 'stmts' => [ + $this->compileParameter( + new Node\Arg( + new Node\Expr\BinaryOp\Concat( + new Node\Scalar\String_($key.'_'), + new Node\Expr\Variable('key'), + ) ), - ], - ] - ); - } else { - yield $this->compileParameters($key, $parameter); - } + [ + 'type' => $parameter['type'], + 'value' => new Node\Expr\Variable('value'), + ] + ), + ], + ] + ); } } - private function compileParameters(int|string|Node\Arg $key, array $parameter): Node\Stmt\Expression + private function compileParameter(int|string|Node\Arg $key, array $parameter): Node\Stmt\Expression { return match ($parameter['type']) { 'datetime' => new Node\Stmt\Expression( diff --git a/src/Builder/Loader.php b/src/Builder/Loader.php index 39b642a..94c051a 100644 --- a/src/Builder/Loader.php +++ b/src/Builder/Loader.php @@ -14,7 +14,10 @@ final class Loader implements StepBuilderInterface private array $beforeQueries = []; /** @var array */ private array $afterQueries = []; + /** @var array */ private array $parameters = []; + /** @var array */ + private array $parametersLists = []; public function __construct( private readonly Node\Expr $query, @@ -144,6 +147,76 @@ public function addBinaryParam(int|string $key, Node\Expr $param): self return $this; } + public function addStringParamList(int|string $key, Node\Expr $param): StepBuilderInterface + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'string', + ]; + + return $this; + } + + public function addIntegerParamList(int|string $key, Node\Expr $param): StepBuilderInterface + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'integer', + ]; + + return $this; + } + + public function addBooleanParamList(int|string $key, Node\Expr $param): StepBuilderInterface + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'boolean', + ]; + + return $this; + } + + public function addDateParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'date', + ]; + + return $this; + } + + public function addDateTimeParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'datetime', + ]; + + return $this; + } + + public function addJSONParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'json', + ]; + + return $this; + } + + public function addBinaryParamList(int|string $key, Node\Expr $param): self + { + $this->parametersLists[$key] = [ + 'value' => $param, + 'type' => 'binary', + ]; + + return $this; + } + public function getNode(): Node { return new Node\Expr\New_( @@ -168,7 +241,7 @@ class: new Node\Name\FullyQualified(\Kiboko\Component\Flow\SQL\Loader::class), ), ], 'stmts' => [ - ...$this->compileParameters(), + ...$this->getParameters(), ], ], )) @@ -234,115 +307,135 @@ public function compileAfterQueries(): Node\Expr ); } - public function compileParameters(): iterable + public function getParameters(): iterable { foreach ($this->parameters as $key => $parameter) { - yield match ($parameter['type']) { - 'datetime' => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('statement'), - name: new Node\Identifier('bindValue'), - args: [ + yield $this->compileParameter($key, $parameter); + } + + foreach ($this->parametersLists as $key => $parameter) { + yield new Node\Stmt\Foreach_( + expr: $parameter['value'], + valueVar: new Node\Expr\Variable('value'), + subNodes: [ + 'keyVar' => new Node\Expr\Variable('key'), + 'stmts' => [ + $this->compileParameter( new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) + new Node\Expr\BinaryOp\Concat( + new Node\Scalar\String_($key.'_'), + new Node\Expr\Variable('key'), + ) ), - new Node\Arg( - value: new Node\Expr\MethodCall( - var: $parameter['value'], - name: new Node\Name('format'), - args: [ - new Node\Arg( - value: new Node\Scalar\String_('YYYY-MM-DD HH:MI:SS') - ), - ], - ), + [ + 'type' => $parameter['type'], + 'value' => new Node\Expr\Variable('value'), + ] + ), + ], + ] + ); + } + } + + public function compileParameter(int|string|Node\Arg $key, array $parameter): Node\Stmt\Expression + { + return match ($parameter['type']) { + 'datetime' => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('statement'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + value: new Node\Expr\MethodCall( + var: $parameter['value'], + name: new Node\Name('format'), + args: [ + new Node\Arg( + value: new Node\Scalar\String_('YYYY-MM-DD HH:MI:SS') + ), + ], ), - $this->compileParameterType($parameter), - ], - ), + ), + $this->compileParameterType($parameter), + ], ), - 'date' => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('statement'), - name: new Node\Identifier('bindValue'), - args: [ - new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) - ), - new Node\Arg( - value: new Node\Expr\MethodCall( - var: $parameter['value'], - name: new Node\Name('format'), - args: [ - new Node\Arg( - value: new Node\Scalar\String_('YYYY-MM-DD') - ), - ], - ), + ), + 'date' => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('statement'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + value: new Node\Expr\MethodCall( + var: $parameter['value'], + name: new Node\Name('format'), + args: [ + new Node\Arg( + value: new Node\Scalar\String_('YYYY-MM-DD') + ), + ], ), - $this->compileParameterType($parameter), - ], - ), + ), + $this->compileParameterType($parameter), + ], ), - 'json' => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('statement'), - name: new Node\Identifier('bindValue'), - args: [ - new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) - ), - new Node\Arg( - new Node\Expr\FuncCall( - name: new Node\Name('json_encode'), - args: [ - new Node\Arg( - value: $parameter['value'] - ), - ], - ), + ), + 'json' => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('statement'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + new Node\Expr\FuncCall( + name: new Node\Name('json_encode'), + args: [ + new Node\Arg( + value: $parameter['value'] + ), + ], ), - $this->compileParameterType($parameter), - ], - ), + ), + $this->compileParameterType($parameter), + ], ), - default => new Node\Stmt\Expression( - new Node\Expr\MethodCall( - var: new Node\Expr\Variable('statement'), - name: new Node\Identifier('bindValue'), - args: [ - new Node\Arg( - \is_string($key) ? new Node\Scalar\Encapsed( - [ - new Node\Scalar\EncapsedStringPart(':'), - new Node\Scalar\EncapsedStringPart($key), - ] - ) : new Node\Scalar\LNumber($key) - ), - new Node\Arg( - $parameter['value'] - ), - $this->compileParameterType($parameter), - ], - ), + ), + default => new Node\Stmt\Expression( + new Node\Expr\MethodCall( + var: new Node\Expr\Variable('statement'), + name: new Node\Identifier('bindValue'), + args: [ + $this->compileParameterKey($key), + new Node\Arg( + $parameter['value'] + ), + $this->compileParameterType($parameter), + ], ), - }; + ), + }; + } + + private function compileParameterKey(int|string|Node\Arg $key): Node\Arg + { + if (\is_string($key)) { + return new Node\Arg( + new Node\Scalar\Encapsed([ + new Node\Scalar\EncapsedStringPart(':'), + new Node\Scalar\EncapsedStringPart($key), + ]) + ); + } + if ($key instanceof Node\Arg) { + return $key; } + + return new Node\Arg( + new Node\Scalar\LNumber($key) + ); } private function compileParameterType(array $parameter): Node\Arg diff --git a/src/Factory/Loader.php b/src/Factory/Loader.php index 2dce588..d36cfd6 100644 --- a/src/Factory/Loader.php +++ b/src/Factory/Loader.php @@ -59,80 +59,146 @@ public function compile(array $config): SQL\Factory\Repository\Loader if (\array_key_exists('parameters', $config)) { foreach ($config['parameters'] as $key => $parameter) { - match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { - 'integer' => $loader->addIntegerParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - 'boolean' => $loader->addBooleanParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - 'date' => $loader->addDateParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - 'datetime' => $loader->addDateTimeParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - 'json' => $loader->addJSONParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - 'binary' => $loader->addBinaryParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - default => $loader->addStringParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - }; - } - } - } else { - $loader = new SQL\Builder\ConditionalLoader(); - - foreach ($config['conditional'] as $alternative) { - $alternativeLoaderBuilder = new SQL\Builder\AlternativeLoader( - compileValueWhenExpression($this->interpreter, $alternative['query']) - ); - - if (\array_key_exists('parameters', $alternative)) { - foreach ($alternative['parameters'] as $key => $parameter) { + if (\array_key_exists('from', $parameter) && isset($parameter['from'])) { match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { - 'integer' => $alternativeLoaderBuilder->addIntegerParam( + 'integer' => $loader->addIntegerParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'boolean' => $loader->addBooleanParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'date' => $loader->addDateParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'datetime' => $loader->addDateTimeParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'json' => $loader->addJSONParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'binary' => $loader->addBinaryParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + default => $loader->addStringParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + }; + } else { + match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { + 'integer' => $loader->addIntegerParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), ), - 'boolean' => $alternativeLoaderBuilder->addBooleanParam( + 'boolean' => $loader->addBooleanParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), ), - 'date' => $alternativeLoaderBuilder->addDateParam( + 'date' => $loader->addDateParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), ), - 'datetime' => $alternativeLoaderBuilder->addDateTimeParam( + 'datetime' => $loader->addDateTimeParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), ), - 'json' => $alternativeLoaderBuilder->addJSONParam( + 'json' => $loader->addJSONParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), ), - 'binary' => $alternativeLoaderBuilder->addBinaryParam( + 'binary' => $loader->addBinaryParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), ), - default => $alternativeLoaderBuilder->addStringParam( + default => $loader->addStringParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), ), }; } } + } + } else { + $loader = new SQL\Builder\ConditionalLoader(); + + foreach ($config['conditional'] as $alternative) { + $alternativeLoaderBuilder = new SQL\Builder\AlternativeLoader( + compileValueWhenExpression($this->interpreter, $alternative['query']) + ); + + if (\array_key_exists('parameters', $alternative)) { + foreach ($alternative['parameters'] as $key => $parameter) { + if (\array_key_exists('from', $parameter) && isset($parameter['from'])) { + match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { + 'integer' => $alternativeLoaderBuilder->addIntegerParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']) + ), + 'boolean' => $alternativeLoaderBuilder->addBooleanParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']) + ), + 'date' => $alternativeLoaderBuilder->addDateParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']) + ), + 'datetime' => $alternativeLoaderBuilder->addDateTimeParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']) + ), + 'json' => $alternativeLoaderBuilder->addJSONParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']) + ), + 'binary' => $alternativeLoaderBuilder->addBinaryParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']) + ), + default => $alternativeLoaderBuilder->addStringParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']) + ), + }; + } else { + match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { + 'integer' => $alternativeLoaderBuilder->addIntegerParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']) + ), + 'boolean' => $alternativeLoaderBuilder->addBooleanParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']) + ), + 'date' => $alternativeLoaderBuilder->addDateParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']) + ), + 'datetime' => $alternativeLoaderBuilder->addDateTimeParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']) + ), + 'json' => $alternativeLoaderBuilder->addJSONParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']) + ), + 'binary' => $alternativeLoaderBuilder->addBinaryParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']) + ), + default => $alternativeLoaderBuilder->addStringParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']) + ), + }; + } + } + } $loader->addAlternative( compileValueWhenExpression($this->interpreter, $alternative['condition']), diff --git a/src/Factory/Lookup.php b/src/Factory/Lookup.php index 166fe58..3ac6f19 100644 --- a/src/Factory/Lookup.php +++ b/src/Factory/Lookup.php @@ -83,95 +83,148 @@ public function compile(array $config): SQL\Factory\Repository\Lookup if (\array_key_exists('parameters', $config)) { foreach ($config['parameters'] as $key => $parameter) { - match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { - 'integer' => $alternativeBuilder->addIntegerParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - 'boolean' => $alternativeBuilder->addBooleanParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - 'date' => $alternativeBuilder->addDateParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - 'datetime' => $alternativeBuilder->addDateTimeParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - 'json' => $alternativeBuilder->addJSONParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - 'binary' => $alternativeBuilder->addBinaryParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - default => $alternativeBuilder->addStringParam( - $key, - compileValueWhenExpression($this->interpreter, $parameter['value']), - ), - }; - } - } - - $this->merge($alternativeBuilder, $config); - } else { - $lookup = new SQL\Builder\ConditionalLookup(); - - foreach ($config['conditional'] as $alternative) { - $alternativeBuilder = new SQL\Builder\AlternativeLookup( - compileValueWhenExpression($this->interpreter, $alternative['query']) - ); - - if (\array_key_exists('parameters', $alternative)) { - foreach ($alternative['parameters'] as $key => $parameter) { - $isIterable = false; - if (\array_key_exists('from', $parameter) && isset($parameter['from'])) { - $parameter['value'] = $parameter['from']; - $isIterable = true; - } - + if (\array_key_exists('from', $parameter) && isset($parameter['from'])) { + match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { + 'integer' => $alternativeBuilder->addIntegerParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'boolean' => $alternativeBuilder->addBooleanParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'date' => $alternativeBuilder->addDateParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'datetime' => $alternativeBuilder->addDateTimeParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'json' => $alternativeBuilder->addJSONParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'binary' => $alternativeBuilder->addBinaryParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + default => $alternativeBuilder->addStringParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + }; + } else { match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { 'integer' => $alternativeBuilder->addIntegerParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), - $isIterable, ), 'boolean' => $alternativeBuilder->addBooleanParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), - $isIterable, ), 'date' => $alternativeBuilder->addDateParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), - $isIterable, ), 'datetime' => $alternativeBuilder->addDateTimeParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), - $isIterable, ), 'json' => $alternativeBuilder->addJSONParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), - $isIterable, ), 'binary' => $alternativeBuilder->addBinaryParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), - $isIterable, ), default => $alternativeBuilder->addStringParam( $key, compileValueWhenExpression($this->interpreter, $parameter['value']), - $isIterable, ), }; } } + } + + $this->merge($alternativeBuilder, $config); + } else { + $lookup = new SQL\Builder\ConditionalLookup(); + + foreach ($config['conditional'] as $alternative) { + $alternativeBuilder = new SQL\Builder\AlternativeLookup( + compileValueWhenExpression($this->interpreter, $alternative['query']) + ); + + if (\array_key_exists('parameters', $alternative)) { + foreach ($alternative['parameters'] as $key => $parameter) { + if (\array_key_exists('from', $parameter) && isset($parameter['from'])) { + match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { + 'integer' => $alternativeBuilder->addIntegerParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'boolean' => $alternativeBuilder->addBooleanParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'date' => $alternativeBuilder->addDateParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'datetime' => $alternativeBuilder->addDateTimeParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'json' => $alternativeBuilder->addJSONParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + 'binary' => $alternativeBuilder->addBinaryParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + default => $alternativeBuilder->addStringParamList( + $key, + compileValueWhenExpression($this->interpreter, $parameter['from']), + ), + }; + } else { + match (\array_key_exists('type', $parameter) ? $parameter['type'] : null) { + 'integer' => $alternativeBuilder->addIntegerParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']), + ), + 'boolean' => $alternativeBuilder->addBooleanParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']), + ), + 'date' => $alternativeBuilder->addDateParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']), + ), + 'datetime' => $alternativeBuilder->addDateTimeParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']), + ), + 'json' => $alternativeBuilder->addJSONParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']), + ), + 'binary' => $alternativeBuilder->addBinaryParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']), + ), + default => $alternativeBuilder->addStringParam( + $key, + compileValueWhenExpression($this->interpreter, $parameter['value']), + ), + }; + } + } + } $lookup->addAlternative( compileValueWhenExpression($this->interpreter, $alternative['condition']), From 505d21207f1ffa7edc07eef82f6e830aea8518b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20PLANCHAT?= Date: Mon, 10 Jul 2023 07:33:15 +0000 Subject: [PATCH 5/5] Renamed getParameters to walkParameters --- src/Builder/AlternativeLoader.php | 4 ++-- src/Builder/AlternativeLookup.php | 4 ++-- src/Builder/Loader.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Builder/AlternativeLoader.php b/src/Builder/AlternativeLoader.php index dc7a326..7b5986e 100644 --- a/src/Builder/AlternativeLoader.php +++ b/src/Builder/AlternativeLoader.php @@ -198,7 +198,7 @@ public function getNode(): Node ) ) ), - ...$this->getParameters(), + ...$this->walkParameters(), new Node\Stmt\Expression( expr: new Node\Expr\MethodCall( var: new Node\Expr\Variable('statement'), @@ -219,7 +219,7 @@ public function getNode(): Node ); } - public function getParameters(): iterable + public function walkParameters(): iterable { foreach ($this->parameters as $key => $parameter) { yield $this->compileParameter($key, $parameter); diff --git a/src/Builder/AlternativeLookup.php b/src/Builder/AlternativeLookup.php index 69b6154..a7fc111 100644 --- a/src/Builder/AlternativeLookup.php +++ b/src/Builder/AlternativeLookup.php @@ -230,7 +230,7 @@ public function getAlternativeLookupNode(): Node ), ), ), - ...$this->getParameters(), + ...$this->walkParameters(), new Node\Stmt\Expression( expr: new Node\Expr\MethodCall( var: new Node\Expr\Variable('stmt'), @@ -312,7 +312,7 @@ class: new Node\Name\FullyQualified('PDO'), ))->getNode(); } - public function getParameters(): iterable + public function walkParameters(): iterable { foreach ($this->parameters as $key => $parameter) { yield $this->compileParameter($key, $parameter); diff --git a/src/Builder/Loader.php b/src/Builder/Loader.php index 94c051a..42f7488 100644 --- a/src/Builder/Loader.php +++ b/src/Builder/Loader.php @@ -241,7 +241,7 @@ class: new Node\Name\FullyQualified(\Kiboko\Component\Flow\SQL\Loader::class), ), ], 'stmts' => [ - ...$this->getParameters(), + ...$this->walkParameters(), ], ], )) @@ -307,7 +307,7 @@ public function compileAfterQueries(): Node\Expr ); } - public function getParameters(): iterable + public function walkParameters(): iterable { foreach ($this->parameters as $key => $parameter) { yield $this->compileParameter($key, $parameter);