Passed
Pull Request — master (#483)
by
unknown
03:28
created

OrderKeyword::buildAll()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser\Components;
6
7
use PhpMyAdmin\SqlParser\Component;
8
use PhpMyAdmin\SqlParser\Parser;
9
use PhpMyAdmin\SqlParser\Token;
10
use PhpMyAdmin\SqlParser\TokensList;
11
12
use function implode;
13
14
/**
15
 * `ORDER BY` keyword parser.
16
 */
17
final class OrderKeyword implements Component
18
{
19
    /**
20
     * The expression that is used for ordering.
21
     *
22
     * @var Expression
23
     */
24
    public $expr;
25
26
    /**
27
     * The order type.
28
     *
29
     * @var string
30
     */
31
    public $type;
32
33
    /**
34
     * @param Expression $expr the expression that we are sorting by
35
     * @param string     $type the sorting type
36
     */
37 58
    public function __construct($expr = null, $type = 'ASC')
38
    {
39 58
        $this->expr = $expr;
40 58
        $this->type = $type;
41
    }
42
43
    /**
44
     * @param Parser               $parser  the parser that serves as context
45
     * @param TokensList           $list    the list of tokens that are being parsed
46
     * @param array<string, mixed> $options parameters for parsing
47
     *
48
     * @return OrderKeyword[]
49
     */
50 56
    public static function parse(Parser $parser, TokensList $list, array $options = []): array
51
    {
52 56
        $ret = [];
53
54 56
        $expr = new static();
55
56
        /**
57
         * The state of the parser.
58
         *
59
         * Below are the states of the parser.
60
         *
61
         *      0 --------------------[ expression ]-------------------> 1
62
         *
63
         *      1 ------------------------[ , ]------------------------> 0
64
         *      1 -------------------[ ASC / DESC ]--------------------> 1
65
         *
66
         * @var int
67
         */
68 56
        $state = 0;
69
70 56
        for (; $list->idx < $list->count; ++$list->idx) {
71
            /**
72
             * Token parsed at this moment.
73
             */
74 56
            $token = $list->tokens[$list->idx];
75
76
            // End of statement.
77 56
            if ($token->type === Token::TYPE_DELIMITER) {
78 24
                break;
79
            }
80
81
            // Skipping whitespaces and comments.
82 56
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
83 56
                continue;
84
            }
85
86 56
            if ($state === 0) {
87 56
                $expr->expr = Expression::parse($parser, $list);
88 56
                $state = 1;
89 44
            } elseif ($state === 1) {
90
                if (
91 44
                    ($token->type === Token::TYPE_KEYWORD)
92 44
                    && (($token->keyword === 'ASC') || ($token->keyword === 'DESC'))
93
                ) {
94 34
                    $expr->type = $token->keyword;
95 36
                } elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
96 10
                    if (! empty($expr->expr)) {
97 10
                        $ret[] = $expr;
98
                    }
99
100 10
                    $expr = new static();
101 10
                    $state = 0;
102
                } else {
103 34
                    break;
104
                }
105
            }
106
        }
107
108
        // Last iteration was not processed.
109 56
        if (! empty($expr->expr)) {
110 56
            $ret[] = $expr;
111
        }
112
113 56
        --$list->idx;
114
115 56
        return $ret;
116
    }
117
118
    /**
119
     * @param OrderKeyword $component the component to be built
120
     */
121 20
    public static function build($component): string
122
    {
123 20
        return $component->expr . ' ' . $component->type;
124
    }
125
126
    /**
127
     * @param OrderKeyword[] $component the component to be built
128
     */
129 20
    public static function buildAll(array $component): string
130
    {
131 20
        return implode(', ', $component);
132
    }
133
134 20
    public function __toString(): string
135
    {
136 20
        return static::build($this);
137
    }
138
}
139