1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
sql_format.php
См. документацию.
1<?php
2if (!defined('T_KEYWORD'))
3{
4 define('T_KEYWORD', 400);
5}
6if (!defined('T_BAD_CHARACTER'))
7{
8 define('T_BAD_CHARACTER', 401);
9}
10if (!defined('T_CHARACTER'))
11{
12 define('T_CHARACTER', 402);
13}
14
16{
17 public function format($tokens)
18 {
19 $result = '';
20 $skipWS = false;
21 foreach ($tokens as $i => $token)
22 {
23 if ($token[1] === ',')
24 {
26 $result .= ",\x3" . str_repeat("\x2", $token[2]);
27 $skipWS = true;
28 }
29 elseif (
30 $token[1] === '='
31 || $token[1] === '-'
32 || $token[1] === '+'
33 || $token[1] === '*'
34 || $token[1] === '/'
35 || $token[1] === '<='
36 || $token[1] === '>='
37 )
38 {
40 $result .= "\x1" . $token[1] . "\x1";
41 $skipWS = true;
42 }
43 elseif (
44 $token[1] === 'INNER'
45 || $token[1] === 'LEFT'
46 || $token[1] === 'SET'
47 || $token[1] === 'AND'
48 || $token[1] === 'OR'
49 )
50 {
51 $result .= "\x3" . str_repeat("\x2", $token[2]) . $token[1];
52 }
53 else
54 {
55 if ($skipWS)
56 {
57 $skipWS = false;
58 if ($token[0] === T_WHITESPACE)
59 {
60 continue;
61 }
62 }
63 elseif ($i > 0 && ($tokens[$i - 1][2] <> $token[2]))
64 {
65 $result .= "\x3" . str_repeat("\x2", $token[2]);
66 if ($token[0] === T_WHITESPACE)
67 {
68 continue;
69 }
70 }
71
72 if ($token[0] === T_WHITESPACE)
73 {
74 $result .= "\x1";
75 }
76 else
77 {
78 $result .= $token[1];
79 }
80 }
81 }
82
83 $result = preg_replace_callback("/(
84 \\([\\x1\\x2\\x3_0-9A-Za-z.0-9_,]+\\)
85 |\\([\\x1\\x2\\x3'x%0-9,]+\\)
86 |\\([\\x1\\x2\\x3]*[a-zA-Z0-9_.]+[\\x1\\x2\\x3]*=[\\x1\\x2\\x3]*[a-zA-Z0-9_.']+[\\x1\\x2\\x3]*\\)
87 )/x", [$this, 'removeSpaces'], $result);
88
89 $result = str_replace([
90 "\x1",
91 "\x2",
92 "\x3",
93 ], [
94 $this->getSpace(),
95 $this->getTab(),
96 $this->getEol(),
97 ], $result);
98
99 return $result;
100 }
101
102 public function removeSpaces($match)
103 {
104 $result = preg_replace("/^\\([\\x1\\x2\\x3]+/", '(', $match[0]);
105 $result = preg_replace("/[\\x1\\x2\\x3]+\\)\$/", ')', $result);
106 $result = preg_replace("/,[\\x1\\x2\\x3]+/", ', ', $result);
107 return $result;
108 }
109
110 public function removeTrailingSpaces(&$str)
111 {
112 $str = rtrim($str, "\x1\x2\x3");
113 }
114
115 public function getEol()
116 {
117 return ' ';
118 }
119
120 public function getSpace()
121 {
122 return ' ';
123 }
124
125 public function getTab()
126 {
127 return ' ';
128 }
129}
130
132{
133 public function getEol()
134 {
135 return "\n";
136 }
137
138 public function getSpace()
139 {
140 return ' ';
141 }
142
143 public function getTab()
144 {
145 return "\t";
146 }
147}
148
150{
151 private $tokens = null;
152 private $current = 0;
153
154 public function parse($sql)
155 {
156 $this->tokens = token_get_all('<?' . $sql);
157 array_shift($this->tokens);
158 $this->current = 0;
159
160 while (isset($this->tokens[$this->current]))
161 {
162 //Remove excessive brackets
163 if (
164 $this->tokens[$this->current] === '('
165 && $this->lookForwardFor('(')
166 )
167 {
168 if ($this->removeBalancedBrackets())
169 {
170 continue;
171 }
172 }
173
174 //Remove following spaces
175 if ($this->tokens[$this->current][0] === T_WHITESPACE && $this->tokens[$this->current - 1][0] === T_WHITESPACE)
176 {
177 array_splice($this->tokens, $this->current, 1);
178 continue;
179 }
180
181 $this->tokens[$this->current] = $this->transform($this->tokens[$this->current]);
182 $this->current++;
183 }
184
185 //Remove leading spaces
186 while (
187 isset($this->tokens[0])
188 && $this->tokens[0][0] === T_WHITESPACE
189 )
190 {
191 array_splice($this->tokens, 0, 1);
192 }
193
194 //Remove trailing spaces
195 while (
196 !empty($this->tokens)
197 && $this->tokens[count($this->tokens) - 1][0] === T_WHITESPACE
198 )
199 {
200 array_splice($this->tokens, -1, 1);
201 }
202
203 return $this->tokens;
204 }
205
206 protected function transform($token)
207 {
208 static $keywords = 'UPDATE|SET|DELETE|SELECT|DISTINCT|INNER|LEFT|OUTER|JOIN|ON|FROM|WHERE|GROUP|BY|IN|EXISTS|HAVING|ORDER|ASC|DESC|LIMIT|AND|OR';
209 static $functions = 'DATE_FORMAT|UNIX_TIMESTAMP|CONCAT|DATE_ADD|UPPER|LENGTH|IFNULL';
210
211 if (isset($token[1]))
212 {
213 $token = [$token[0], $token[1]];
214 }
215 else
216 {
217 $token = [T_CHARACTER, $token[0]];
218 }
219
220 switch ($token[0])
221 {
222 case T_STRING:
223 if (preg_match('/^(' . $keywords . ')$/i', $token[1]))
224 {
225 $token = [T_KEYWORD, mb_strtoupper($token[1])];
226 }
227 elseif (preg_match('/^(' . $functions . ')$/i', $token[1]))
228 {
229 $token = [T_FUNCTION, $token[1]];
230 }
231 break;
232 case T_LOGICAL_AND:
233 case T_LOGICAL_OR:
234 $token = [T_KEYWORD, mb_strtoupper($token[1])];
235 break;
236 case T_AS:
237 $token = [T_KEYWORD, $token[1]];
238 break;
239 case T_COMMENT:
240 case T_BAD_CHARACTER:
241 $token = [T_WHITESPACE, ' '];
242 break;
243 }
244
245 return $token;
246 }
247
248 protected function removeBalancedBrackets()
249 {
250 $pos = $this->current;
251 $balance = 0;
252 $hasOp = [false];
253 while (isset($this->tokens[$pos]))
254 {
255 if ($this->tokens[$pos][0] === '(')
256 {
257 $balance++;
258 $hasOp[$balance] = false;
259 }
260 elseif ($this->tokens[$pos][0] === ')')
261 {
262 $balance--;
263 }
264 elseif (
265 $this->tokens[$pos][0] === T_LOGICAL_AND
266 || $this->tokens[$pos][0] === T_LOGICAL_OR
267 || $this->tokens[$pos][0] === ','
268 )
269 {
270 $hasOp[$balance] = true;
271 }
272
273 if ($balance === 0)
274 {
275 if (!$hasOp[$balance + 1])
276 {
277 array_splice($this->tokens, $pos, 1);
278 array_splice($this->tokens, $this->current, 1);
279 return true;
280 }
281 else
282 {
283 return false;
284 }
285 }
286 $pos++;
287 }
288 return false;
289 }
290
291 protected function lookForwardFor($token)
292 {
293 $pos = $this->current + 1;
294 while (isset($this->tokens[$pos]))
295 {
296 if ($this->tokens[$pos] == $token)
297 {
298 return true;
299 }
300 elseif ($this->tokens[$pos][0] !== T_WHITESPACE)
301 {
302 return false;
303 }
304 $pos++;
305 }
306 return false;
307 }
308}
309
311{
312 private $tokens = [];
313 private $balance = 0;
314 private $level = 0;
315 private $current = 0;
316
317 public function addLevel(array $tokens)
318 {
319 $this->level = [];
320 $this->balance = 0;
321 $this->tokens = $tokens;
322 $this->current = 0;
323 while (isset($this->tokens[$this->current]))
324 {
325 if ($this->tokens[$this->current][1] === '(')
326 {
327 $this->balance++;
328 }
329 elseif ($this->tokens[$this->current][1] === ')')
330 {
331 $this->balance--;
332 }
333
334 if ($this->tokens[$this->current][0] !== T_WHITESPACE)
335 {
336 $this->changeLevelBefore();
337 }
338
339 $this->tokens[$this->current][] = array_sum($this->level);
340
341 if ($this->tokens[$this->current][0] !== T_WHITESPACE)
342 {
343 $this->changeLevelAfter();
344 }
345
346 $this->current++;
347 }
348
349 return $this->tokens;
350 }
351
352 public function changeLevelBefore()
353 {
354 if ($this->tokens[$this->current][1] === ')')
355 {
356 $this->level['(']--;
357 $this->level['SELECT_' . ($this->balance + 1)] = 0;
358 $this->level['JOIN_' . ($this->balance + 1)] = 0;
359 }
360 elseif (
361 $this->tokens[$this->current][1] === 'FROM'
362 || $this->tokens[$this->current][1] === 'LIMIT'
363 )
364 {
365 $this->level['SELECT_' . $this->balance]--;
366 }
367 elseif (
368 $this->tokens[$this->current][1] === 'WHERE'
369 || $this->tokens[$this->current][1] === 'GROUP'
370 || $this->tokens[$this->current][1] === 'HAVING'
371 || $this->tokens[$this->current][1] === 'ORDER'
372 )
373 {
374 $this->level['SELECT_' . $this->balance]--;
375 if ($this->level['JOIN_' . $this->balance] ?? 0)
376 {
377 $this->level['JOIN_' . $this->balance]--;
378 }
379 }
380 elseif (
381 $this->tokens[$this->current][1] === 'INNER'
382 || $this->tokens[$this->current][1] === 'LEFT'
383 )
384 {
385 if ($this->level['JOIN_' . $this->balance] > 0)
386 {
387 $this->level['JOIN_' . $this->balance]--;
388 }
389 }
390 }
391
392 public function changeLevelAfter()
393 {
394 if ($this->tokens[$this->current][1] === '(')
395 {
396 if (isset($this->level['(']))
397 {
398 $this->level['(']++;
399 }
400 else
401 {
402 $this->level['('] = 1;
403 }
404 }
405 elseif (
406 (
407 $this->tokens[$this->current][1] === 'SELECT'
408 && !$this->lookForwardFor('DISTINCT')
409 ) || (
410 $this->tokens[$this->current][1] === 'DISTINCT'
411 )
412 )
413 {
414 if (isset($this->level['SELECT_' . $this->balance]))
415 {
416 $this->level['SELECT_' . $this->balance]++;
417 }
418 else
419 {
420 $this->level['SELECT_' . $this->balance] = 1;
421 }
422 }
423 elseif (
424 $this->tokens[$this->current][1] === 'FROM'
425 || $this->tokens[$this->current][1] === 'WHERE'
426 || $this->tokens[$this->current][1] === 'BY'
427 || $this->tokens[$this->current][1] === 'HAVING'
428 || $this->tokens[$this->current][1] === 'SET'
429 )
430 {
431 if (isset($this->level['SELECT_' . $this->balance]))
432 {
433 $this->level['SELECT_' . $this->balance]++;
434 }
435 else
436 {
437 $this->level['SELECT_' . $this->balance] = 1;
438 }
439 }
440 elseif ($this->tokens[$this->current][1] === 'ON')
441 {
442 if (isset($this->level['JOIN_' . $this->balance]))
443 {
444 $this->level['JOIN_' . $this->balance]++;
445 }
446 else
447 {
448 $this->level['JOIN_' . $this->balance] = 1;
449 }
450 }
451 }
452
453 protected function lookForwardFor($token)
454 {
455 $pos = $this->current + 1;
456 while (isset($this->tokens[$pos]))
457 {
458 if ($this->tokens[$pos][1] == $token)
459 {
460 return true;
461 }
462 elseif ($this->tokens[$pos][0] !== T_WHITESPACE)
463 {
464 return false;
465 }
466 $pos++;
467 }
468 return false;
469 }
470
471 protected function lookBackwardFor($token)
472 {
473 $pos = $this->current - 1;
474 while (isset($this->tokens[$pos]))
475 {
476 if ($this->tokens[$pos][1] == $token)
477 {
478 return true;
479 }
480 elseif ($this->tokens[$pos][0] !== T_WHITESPACE)
481 {
482 return false;
483 }
484 $pos--;
485 }
486 return false;
487 }
488}
489
491{
493 private $tokenizer = null;
495 private $levelizer = null;
496
497 private $current = null;
498 private $level = 0;
499 private $add = 0;
500 private $result = '';
502 private $formatter = null;
503
504 public function __construct()
505 {
506 $this->tokenizer = new CSqlTokenizer;
507 $this->levelizer = new CSqlLevel;
508
509 $this->level = 0;
510 $this->add = 0;
511 $this->current = 0;
512 $this->result = '';
513 }
514
515 public static function reformatSql($sql, CSqlFormatFormatter $formatter = null)
516 {
517 if (function_exists('token_get_all'))
518 {
519 $format = new CSqlFormat;
520 $format->setFormatter($formatter ?? new CSqlFormatText);
521 return $format->format($sql);
522 }
523 else
524 {
525 return $sql;
526 }
527 }
528
529 public function setFormatter(CSqlFormatFormatter $formatter)
530 {
531 $this->formatter = $formatter;
532 }
533
534 public function format($sql)
535 {
536 $tokens = $this->tokenizer->parse($sql);
537 $tokens = $this->levelizer->addLevel($tokens);
538 return $this->formatter->format($tokens);
539 }
540}
format($tokens)
Определения sql_format.php:17
removeTrailingSpaces(&$str)
Определения sql_format.php:110
getSpace()
Определения sql_format.php:120
getTab()
Определения sql_format.php:125
removeSpaces($match)
Определения sql_format.php:102
getEol()
Определения sql_format.php:115
Определения sql_format.php:491
__construct()
Определения sql_format.php:504
format($sql)
Определения sql_format.php:534
setFormatter(CSqlFormatFormatter $formatter)
Определения sql_format.php:529
static reformatSql($sql, CSqlFormatFormatter $formatter=null)
Определения sql_format.php:515
Определения sql_format.php:132
getSpace()
Определения sql_format.php:138
getTab()
Определения sql_format.php:143
getEol()
Определения sql_format.php:133
Определения sql_format.php:311
addLevel(array $tokens)
Определения sql_format.php:317
changeLevelAfter()
Определения sql_format.php:392
lookForwardFor($token)
Определения sql_format.php:453
changeLevelBefore()
Определения sql_format.php:352
lookBackwardFor($token)
Определения sql_format.php:471
Определения sql_format.php:150
lookForwardFor($token)
Определения sql_format.php:291
removeBalancedBrackets()
Определения sql_format.php:248
transform($token)
Определения sql_format.php:206
parse($sql)
Определения sql_format.php:154
$str
Определения commerceml2.php:63
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$i
Определения factura.php:643
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936