Passed
Push — master ( 6c3f09...c54108 )
by William
03:43
created

CLI::parseTokenize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 0
dl 0
loc 11
ccs 9
cts 9
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\Utils;
6
7
use PhpMyAdmin\SqlParser\Context;
8
use PhpMyAdmin\SqlParser\Lexer;
9
use PhpMyAdmin\SqlParser\Parser;
10
11
use function count;
12
use function getopt;
13
use function implode;
14
use function in_array;
15
use function rtrim;
16
use function stream_get_contents;
17
use function stream_select;
18
use function var_export;
19
20
use const STDIN;
21
22
/**
23
 * CLI interface.
24
 */
25
class CLI
26
{
27 2
    public function __construct()
28
    {
29 2
        Context::load();
30
    }
31
32
    /**
33
     * @param string[]|false[] $params
34
     * @param string[]         $longopts
35
     *
36
     * @return void
37
     */
38 70
    public function mergeLongOpts(&$params, &$longopts)
39
    {
40 70
        foreach ($longopts as $value) {
41 70
            $value = rtrim($value, ':');
42 70
            if (! isset($params[$value])) {
43 70
                continue;
44
            }
45
46 6
            $params[$value[0]] = $params[$value];
47
        }
48
    }
49
50
    /**
51
     * @return void
52
     */
53 8
    public function usageHighlight()
54
    {
55 8
        echo "Usage: highlight-query --query SQL [--format html|cli|text] [--ansi]\n";
56 8
        echo "       cat file.sql | highlight-query\n";
57
    }
58
59
    /**
60
     * @param string   $opt
61
     * @param string[] $long
62
     *
63
     * @return string[]|false[]|false
64
     */
65 2
    public function getopt($opt, $long)
66
    {
67 2
        return getopt($opt, $long);
68
    }
69
70
    /**
71
     * @return mixed|false
72
     */
73 30
    public function parseHighlight()
74
    {
75 30
        $longopts = [
76 30
            'help',
77 30
            'query:',
78 30
            'format:',
79 30
            'ansi',
80 30
        ];
81 30
        $params = $this->getopt('hq:f:a', $longopts);
82 30
        if ($params === false) {
83 4
            return false;
84
        }
85
86 26
        $this->mergeLongOpts($params, $longopts);
87 26
        if (! isset($params['f'])) {
88 14
            $params['f'] = 'cli';
89
        }
90
91 26
        if (! in_array($params['f'], ['html', 'cli', 'text'])) {
92 4
            echo "ERROR: Invalid value for format!\n";
93
94 4
            return false;
95
        }
96
97 22
        return $params;
98
    }
99
100
    /**
101
     * @return int
102
     */
103 30
    public function runHighlight()
104
    {
105 30
        $params = $this->parseHighlight();
106 30
        if ($params === false) {
107 8
            return 1;
108
        }
109
110 22
        if (isset($params['h'])) {
111 4
            $this->usageHighlight();
112
113 4
            return 0;
114
        }
115
116 18
        if (! isset($params['q'])) {
117 10
            $stdIn = $this->readStdin();
118
119 10
            if ($stdIn) {
120 6
                $params['q'] = $stdIn;
121
            }
122
        }
123
124 18
        if (isset($params['a'])) {
125
            Context::setMode(Context::SQL_MODE_ANSI_QUOTES);
126
        }
127
128 18
        if (isset($params['q'])) {
129 14
            echo Formatter::format(
130 14
                $params['q'],
131 14
                ['type' => $params['f']]
132 14
            );
133 14
            echo "\n";
134
135 14
            return 0;
136
        }
137
138 4
        echo "ERROR: Missing parameters!\n";
139 4
        $this->usageHighlight();
140
141 4
        return 1;
142
    }
143
144
    /**
145
     * @return void
146
     */
147 8
    public function usageLint()
148
    {
149 8
        echo "Usage: lint-query --query SQL [--ansi]\n";
150 8
        echo "       cat file.sql | lint-query\n";
151
    }
152
153
    /**
154
     * @return mixed
155
     */
156 26
    public function parseLint()
157
    {
158 26
        $longopts = [
159 26
            'help',
160 26
            'query:',
161 26
            'context:',
162 26
            'ansi',
163 26
        ];
164 26
        $params = $this->getopt('hq:c:a', $longopts);
165 26
        $this->mergeLongOpts($params, $longopts);
0 ignored issues
show
Bug introduced by
It seems like $params can also be of type false; however, parameter $params of PhpMyAdmin\SqlParser\Utils\CLI::mergeLongOpts() does only seem to accept array<mixed,false>|string[], maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

165
        $this->mergeLongOpts(/** @scrutinizer ignore-type */ $params, $longopts);
Loading history...
166
167 26
        return $params;
168
    }
169
170
    /**
171
     * @return int
172
     */
173 26
    public function runLint()
174
    {
175 26
        $params = $this->parseLint();
176 26
        if ($params === false) {
177 4
            return 1;
178
        }
179
180 22
        if (isset($params['h'])) {
181 4
            $this->usageLint();
182
183 4
            return 0;
184
        }
185
186 18
        if (isset($params['c'])) {
187 4
            Context::load($params['c']);
188
        }
189
190 18
        if (! isset($params['q'])) {
191 10
            $stdIn = $this->readStdin();
192
193 10
            if ($stdIn) {
194 6
                $params['q'] = $stdIn;
195
            }
196
        }
197
198 18
        if (isset($params['a'])) {
199
            Context::setMode(Context::SQL_MODE_ANSI_QUOTES);
200
        }
201
202 18
        if (isset($params['q'])) {
203 14
            $lexer = new Lexer($params['q'], false);
204 14
            $parser = new Parser($lexer->list);
205 14
            $errors = Error::get([$lexer, $parser]);
0 ignored issues
show
Bug introduced by
array($lexer, $parser) of type array<integer,PhpMyAdmin...Admin\SqlParser\Parser> is incompatible with the type array<integer|string,Php...Admin\SqlParser\Parser> expected by parameter $objs of PhpMyAdmin\SqlParser\Utils\Error::get(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

205
            $errors = Error::get(/** @scrutinizer ignore-type */ [$lexer, $parser]);
Loading history...
206 14
            if (count($errors) === 0) {
207 6
                return 0;
208
            }
209
210 8
            $output = Error::format($errors);
211 8
            echo implode("\n", $output);
212 8
            echo "\n";
213
214 8
            return 10;
215
        }
216
217 4
        echo "ERROR: Missing parameters!\n";
218 4
        $this->usageLint();
219
220 4
        return 1;
221
    }
222
223
    /**
224
     * @return void
225
     */
226 8
    public function usageTokenize()
227
    {
228 8
        echo "Usage: tokenize-query --query SQL [--ansi]\n";
229 8
        echo "       cat file.sql | tokenize-query\n";
230
    }
231
232
    /**
233
     * @return mixed
234
     */
235 18
    public function parseTokenize()
236
    {
237 18
        $longopts = [
238 18
            'help',
239 18
            'query:',
240 18
            'ansi',
241 18
        ];
242 18
        $params = $this->getopt('hq:a', $longopts);
243 18
        $this->mergeLongOpts($params, $longopts);
0 ignored issues
show
Bug introduced by
It seems like $params can also be of type false; however, parameter $params of PhpMyAdmin\SqlParser\Utils\CLI::mergeLongOpts() does only seem to accept array<mixed,false>|string[], maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

243
        $this->mergeLongOpts(/** @scrutinizer ignore-type */ $params, $longopts);
Loading history...
244
245 18
        return $params;
246
    }
247
248
    /**
249
     * @return int
250
     */
251 18
    public function runTokenize()
252
    {
253 18
        $params = $this->parseTokenize();
254 18
        if ($params === false) {
255 4
            return 1;
256
        }
257
258 14
        if (isset($params['h'])) {
259 4
            $this->usageTokenize();
260
261 4
            return 0;
262
        }
263
264 10
        if (! isset($params['q'])) {
265 6
            $stdIn = $this->readStdin();
266
267 6
            if ($stdIn) {
268 2
                $params['q'] = $stdIn;
269
            }
270
        }
271
272 10
        if (isset($params['a'])) {
273
            Context::setMode(Context::SQL_MODE_ANSI_QUOTES);
274
        }
275
276 10
        if (isset($params['q'])) {
277 6
            $lexer = new Lexer($params['q'], false);
278 6
            foreach ($lexer->list->tokens as $idx => $token) {
279 6
                echo '[TOKEN ', $idx, "]\n";
280 6
                echo 'Type = ', $token->type, "\n";
281 6
                echo 'Flags = ', $token->flags, "\n";
282 6
                echo 'Value = ';
283 6
                var_export($token->value);
284 6
                echo "\n";
285 6
                echo 'Token = ';
286 6
                var_export($token->token);
287 6
                echo "\n";
288 6
                echo "\n";
289
            }
290
291 6
            return 0;
292
        }
293
294 4
        echo "ERROR: Missing parameters!\n";
295 4
        $this->usageTokenize();
296
297 4
        return 1;
298
    }
299
300
    /**
301
     * @return string|false
302
     */
303 6
    public function readStdin()
304
    {
305 6
        $read = [STDIN];
306 6
        $write = [];
307 6
        $except = [];
308
309
        // Assume there's nothing to be read from STDIN.
310 6
        $stdin = null;
311
312
        // Try to read from STDIN.  Wait 0.2 second before timing out.
313 6
        $result = stream_select($read, $write, $except, 0, 2000);
314
315 6
        if ($result > 0) {
316 6
            $stdin = stream_get_contents(STDIN);
317
        }
318
319 6
        return $stdin;
320
    }
321
}
322