Passed
Push — master ( b16987...8b6d77 )
by Maurício
03:49 queued 13s
created

OrderKeywords   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 79
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 29
dl 0
loc 79
ccs 28
cts 28
cp 1
rs 10
c 0
b 0
f 0
wmc 14

2 Methods

Rating   Name   Duplication   Size   Complexity  
A buildAll() 0 3 1
C parse() 0 64 13
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser\Parsers;
6
7
use PhpMyAdmin\SqlParser\Components\OrderKeyword;
8
use PhpMyAdmin\SqlParser\Parseable;
9
use PhpMyAdmin\SqlParser\Parser;
10
use PhpMyAdmin\SqlParser\TokensList;
11
use PhpMyAdmin\SqlParser\TokenType;
12
13
use function implode;
14
15
/**
16
 * `ORDER BY` keyword parser.
17
 */
18
final class OrderKeywords implements Parseable
19
{
20
    /**
21
     * @param Parser               $parser  the parser that serves as context
22
     * @param TokensList           $list    the list of tokens that are being parsed
23
     * @param array<string, mixed> $options parameters for parsing
24
     *
25
     * @return OrderKeyword[]
26
     */
27 56
    public static function parse(Parser $parser, TokensList $list, array $options = []): array
28
    {
29 56
        $ret = [];
30
31 56
        $expr = new OrderKeyword();
32
33
        /**
34
         * The state of the parser.
35
         *
36
         * Below are the states of the parser.
37
         *
38
         *      0 --------------------[ expression ]-------------------> 1
39
         *
40
         *      1 ------------------------[ , ]------------------------> 0
41
         *      1 -------------------[ ASC / DESC ]--------------------> 1
42
         */
43 56
        $state = 0;
44
45 56
        for (; $list->idx < $list->count; ++$list->idx) {
46
            /**
47
             * Token parsed at this moment.
48
             */
49 56
            $token = $list->tokens[$list->idx];
50
51
            // End of statement.
52 56
            if ($token->type === TokenType::Delimiter) {
53 24
                break;
54
            }
55
56
            // Skipping whitespaces and comments.
57 56
            if (($token->type === TokenType::Whitespace) || ($token->type === TokenType::Comment)) {
58 56
                continue;
59
            }
60
61 56
            if ($state === 0) {
62 56
                $expr->expr = Expressions::parse($parser, $list);
63 56
                $state = 1;
64
            } else {
65
                if (
66 44
                    ($token->type === TokenType::Keyword)
67 44
                    && (($token->keyword === 'ASC') || ($token->keyword === 'DESC'))
68
                ) {
69 34
                    $expr->type = $token->keyword;
70 36
                } elseif (($token->type === TokenType::Operator) && ($token->value === ',')) {
71 10
                    if (! empty($expr->expr)) {
72 10
                        $ret[] = $expr;
73
                    }
74
75 10
                    $expr = new OrderKeyword();
76 10
                    $state = 0;
77
                } else {
78 34
                    break;
79
                }
80
            }
81
        }
82
83
        // Last iteration was not processed.
84 56
        if (! empty($expr->expr)) {
85 56
            $ret[] = $expr;
86
        }
87
88 56
        --$list->idx;
89
90 56
        return $ret;
91
    }
92
93
    /** @param OrderKeyword[] $component the component to be built */
94 20
    public static function buildAll(array $component): string
95
    {
96 20
        return implode(', ', $component);
97
    }
98
}
99