Skip to content

Commit 2eb3bde

Browse files
committed
Split up JoinKeyword
Signed-off-by: Kamil Tekiela <[email protected]>
1 parent 33799aa commit 2eb3bde

File tree

7 files changed

+195
-178
lines changed

7 files changed

+195
-178
lines changed

phpstan-baseline.neon

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ parameters:
112112

113113
-
114114
message: "#^Property PhpMyAdmin\\\\SqlParser\\\\Components\\\\JoinKeyword\\:\\:\\$expr \\(PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\) does not accept PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\|null\\.$#"
115-
count: 2
115+
count: 1
116116
path: src/Components/JoinKeyword.php
117117

118118
-
@@ -130,11 +130,6 @@ parameters:
130130
count: 1
131131
path: src/Components/JoinKeyword.php
132132

133-
-
134-
message: "#^Property PhpMyAdmin\\\\SqlParser\\\\Components\\\\JoinKeyword\\:\\:\\$using \\(PhpMyAdmin\\\\SqlParser\\\\Components\\\\ArrayObj\\) does not accept array\\<PhpMyAdmin\\\\SqlParser\\\\Component\\>\\|PhpMyAdmin\\\\SqlParser\\\\Components\\\\ArrayObj\\.$#"
135-
count: 1
136-
path: src/Components/JoinKeyword.php
137-
138133
-
139134
message: "#^Property PhpMyAdmin\\\\SqlParser\\\\Components\\\\JoinKeyword\\:\\:\\$using \\(PhpMyAdmin\\\\SqlParser\\\\Components\\\\ArrayObj\\) in empty\\(\\) is not falsy\\.$#"
140135
count: 1
@@ -215,6 +210,16 @@ parameters:
215210
count: 1
216211
path: src/Components/Lists/IndexHints.php
217212

213+
-
214+
message: "#^Property PhpMyAdmin\\\\SqlParser\\\\Components\\\\JoinKeyword\\:\\:\\$expr \\(PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\) does not accept PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\|null\\.$#"
215+
count: 1
216+
path: src/Components/Lists/JoinKeywords.php
217+
218+
-
219+
message: "#^Property PhpMyAdmin\\\\SqlParser\\\\Components\\\\JoinKeyword\\:\\:\\$using \\(PhpMyAdmin\\\\SqlParser\\\\Components\\\\ArrayObj\\) does not accept array\\<PhpMyAdmin\\\\SqlParser\\\\Component\\>\\|PhpMyAdmin\\\\SqlParser\\\\Components\\\\ArrayObj\\.$#"
220+
count: 1
221+
path: src/Components/Lists/JoinKeywords.php
222+
218223
-
219224
message: "#^Property PhpMyAdmin\\\\SqlParser\\\\Components\\\\LockExpression\\:\\:\\$table \\(PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\) does not accept PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\|null\\.$#"
220225
count: 1

psalm-baseline.xml

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -169,31 +169,15 @@
169169
<DocblockTypeContradiction>
170170
<code><![CDATA['']]></code>
171171
</DocblockTypeContradiction>
172-
<MixedArrayOffset>
173-
<code><![CDATA[self::JOINS[$token->keyword]]]></code>
174-
<code><![CDATA[self::JOINS[$token->keyword]]]></code>
175-
</MixedArrayOffset>
176172
<PossiblyFalseOperand>
177-
<code><![CDATA[array_search($c->type, self::JOINS)]]></code>
173+
<code><![CDATA[array_search($this->type, self::JOINS)]]></code>
178174
</PossiblyFalseOperand>
179-
<PossiblyInvalidPropertyAssignmentValue>
180-
<code>ArrayObj::parse($parser, $list)</code>
181-
</PossiblyInvalidPropertyAssignmentValue>
182175
<PossiblyNullPropertyAssignmentValue>
183176
<code>$expr</code>
184177
<code>$on</code>
185178
<code>$type</code>
186179
<code>$using</code>
187-
<code><![CDATA[Expression::parse($parser, $list, ['field' => 'table'])]]></code>
188180
</PossiblyNullPropertyAssignmentValue>
189-
<UnusedParam>
190-
<code>$options</code>
191-
</UnusedParam>
192-
<UnusedVariable>
193-
<code>$state</code>
194-
<code>$state</code>
195-
<code>$state</code>
196-
</UnusedVariable>
197181
</file>
198182
<file src="src/Components/Key.php">
199183
<MixedAssignment>
@@ -271,6 +255,26 @@
271255
<code>buildAll</code>
272256
</PossiblyUnusedMethod>
273257
</file>
258+
<file src="src/Components/Lists/JoinKeywords.php">
259+
<MixedArrayOffset>
260+
<code><![CDATA[JoinKeyword::JOINS[$token->keyword]]]></code>
261+
<code><![CDATA[JoinKeyword::JOINS[$token->keyword]]]></code>
262+
</MixedArrayOffset>
263+
<PossiblyInvalidPropertyAssignmentValue>
264+
<code>ArrayObj::parse($parser, $list)</code>
265+
</PossiblyInvalidPropertyAssignmentValue>
266+
<PossiblyNullPropertyAssignmentValue>
267+
<code><![CDATA[Expression::parse($parser, $list, ['field' => 'table'])]]></code>
268+
</PossiblyNullPropertyAssignmentValue>
269+
<UnusedParam>
270+
<code>$options</code>
271+
</UnusedParam>
272+
<UnusedVariable>
273+
<code>$state</code>
274+
<code>$state</code>
275+
<code>$state</code>
276+
</UnusedVariable>
277+
</file>
274278
<file src="src/Components/LockExpression.php">
275279
<MissingConstructor>
276280
<code>$table</code>

src/Components/JoinKeyword.php

Lines changed: 3 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,8 @@
66

77
use PhpMyAdmin\SqlParser\Component;
88
use PhpMyAdmin\SqlParser\Components\Lists\Conditions;
9-
use PhpMyAdmin\SqlParser\Parser;
10-
use PhpMyAdmin\SqlParser\TokensList;
11-
use PhpMyAdmin\SqlParser\TokenType;
12-
use PhpMyAdmin\SqlParser\Translator;
13-
use RuntimeException;
149

1510
use function array_search;
16-
use function implode;
1711

1812
/**
1913
* `JOIN` keyword parser.
@@ -91,135 +85,11 @@ public function __construct(
9185
$this->using = $using;
9286
}
9387

94-
/**
95-
* @param Parser $parser the parser that serves as context
96-
* @param TokensList $list the list of tokens that are being parsed
97-
* @param array<string, mixed> $options parameters for parsing
98-
*
99-
* @return JoinKeyword[]
100-
*/
101-
public static function parse(Parser $parser, TokensList $list, array $options = []): array
102-
{
103-
$ret = [];
104-
105-
$expr = new static();
106-
107-
/**
108-
* The state of the parser.
109-
*
110-
* Below are the states of the parser.
111-
*
112-
* 0 -----------------------[ JOIN ]----------------------> 1
113-
*
114-
* 1 -----------------------[ expr ]----------------------> 2
115-
*
116-
* 2 ------------------------[ ON ]-----------------------> 3
117-
* 2 -----------------------[ USING ]---------------------> 4
118-
*
119-
* 3 --------------------[ conditions ]-------------------> 0
120-
*
121-
* 4 ----------------------[ columns ]--------------------> 0
122-
*
123-
* @var int
124-
*/
125-
$state = 0;
126-
127-
// By design, the parser will parse first token after the keyword.
128-
// In this case, the keyword must be analyzed too, in order to determine
129-
// the type of this join.
130-
if ($list->idx > 0) {
131-
--$list->idx;
132-
}
133-
134-
for (; $list->idx < $list->count; ++$list->idx) {
135-
/**
136-
* Token parsed at this moment.
137-
*/
138-
$token = $list->tokens[$list->idx];
139-
140-
// End of statement.
141-
if ($token->type === TokenType::Delimiter) {
142-
break;
143-
}
144-
145-
// Skipping whitespaces and comments.
146-
if (($token->type === TokenType::Whitespace) || ($token->type === TokenType::Comment)) {
147-
continue;
148-
}
149-
150-
if ($state === 0) {
151-
if (($token->type !== TokenType::Keyword) || empty(self::JOINS[$token->keyword])) {
152-
break;
153-
}
154-
155-
$expr->type = self::JOINS[$token->keyword];
156-
$state = 1;
157-
} elseif ($state === 1) {
158-
$expr->expr = Expression::parse($parser, $list, ['field' => 'table']);
159-
$state = 2;
160-
} elseif ($state === 2) {
161-
if ($token->type === TokenType::Keyword) {
162-
switch ($token->keyword) {
163-
case 'ON':
164-
$state = 3;
165-
break;
166-
case 'USING':
167-
$state = 4;
168-
break;
169-
default:
170-
if (empty(self::JOINS[$token->keyword])) {
171-
/* Next clause is starting */
172-
break 2;
173-
}
174-
175-
$ret[] = $expr;
176-
$expr = new static();
177-
$expr->type = self::JOINS[$token->keyword];
178-
$state = 1;
179-
180-
break;
181-
}
182-
}
183-
} elseif ($state === 3) {
184-
$expr->on = Conditions::parse($parser, $list);
185-
$ret[] = $expr;
186-
$expr = new static();
187-
$state = 0;
188-
} elseif ($state === 4) {
189-
$expr->using = ArrayObj::parse($parser, $list);
190-
$ret[] = $expr;
191-
$expr = new static();
192-
$state = 0;
193-
}
194-
}
195-
196-
if (! empty($expr->type)) {
197-
$ret[] = $expr;
198-
}
199-
200-
--$list->idx;
201-
202-
return $ret;
203-
}
204-
20588
public function build(): string
20689
{
207-
throw new RuntimeException(Translator::gettext('Not implemented yet.'));
208-
}
209-
210-
/** @param JoinKeyword[] $component the component to be built */
211-
public static function buildAll(array $component): string
212-
{
213-
$ret = [];
214-
foreach ($component as $c) {
215-
$ret[] = array_search($c->type, self::JOINS) . ' ' . $c->expr
216-
. (! empty($c->on)
217-
? ' ON ' . Conditions::buildAll($c->on) : '')
218-
. (! empty($c->using)
219-
? ' USING ' . $c->using->build() : '');
220-
}
221-
222-
return implode(' ', $ret);
90+
return array_search($this->type, self::JOINS) . ' ' . $this->expr
91+
. (! empty($this->on) ? ' ON ' . Conditions::buildAll($this->on) : '')
92+
. (! empty($this->using) ? ' USING ' . $this->using->build() : '');
22393
}
22494

22595
public function __toString(): string
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMyAdmin\SqlParser\Components\Lists;
6+
7+
use PhpMyAdmin\SqlParser\Components\ArrayObj;
8+
use PhpMyAdmin\SqlParser\Components\Expression;
9+
use PhpMyAdmin\SqlParser\Components\JoinKeyword;
10+
use PhpMyAdmin\SqlParser\Parser;
11+
use PhpMyAdmin\SqlParser\TokensList;
12+
use PhpMyAdmin\SqlParser\TokenType;
13+
14+
use function implode;
15+
16+
/**
17+
* `JOIN` keyword parser.
18+
*/
19+
final class JoinKeywords
20+
{
21+
/**
22+
* @param Parser $parser the parser that serves as context
23+
* @param TokensList $list the list of tokens that are being parsed
24+
* @param array<string, mixed> $options parameters for parsing
25+
*
26+
* @return JoinKeyword[]
27+
*/
28+
public static function parse(Parser $parser, TokensList $list, array $options = []): array
29+
{
30+
$ret = [];
31+
32+
$expr = new JoinKeyword();
33+
34+
/**
35+
* The state of the parser.
36+
*
37+
* Below are the states of the parser.
38+
*
39+
* 0 -----------------------[ JOIN ]----------------------> 1
40+
*
41+
* 1 -----------------------[ expr ]----------------------> 2
42+
*
43+
* 2 ------------------------[ ON ]-----------------------> 3
44+
* 2 -----------------------[ USING ]---------------------> 4
45+
*
46+
* 3 --------------------[ conditions ]-------------------> 0
47+
*
48+
* 4 ----------------------[ columns ]--------------------> 0
49+
*
50+
* @var int
51+
*/
52+
$state = 0;
53+
54+
// By design, the parser will parse first token after the keyword.
55+
// In this case, the keyword must be analyzed too, in order to determine
56+
// the type of this join.
57+
if ($list->idx > 0) {
58+
--$list->idx;
59+
}
60+
61+
for (; $list->idx < $list->count; ++$list->idx) {
62+
/**
63+
* Token parsed at this moment.
64+
*/
65+
$token = $list->tokens[$list->idx];
66+
67+
// End of statement.
68+
if ($token->type === TokenType::Delimiter) {
69+
break;
70+
}
71+
72+
// Skipping whitespaces and comments.
73+
if (($token->type === TokenType::Whitespace) || ($token->type === TokenType::Comment)) {
74+
continue;
75+
}
76+
77+
if ($state === 0) {
78+
if (($token->type !== TokenType::Keyword) || empty(JoinKeyword::JOINS[$token->keyword])) {
79+
break;
80+
}
81+
82+
$expr->type = JoinKeyword::JOINS[$token->keyword];
83+
$state = 1;
84+
} elseif ($state === 1) {
85+
$expr->expr = Expression::parse($parser, $list, ['field' => 'table']);
86+
$state = 2;
87+
} elseif ($state === 2) {
88+
if ($token->type === TokenType::Keyword) {
89+
switch ($token->keyword) {
90+
case 'ON':
91+
$state = 3;
92+
break;
93+
case 'USING':
94+
$state = 4;
95+
break;
96+
default:
97+
if (empty(JoinKeyword::JOINS[$token->keyword])) {
98+
/* Next clause is starting */
99+
break 2;
100+
}
101+
102+
$ret[] = $expr;
103+
$expr = new JoinKeyword();
104+
$expr->type = JoinKeyword::JOINS[$token->keyword];
105+
$state = 1;
106+
107+
break;
108+
}
109+
}
110+
} elseif ($state === 3) {
111+
$expr->on = Conditions::parse($parser, $list);
112+
$ret[] = $expr;
113+
$expr = new JoinKeyword();
114+
$state = 0;
115+
} elseif ($state === 4) {
116+
$expr->using = ArrayObj::parse($parser, $list);
117+
$ret[] = $expr;
118+
$expr = new JoinKeyword();
119+
$state = 0;
120+
}
121+
}
122+
123+
if (! empty($expr->type)) {
124+
$ret[] = $expr;
125+
}
126+
127+
--$list->idx;
128+
129+
return $ret;
130+
}
131+
132+
/** @param JoinKeyword[] $component the component to be built */
133+
public static function buildAll(array $component): string
134+
{
135+
return implode(' ', $component);
136+
}
137+
}

0 commit comments

Comments
 (0)