PluginProbe ʕ •ᴥ•ʔ
Kubio AI Page Builder / 2.8.6
Kubio AI Page Builder v2.8.6
2.9.0 2.8.6 2.8.5 2.8.4 2.8.3 2.8.2 2.8.1 trunk 1.0.0 1.0.1 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.9.0 2.0.0 2.1.1 2.1.2 2.1.3 2.2.0 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.5 2.5.0 2.5.1 2.5.2 2.5.3 2.6.0 2.6.1 2.6.2 2.6.3 2.6.5 2.6.6 2.6.7 2.7.0 2.7.1 2.7.2 2.7.3 2.8.0
kubio / vendor / symfony / var-dumper / Dumper / CliDumper.php
kubio / vendor / symfony / var-dumper / Dumper Last commit date
ContextProvider 1 year ago AbstractDumper.php 1 year ago CliDumper.php 1 year ago ContextualizedDumper.php 4 years ago DataDumperInterface.php 4 years ago HtmlDumper.php 1 year ago ServerDumper.php 1 year ago
CliDumper.php
675 lines
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Symfony\Component\VarDumper\Dumper;
13
14 use Symfony\Component\VarDumper\Cloner\Cursor;
15 use Symfony\Component\VarDumper\Cloner\Stub;
16
17 /**
18 * CliDumper dumps variables for command line output.
19 *
20 * @author Nicolas Grekas <p@tchwork.com>
21 */
22 class CliDumper extends AbstractDumper
23 {
24 public static $defaultColors;
25 public static $defaultOutput = 'php://stdout';
26
27 protected $colors;
28 protected $maxStringWidth = 0;
29 protected $styles = [
30 // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
31 'default' => '0;38;5;208',
32 'num' => '1;38;5;38',
33 'const' => '1;38;5;208',
34 'str' => '1;38;5;113',
35 'note' => '38;5;38',
36 'ref' => '38;5;247',
37 'public' => '',
38 'protected' => '',
39 'private' => '',
40 'meta' => '38;5;170',
41 'key' => '38;5;113',
42 'index' => '38;5;38',
43 ];
44
45 protected static $controlCharsRx = '/[\x00-\x1F\x7F]+/';
46 protected static $controlCharsMap = [
47 "\t" => '\t',
48 "\n" => '\n',
49 "\v" => '\v',
50 "\f" => '\f',
51 "\r" => '\r',
52 "\033" => '\e',
53 ];
54
55 protected $collapseNextHash = false;
56 protected $expandNextHash = false;
57
58 private $displayOptions = [
59 'fileLinkFormat' => null,
60 ];
61
62 private $handlesHrefGracefully;
63
64 /**
65 * {@inheritdoc}
66 */
67 public function __construct($output = null, ?string $charset = null, int $flags = 0)
68 {
69 parent::__construct($output, $charset, $flags);
70
71 if ('\\' === \DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) {
72 // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI
73 $this->setStyles([
74 'default' => '31',
75 'num' => '1;34',
76 'const' => '1;31',
77 'str' => '1;32',
78 'note' => '34',
79 'ref' => '1;30',
80 'meta' => '35',
81 'key' => '32',
82 'index' => '34',
83 ]);
84 }
85
86 $this->displayOptions['fileLinkFormat'] = \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l';
87 }
88
89 /**
90 * Enables/disables colored output.
91 */
92 public function setColors(bool $colors)
93 {
94 $this->colors = $colors;
95 }
96
97 /**
98 * Sets the maximum number of characters per line for dumped strings.
99 */
100 public function setMaxStringWidth(int $maxStringWidth)
101 {
102 $this->maxStringWidth = $maxStringWidth;
103 }
104
105 /**
106 * Configures styles.
107 *
108 * @param array $styles A map of style names to style definitions
109 */
110 public function setStyles(array $styles)
111 {
112 $this->styles = $styles + $this->styles;
113 }
114
115 /**
116 * Configures display options.
117 *
118 * @param array $displayOptions A map of display options to customize the behavior
119 */
120 public function setDisplayOptions(array $displayOptions)
121 {
122 $this->displayOptions = $displayOptions + $this->displayOptions;
123 }
124
125 /**
126 * {@inheritdoc}
127 */
128 public function dumpScalar(Cursor $cursor, string $type, $value)
129 {
130 $this->dumpKey($cursor);
131 $this->collapseNextHash = $this->expandNextHash = false;
132
133 $style = 'const';
134 $attr = $cursor->attr;
135
136 switch ($type) {
137 case 'default':
138 $style = 'default';
139 break;
140
141 case 'integer':
142 $style = 'num';
143
144 if (isset($this->styles['integer'])) {
145 $style = 'integer';
146 }
147
148 break;
149
150 case 'double':
151 $style = 'num';
152
153 if (isset($this->styles['float'])) {
154 $style = 'float';
155 }
156
157 switch (true) {
158 case \INF === $value: $value = 'INF'; break;
159 case -\INF === $value: $value = '-INF'; break;
160 case is_nan($value): $value = 'NAN'; break;
161 default:
162 $value = (string) $value;
163 if (!str_contains($value, $this->decimalPoint)) {
164 $value .= $this->decimalPoint.'0';
165 }
166 break;
167 }
168 break;
169
170 case 'NULL':
171 $value = 'null';
172 break;
173
174 case 'boolean':
175 $value = $value ? 'true' : 'false';
176 break;
177
178 default:
179 $attr += ['value' => $this->utf8Encode($value)];
180 $value = $this->utf8Encode($type);
181 break;
182 }
183
184 $this->line .= $this->style($style, $value, $attr);
185
186 $this->endValue($cursor);
187 }
188
189 /**
190 * {@inheritdoc}
191 */
192 public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut)
193 {
194 $this->dumpKey($cursor);
195 $this->collapseNextHash = $this->expandNextHash = false;
196 $attr = $cursor->attr;
197
198 if ($bin) {
199 $str = $this->utf8Encode($str);
200 }
201 if ('' === $str) {
202 $this->line .= '""';
203 if ($cut) {
204 $this->line .= ''.$cut;
205 }
206 $this->endValue($cursor);
207 } else {
208 $attr += [
209 'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0,
210 'binary' => $bin,
211 ];
212 $str = $bin && false !== strpos($str, "\0") ? [$str] : explode("\n", $str);
213 if (isset($str[1]) && !isset($str[2]) && !isset($str[1][0])) {
214 unset($str[1]);
215 $str[0] .= "\n";
216 }
217 $m = \count($str) - 1;
218 $i = $lineCut = 0;
219
220 if (self::DUMP_STRING_LENGTH & $this->flags) {
221 $this->line .= '('.$attr['length'].') ';
222 }
223 if ($bin) {
224 $this->line .= 'b';
225 }
226
227 if ($m) {
228 $this->line .= '"""';
229 $this->dumpLine($cursor->depth);
230 } else {
231 $this->line .= '"';
232 }
233
234 foreach ($str as $str) {
235 if ($i < $m) {
236 $str .= "\n";
237 }
238 if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) {
239 $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8');
240 $lineCut = $len - $this->maxStringWidth;
241 }
242 if ($m && 0 < $cursor->depth) {
243 $this->line .= $this->indentPad;
244 }
245 if ('' !== $str) {
246 $this->line .= $this->style('str', $str, $attr);
247 }
248 if ($i++ == $m) {
249 if ($m) {
250 if ('' !== $str) {
251 $this->dumpLine($cursor->depth);
252 if (0 < $cursor->depth) {
253 $this->line .= $this->indentPad;
254 }
255 }
256 $this->line .= '"""';
257 } else {
258 $this->line .= '"';
259 }
260 if ($cut < 0) {
261 $this->line .= '';
262 $lineCut = 0;
263 } elseif ($cut) {
264 $lineCut += $cut;
265 }
266 }
267 if ($lineCut) {
268 $this->line .= ''.$lineCut;
269 $lineCut = 0;
270 }
271
272 if ($i > $m) {
273 $this->endValue($cursor);
274 } else {
275 $this->dumpLine($cursor->depth);
276 }
277 }
278 }
279 }
280
281 /**
282 * {@inheritdoc}
283 */
284 public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild)
285 {
286 if (null === $this->colors) {
287 $this->colors = $this->supportsColors();
288 }
289
290 $this->dumpKey($cursor);
291 $this->expandNextHash = false;
292 $attr = $cursor->attr;
293
294 if ($this->collapseNextHash) {
295 $cursor->skipChildren = true;
296 $this->collapseNextHash = $hasChild = false;
297 }
298
299 $class = $this->utf8Encode($class);
300 if (Cursor::HASH_OBJECT === $type) {
301 $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).(empty($attr['cut_hash']) ? ' {' : '') : '{';
302 } elseif (Cursor::HASH_RESOURCE === $type) {
303 $prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' ');
304 } else {
305 $prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class).' [' : '[';
306 }
307
308 if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) {
309 $prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#').(0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]);
310 } elseif ($cursor->hardRefTo && !$cursor->refIndex && $class) {
311 $prefix .= $this->style('ref', '&'.$cursor->hardRefTo, ['count' => $cursor->hardRefCount]);
312 } elseif (!$hasChild && Cursor::HASH_RESOURCE === $type) {
313 $prefix = substr($prefix, 0, -1);
314 }
315
316 $this->line .= $prefix;
317
318 if ($hasChild) {
319 $this->dumpLine($cursor->depth);
320 }
321 }
322
323 /**
324 * {@inheritdoc}
325 */
326 public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut)
327 {
328 if (empty($cursor->attr['cut_hash'])) {
329 $this->dumpEllipsis($cursor, $hasChild, $cut);
330 $this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : ''));
331 }
332
333 $this->endValue($cursor);
334 }
335
336 /**
337 * Dumps an ellipsis for cut children.
338 *
339 * @param bool $hasChild When the dump of the hash has child item
340 * @param int $cut The number of items the hash has been cut by
341 */
342 protected function dumpEllipsis(Cursor $cursor, bool $hasChild, int $cut)
343 {
344 if ($cut) {
345 $this->line .= '';
346 if (0 < $cut) {
347 $this->line .= $cut;
348 }
349 if ($hasChild) {
350 $this->dumpLine($cursor->depth + 1);
351 }
352 }
353 }
354
355 /**
356 * Dumps a key in a hash structure.
357 */
358 protected function dumpKey(Cursor $cursor)
359 {
360 if (null !== $key = $cursor->hashKey) {
361 if ($cursor->hashKeyIsBinary) {
362 $key = $this->utf8Encode($key);
363 }
364 $attr = ['binary' => $cursor->hashKeyIsBinary];
365 $bin = $cursor->hashKeyIsBinary ? 'b' : '';
366 $style = 'key';
367 switch ($cursor->hashType) {
368 default:
369 case Cursor::HASH_INDEXED:
370 if (self::DUMP_LIGHT_ARRAY & $this->flags) {
371 break;
372 }
373 $style = 'index';
374 // no break
375 case Cursor::HASH_ASSOC:
376 if (\is_int($key)) {
377 $this->line .= $this->style($style, $key).' => ';
378 } else {
379 $this->line .= $bin.'"'.$this->style($style, $key).'" => ';
380 }
381 break;
382
383 case Cursor::HASH_RESOURCE:
384 $key = "\0~\0".$key;
385 // no break
386 case Cursor::HASH_OBJECT:
387 if (!isset($key[0]) || "\0" !== $key[0]) {
388 $this->line .= '+'.$bin.$this->style('public', $key).': ';
389 } elseif (0 < strpos($key, "\0", 1)) {
390 $key = explode("\0", substr($key, 1), 2);
391
392 switch ($key[0][0]) {
393 case '+': // User inserted keys
394 $attr['dynamic'] = true;
395 $this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": ';
396 break 2;
397 case '~':
398 $style = 'meta';
399 if (isset($key[0][1])) {
400 parse_str(substr($key[0], 1), $attr);
401 $attr += ['binary' => $cursor->hashKeyIsBinary];
402 }
403 break;
404 case '*':
405 $style = 'protected';
406 $bin = '#'.$bin;
407 break;
408 default:
409 $attr['class'] = $key[0];
410 $style = 'private';
411 $bin = '-'.$bin;
412 break;
413 }
414
415 if (isset($attr['collapse'])) {
416 if ($attr['collapse']) {
417 $this->collapseNextHash = true;
418 } else {
419 $this->expandNextHash = true;
420 }
421 }
422
423 $this->line .= $bin.$this->style($style, $key[1], $attr).($attr['separator'] ?? ': ');
424 } else {
425 // This case should not happen
426 $this->line .= '-'.$bin.'"'.$this->style('private', $key, ['class' => '']).'": ';
427 }
428 break;
429 }
430
431 if ($cursor->hardRefTo) {
432 $this->line .= $this->style('ref', '&'.($cursor->hardRefCount ? $cursor->hardRefTo : ''), ['count' => $cursor->hardRefCount]).' ';
433 }
434 }
435 }
436
437 /**
438 * Decorates a value with some style.
439 *
440 * @param string $style The type of style being applied
441 * @param string $value The value being styled
442 * @param array $attr Optional context information
443 *
444 * @return string
445 */
446 protected function style(string $style, string $value, array $attr = [])
447 {
448 if (null === $this->colors) {
449 $this->colors = $this->supportsColors();
450 }
451
452 if (null === $this->handlesHrefGracefully) {
453 $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR')
454 && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100)
455 && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']);
456 }
457
458 if (isset($attr['ellipsis'], $attr['ellipsis-type'])) {
459 $prefix = substr($value, 0, -$attr['ellipsis']);
460 if ('cli' === \PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === \DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && str_starts_with($prefix, $_SERVER[$pwd])) {
461 $prefix = '.'.substr($prefix, \strlen($_SERVER[$pwd]));
462 }
463 if (!empty($attr['ellipsis-tail'])) {
464 $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']);
465 $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']);
466 } else {
467 $value = substr($value, -$attr['ellipsis']);
468 }
469
470 $value = $this->style('default', $prefix).$this->style($style, $value);
471
472 goto href;
473 }
474
475 $map = static::$controlCharsMap;
476 $startCchr = $this->colors ? "\033[m\033[{$this->styles['default']}m" : '';
477 $endCchr = $this->colors ? "\033[m\033[{$this->styles[$style]}m" : '';
478 $value = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $startCchr, $endCchr) {
479 $s = $startCchr;
480 $c = $c[$i = 0];
481 do {
482 $s .= $map[$c[$i]] ?? sprintf('\x%02X', \ord($c[$i]));
483 } while (isset($c[++$i]));
484
485 return $s.$endCchr;
486 }, $value, -1, $cchrCount);
487
488 if ($this->colors) {
489 if ($cchrCount && "\033" === $value[0]) {
490 $value = substr($value, \strlen($startCchr));
491 } else {
492 $value = "\033[{$this->styles[$style]}m".$value;
493 }
494 if ($cchrCount && str_ends_with($value, $endCchr)) {
495 $value = substr($value, 0, -\strlen($endCchr));
496 } else {
497 $value .= "\033[{$this->styles['default']}m";
498 }
499 }
500
501 href:
502 if ($this->colors && $this->handlesHrefGracefully) {
503 if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) {
504 if ('note' === $style) {
505 $value .= "\033]8;;{$href}\033\\^\033]8;;\033\\";
506 } else {
507 $attr['href'] = $href;
508 }
509 }
510 if (isset($attr['href'])) {
511 $value = "\033]8;;{$attr['href']}\033\\{$value}\033]8;;\033\\";
512 }
513 } elseif ($attr['if_links'] ?? false) {
514 return '';
515 }
516
517 return $value;
518 }
519
520 /**
521 * @return bool
522 */
523 protected function supportsColors()
524 {
525 if ($this->outputStream !== static::$defaultOutput) {
526 return $this->hasColorSupport($this->outputStream);
527 }
528 if (null !== static::$defaultColors) {
529 return static::$defaultColors;
530 }
531 if (isset($_SERVER['argv'][1])) {
532 $colors = $_SERVER['argv'];
533 $i = \count($colors);
534 while (--$i > 0) {
535 if (isset($colors[$i][5])) {
536 switch ($colors[$i]) {
537 case '--ansi':
538 case '--color':
539 case '--color=yes':
540 case '--color=force':
541 case '--color=always':
542 case '--colors=always':
543 return static::$defaultColors = true;
544
545 case '--no-ansi':
546 case '--color=no':
547 case '--color=none':
548 case '--color=never':
549 case '--colors=never':
550 return static::$defaultColors = false;
551 }
552 }
553 }
554 }
555
556 $h = stream_get_meta_data($this->outputStream) + ['wrapper_type' => null];
557 $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'w') : $this->outputStream;
558
559 return static::$defaultColors = $this->hasColorSupport($h);
560 }
561
562 /**
563 * {@inheritdoc}
564 */
565 protected function dumpLine(int $depth, bool $endOfValue = false)
566 {
567 if (null === $this->colors) {
568 $this->colors = $this->supportsColors();
569 }
570
571 if ($this->colors) {
572 $this->line = sprintf("\033[%sm%s\033[m", $this->styles['default'], $this->line);
573 }
574 parent::dumpLine($depth);
575 }
576
577 protected function endValue(Cursor $cursor)
578 {
579 if (-1 === $cursor->hashType) {
580 return;
581 }
582
583 if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) {
584 if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) {
585 $this->line .= ',';
586 } elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) {
587 $this->line .= ',';
588 }
589 }
590
591 $this->dumpLine($cursor->depth, true);
592 }
593
594 /**
595 * Returns true if the stream supports colorization.
596 *
597 * Reference: Composer\XdebugHandler\Process::supportsColor
598 * https://github.com/composer/xdebug-handler
599 *
600 * @param mixed $stream A CLI output stream
601 */
602 private function hasColorSupport($stream): bool
603 {
604 if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) {
605 return false;
606 }
607
608 // Follow https://no-color.org/
609 if ('' !== (($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR'))[0] ?? '')) {
610 return false;
611 }
612
613 // Detect msysgit/mingw and assume this is a tty because detection
614 // does not work correctly, see https://github.com/composer/composer/issues/9690
615 if (!@stream_isatty($stream) && !\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) {
616 return false;
617 }
618
619 if ('\\' === \DIRECTORY_SEPARATOR && @sapi_windows_vt100_support($stream)) {
620 return true;
621 }
622
623 if ('Hyper' === getenv('TERM_PROGRAM')
624 || false !== getenv('COLORTERM')
625 || false !== getenv('ANSICON')
626 || 'ON' === getenv('ConEmuANSI')
627 ) {
628 return true;
629 }
630
631 if ('dumb' === $term = (string) getenv('TERM')) {
632 return false;
633 }
634
635 // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157
636 return preg_match('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/', $term);
637 }
638
639 /**
640 * Returns true if the Windows terminal supports true color.
641 *
642 * Note that this does not check an output stream, but relies on environment
643 * variables from known implementations, or a PHP and Windows version that
644 * supports true color.
645 */
646 private function isWindowsTrueColor(): bool
647 {
648 $result = 183 <= getenv('ANSICON_VER')
649 || 'ON' === getenv('ConEmuANSI')
650 || 'xterm' === getenv('TERM')
651 || 'Hyper' === getenv('TERM_PROGRAM');
652
653 if (!$result) {
654 $version = sprintf(
655 '%s.%s.%s',
656 PHP_WINDOWS_VERSION_MAJOR,
657 PHP_WINDOWS_VERSION_MINOR,
658 PHP_WINDOWS_VERSION_BUILD
659 );
660 $result = $version >= '10.0.15063';
661 }
662
663 return $result;
664 }
665
666 private function getSourceLink(string $file, int $line)
667 {
668 if ($fmt = $this->displayOptions['fileLinkFormat']) {
669 return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file.'#L'.$line);
670 }
671
672 return false;
673 }
674 }
675