|
5 | 5 | namespace PhpMyAdmin\SqlParser\Components; |
6 | 6 |
|
7 | 7 | use PhpMyAdmin\SqlParser\Component; |
8 | | -use PhpMyAdmin\SqlParser\Parser; |
9 | | -use PhpMyAdmin\SqlParser\Token; |
10 | | -use PhpMyAdmin\SqlParser\TokensList; |
11 | | -use PhpMyAdmin\SqlParser\TokenType; |
12 | 8 |
|
13 | | -use function implode; |
14 | | -use function in_array; |
15 | 9 | use function trim; |
16 | 10 |
|
17 | | -/** |
18 | | - * `WHERE` keyword parser. |
19 | | - */ |
20 | 11 | final class Condition implements Component |
21 | 12 | { |
22 | | - /** |
23 | | - * Logical operators that can be used to delimit expressions. |
24 | | - */ |
25 | | - private const DELIMITERS = [ |
26 | | - '&&', |
27 | | - '||', |
28 | | - 'AND', |
29 | | - 'OR', |
30 | | - 'XOR', |
31 | | - ]; |
32 | | - |
33 | | - /** |
34 | | - * List of allowed reserved keywords in conditions. |
35 | | - */ |
36 | | - private const ALLOWED_KEYWORDS = [ |
37 | | - 'ALL' => 1, |
38 | | - 'AND' => 1, |
39 | | - 'BETWEEN' => 1, |
40 | | - 'COLLATE' => 1, |
41 | | - 'EXISTS' => 1, |
42 | | - 'IF' => 1, |
43 | | - 'IN' => 1, |
44 | | - 'INTERVAL' => 1, |
45 | | - 'IS' => 1, |
46 | | - 'LIKE' => 1, |
47 | | - 'MATCH' => 1, |
48 | | - 'NOT IN' => 1, |
49 | | - 'NOT NULL' => 1, |
50 | | - 'NOT' => 1, |
51 | | - 'NULL' => 1, |
52 | | - 'OR' => 1, |
53 | | - 'REGEXP' => 1, |
54 | | - 'RLIKE' => 1, |
55 | | - 'SOUNDS' => 1, |
56 | | - 'XOR' => 1, |
57 | | - ]; |
58 | | - |
59 | 13 | /** |
60 | 14 | * Identifiers recognized. |
61 | 15 | * |
@@ -83,149 +37,11 @@ public function __construct(string|null $expr = null) |
83 | 37 | $this->expr = trim((string) $expr); |
84 | 38 | } |
85 | 39 |
|
86 | | - /** |
87 | | - * @param Parser $parser the parser that serves as context |
88 | | - * @param TokensList $list the list of tokens that are being parsed |
89 | | - * @param array<string, mixed> $options parameters for parsing |
90 | | - * |
91 | | - * @return Condition[] |
92 | | - */ |
93 | | - public static function parse(Parser $parser, TokensList $list, array $options = []): array |
94 | | - { |
95 | | - $ret = []; |
96 | | - |
97 | | - $expr = new static(); |
98 | | - |
99 | | - /** |
100 | | - * Counts brackets. |
101 | | - * |
102 | | - * @var int |
103 | | - */ |
104 | | - $brackets = 0; |
105 | | - |
106 | | - /** |
107 | | - * Whether there was a `BETWEEN` keyword before or not. |
108 | | - * |
109 | | - * It is required to keep track of them because their structure contains |
110 | | - * the keyword `AND`, which is also an operator that delimits |
111 | | - * expressions. |
112 | | - * |
113 | | - * @var bool |
114 | | - */ |
115 | | - $betweenBefore = false; |
116 | | - |
117 | | - for (; $list->idx < $list->count; ++$list->idx) { |
118 | | - /** |
119 | | - * Token parsed at this moment. |
120 | | - */ |
121 | | - $token = $list->tokens[$list->idx]; |
122 | | - |
123 | | - // End of statement. |
124 | | - if ($token->type === TokenType::Delimiter) { |
125 | | - break; |
126 | | - } |
127 | | - |
128 | | - // Skipping whitespaces and comments. |
129 | | - if ($token->type === TokenType::Comment) { |
130 | | - continue; |
131 | | - } |
132 | | - |
133 | | - // Replacing all whitespaces (new lines, tabs, etc.) with a single |
134 | | - // space character. |
135 | | - if ($token->type === TokenType::Whitespace) { |
136 | | - $expr->expr .= ' '; |
137 | | - continue; |
138 | | - } |
139 | | - |
140 | | - // Conditions are delimited by logical operators. |
141 | | - if (in_array($token->value, self::DELIMITERS, true)) { |
142 | | - if ($betweenBefore && ($token->value === 'AND')) { |
143 | | - // The syntax of keyword `BETWEEN` is hard-coded. |
144 | | - $betweenBefore = false; |
145 | | - } else { |
146 | | - // The expression ended. |
147 | | - $expr->expr = trim($expr->expr); |
148 | | - if (! empty($expr->expr)) { |
149 | | - $ret[] = $expr; |
150 | | - } |
151 | | - |
152 | | - // Adding the operator. |
153 | | - $expr = new static($token->value); |
154 | | - $expr->isOperator = true; |
155 | | - $ret[] = $expr; |
156 | | - |
157 | | - // Preparing to parse another condition. |
158 | | - $expr = new static(); |
159 | | - continue; |
160 | | - } |
161 | | - } |
162 | | - |
163 | | - if ( |
164 | | - ($token->type === TokenType::Keyword) |
165 | | - && ($token->flags & Token::FLAG_KEYWORD_RESERVED) |
166 | | - && ! ($token->flags & Token::FLAG_KEYWORD_FUNCTION) |
167 | | - ) { |
168 | | - if ($token->value === 'BETWEEN') { |
169 | | - $betweenBefore = true; |
170 | | - } |
171 | | - |
172 | | - if (($brackets === 0) && empty(self::ALLOWED_KEYWORDS[$token->value])) { |
173 | | - break; |
174 | | - } |
175 | | - } |
176 | | - |
177 | | - if ($token->type === TokenType::Operator) { |
178 | | - if ($token->value === '(') { |
179 | | - ++$brackets; |
180 | | - } elseif ($token->value === ')') { |
181 | | - if ($brackets === 0) { |
182 | | - break; |
183 | | - } |
184 | | - |
185 | | - --$brackets; |
186 | | - } |
187 | | - } |
188 | | - |
189 | | - $expr->expr .= $token->token; |
190 | | - if ( |
191 | | - ($token->type !== TokenType::None) |
192 | | - && (($token->type !== TokenType::Keyword) |
193 | | - || ($token->flags & Token::FLAG_KEYWORD_RESERVED)) |
194 | | - && ($token->type !== TokenType::String) |
195 | | - && ($token->type !== TokenType::Symbol || ($token->flags & Token::FLAG_SYMBOL_PARAMETER)) |
196 | | - ) { |
197 | | - continue; |
198 | | - } |
199 | | - |
200 | | - if (in_array($token->value, $expr->identifiers)) { |
201 | | - continue; |
202 | | - } |
203 | | - |
204 | | - $expr->identifiers[] = $token->value; |
205 | | - } |
206 | | - |
207 | | - // Last iteration was not processed. |
208 | | - $expr->expr = trim($expr->expr); |
209 | | - if (! empty($expr->expr)) { |
210 | | - $ret[] = $expr; |
211 | | - } |
212 | | - |
213 | | - --$list->idx; |
214 | | - |
215 | | - return $ret; |
216 | | - } |
217 | | - |
218 | 40 | public function build(): string |
219 | 41 | { |
220 | 42 | return $this->expr; |
221 | 43 | } |
222 | 44 |
|
223 | | - /** @param Condition[] $component the component to be built */ |
224 | | - public static function buildAll(array $component): string |
225 | | - { |
226 | | - return implode(' ', $component); |
227 | | - } |
228 | | - |
229 | 45 | public function __toString(): string |
230 | 46 | { |
231 | 47 | return $this->build(); |
|
0 commit comments