Passed
Push — main ( 67265c...6a5ba9 )
by Martin
36:25 queued 21:26
created

BaseVariadicFunction   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 72
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 29
c 1
b 0
f 1
dl 0
loc 72
ccs 29
cts 29
cp 1
rs 10
wmc 15

3 Methods

Rating   Name   Duplication   Size   Complexity  
B feedParserWithNodesForNodeMappingPattern() 0 28 9
A feedParserWithNodes() 0 13 3
A getSql() 0 8 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6
7
use Doctrine\ORM\Query\AST\Node;
8
use Doctrine\ORM\Query\Lexer;
9
use Doctrine\ORM\Query\Parser;
10
use Doctrine\ORM\Query\SqlWalker;
11
use Doctrine\ORM\Query\TokenType;
12
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
13
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\ParserException;
14
use MartinGeorgiev\Utils\DoctrineLexer;
15
use MartinGeorgiev\Utils\DoctrineOrm;
16
17
/**
18
 * @author Martin Georgiev <[email protected]>
19
 */
20
abstract class BaseVariadicFunction extends BaseFunction
21
{
22
    /**
23
     * @return array<int|string, string>
24
     */
25
    abstract protected function getNodeMappingPattern(): array;
26
27
    /**
28
     * @throws ParserException
29
     */
30 66
    protected function feedParserWithNodes(Parser $parser): void
31
    {
32 66
        foreach ($this->getNodeMappingPattern() as $nodeMappingPattern) {
33
            try {
34 66
                $this->feedParserWithNodesForNodeMappingPattern($parser, $nodeMappingPattern);
35
36 64
                break;
37 2
            } catch (ParserException) {
38
                // swallow and continue with next pattern
39
            }
40
        }
41
42 66
        $this->validateArguments(...$this->nodes); // @phpstan-ignore-line
43
    }
44
45 66
    private function feedParserWithNodesForNodeMappingPattern(Parser $parser, string $nodeMappingPattern): void
46
    {
47 66
        $nodeMapping = \explode(',', $nodeMappingPattern);
48 66
        $lexer = $parser->getLexer();
49
50
        try {
51
            // @phpstan-ignore-next-line
52 66
            $this->nodes[] = $parser->{$nodeMapping[0]}();
53 64
            $lookaheadType = DoctrineLexer::getLookaheadType($lexer);
54 64
            if ($lookaheadType === null) {
55 64
                throw ParserException::missingLookaheadType();
56
            }
57 2
        } catch (\Throwable $throwable) {
58 2
            throw ParserException::withThrowable($throwable);
59
        }
60
61 64
        $shouldUseLexer = DoctrineOrm::isPre219();
62 64
        $isNodeMappingASimplePattern = \count($nodeMapping) === 1;
63 64
        $nodeIndex = 1;
64 64
        while (($shouldUseLexer ? Lexer::T_CLOSE_PARENTHESIS : TokenType::T_CLOSE_PARENTHESIS) !== $lookaheadType) {
0 ignored issues
show
Bug introduced by
The constant Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
65 51
            if (($shouldUseLexer ? Lexer::T_COMMA : TokenType::T_COMMA) === $lookaheadType) {
0 ignored issues
show
Bug introduced by
The constant Doctrine\ORM\Query\Lexer::T_COMMA was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
66 51
                $parser->match($shouldUseLexer ? Lexer::T_COMMA : TokenType::T_COMMA);
67
                // @phpstan-ignore-next-line
68 51
                $this->nodes[] = $parser->{$nodeMapping[$isNodeMappingASimplePattern ? 0 : $nodeIndex]}();
69 51
                $nodeIndex++;
70
            }
71
72 51
            $lookaheadType = DoctrineLexer::getLookaheadType($lexer);
73
        }
74
    }
75
76 26
    public function getSql(SqlWalker $sqlWalker): string
77
    {
78 26
        $dispatched = [];
79 26
        foreach ($this->nodes as $node) {
80 26
            $dispatched[] = $node instanceof Node ? $node->dispatch($sqlWalker) : 'null';
81
        }
82
83 26
        return \sprintf($this->functionPrototype, \implode(', ', $dispatched));
84
    }
85
86
    /**
87
     * Validates the arguments passed to the function.
88
     *
89
     * @throws InvalidArgumentForVariadicFunctionException
90
     */
91
    abstract protected function validateArguments(Node ...$arguments): void;
92
}
93