Skip to content

Commit 3ca5ee2

Browse files
committed
Split up Condition class
Signed-off-by: Kamil Tekiela <[email protected]>
1 parent 273ddc4 commit 3ca5ee2

File tree

8 files changed

+216
-199
lines changed

8 files changed

+216
-199
lines changed

psalm-baseline.xml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,6 @@
6666
</UnusedParam>
6767
</file>
6868
<file src="src/Components/Condition.php">
69-
<MixedArrayOffset>
70-
<code><![CDATA[self::ALLOWED_KEYWORDS[$token->value]]]></code>
71-
</MixedArrayOffset>
7269
<PossiblyUnusedProperty>
7370
<code>$isOperator</code>
7471
</PossiblyUnusedProperty>
@@ -261,6 +258,11 @@
261258
<code><![CDATA[$ret->rowCount]]></code>
262259
</MixedAssignment>
263260
</file>
261+
<file src="src/Components/Lists/Conditions.php">
262+
<MixedArrayOffset>
263+
<code><![CDATA[self::ALLOWED_KEYWORDS[$token->value]]]></code>
264+
</MixedArrayOffset>
265+
</file>
264266
<file src="src/Components/LockExpression.php">
265267
<MissingConstructor>
266268
<code>$table</code>

src/Components/CaseExpression.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpMyAdmin\SqlParser\Components;
66

77
use PhpMyAdmin\SqlParser\Component;
8+
use PhpMyAdmin\SqlParser\Components\Lists\Conditions;
89
use PhpMyAdmin\SqlParser\Context;
910
use PhpMyAdmin\SqlParser\Parser;
1011
use PhpMyAdmin\SqlParser\Token;
@@ -108,7 +109,7 @@ public static function parse(Parser $parser, TokensList $list, array $options =
108109
switch ($token->keyword) {
109110
case 'WHEN':
110111
++$list->idx; // Skip 'WHEN'
111-
$newCondition = Condition::parse($parser, $list);
112+
$newCondition = Conditions::parse($parser, $list);
112113
$type = 1;
113114
$state = 1;
114115
$ret->conditions[] = $newCondition;
@@ -268,7 +269,7 @@ public function build(): string
268269
$valuesCount = count($this->conditions);
269270
$resultsCount = count($this->results);
270271
for ($i = 0; $i < $valuesCount && $i < $resultsCount; ++$i) {
271-
$ret .= 'WHEN ' . Condition::buildAll($this->conditions[$i]) . ' ';
272+
$ret .= 'WHEN ' . Conditions::buildAll($this->conditions[$i]) . ' ';
272273
$ret .= 'THEN ' . $this->results[$i] . ' ';
273274
}
274275
}

src/Components/Condition.php

Lines changed: 0 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,11 @@
55
namespace PhpMyAdmin\SqlParser\Components;
66

77
use PhpMyAdmin\SqlParser\Component;
8-
use PhpMyAdmin\SqlParser\Parser;
9-
use PhpMyAdmin\SqlParser\Token;
10-
use PhpMyAdmin\SqlParser\TokensList;
11-
use PhpMyAdmin\SqlParser\TokenType;
128

13-
use function implode;
14-
use function in_array;
159
use function trim;
1610

17-
/**
18-
* `WHERE` keyword parser.
19-
*/
2011
final class Condition implements Component
2112
{
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-
5913
/**
6014
* Identifiers recognized.
6115
*
@@ -83,149 +37,11 @@ public function __construct(string|null $expr = null)
8337
$this->expr = trim((string) $expr);
8438
}
8539

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-
21840
public function build(): string
21941
{
22042
return $this->expr;
22143
}
22244

223-
/** @param Condition[] $component the component to be built */
224-
public static function buildAll(array $component): string
225-
{
226-
return implode(' ', $component);
227-
}
228-
22945
public function __toString(): string
23046
{
23147
return $this->build();

src/Components/JoinKeyword.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpMyAdmin\SqlParser\Components;
66

77
use PhpMyAdmin\SqlParser\Component;
8+
use PhpMyAdmin\SqlParser\Components\Lists\Conditions;
89
use PhpMyAdmin\SqlParser\Parser;
910
use PhpMyAdmin\SqlParser\TokensList;
1011
use PhpMyAdmin\SqlParser\TokenType;
@@ -180,7 +181,7 @@ public static function parse(Parser $parser, TokensList $list, array $options =
180181
}
181182
}
182183
} elseif ($state === 3) {
183-
$expr->on = Condition::parse($parser, $list);
184+
$expr->on = Conditions::parse($parser, $list);
184185
$ret[] = $expr;
185186
$expr = new static();
186187
$state = 0;
@@ -213,7 +214,7 @@ public static function buildAll(array $component): string
213214
foreach ($component as $c) {
214215
$ret[] = array_search($c->type, self::JOINS) . ' ' . $c->expr
215216
. (! empty($c->on)
216-
? ' ON ' . Condition::buildAll($c->on) : '')
217+
? ' ON ' . Conditions::buildAll($c->on) : '')
217218
. (! empty($c->using)
218219
? ' USING ' . $c->using->build() : '');
219220
}

0 commit comments

Comments
 (0)