Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of Psy Shell.
5
 *
200 lars 6
 * (c) 2012-2023 Justin Hileman
148 lars 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 Psy\Formatter;
13
 
14
use Psy\Input\FilterOptions;
15
use Symfony\Component\Console\Formatter\OutputFormatter;
16
 
17
/**
18
 * Output formatter for exception traces.
19
 */
20
class TraceFormatter
21
{
22
    /**
23
     * Format the trace of the given exception.
24
     *
25
     * @param \Throwable    $throwable  The error or exception with a backtrace
26
     * @param FilterOptions $filter     (default: null)
27
     * @param int           $count      (default: PHP_INT_MAX)
28
     * @param bool          $includePsy (default: true)
29
     *
30
     * @return string[] Formatted stacktrace lines
31
     */
32
    public static function formatTrace(\Throwable $throwable, FilterOptions $filter = null, int $count = null, bool $includePsy = true): array
33
    {
34
        if ($cwd = \getcwd()) {
35
            $cwd = \rtrim($cwd, \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR;
36
        }
37
 
38
        if ($count === null) {
39
            $count = \PHP_INT_MAX;
40
        }
41
 
42
        $lines = [];
43
 
44
        $trace = $throwable->getTrace();
45
        \array_unshift($trace, [
46
            'function' => '',
47
            'file'     => $throwable->getFile() !== null ? $throwable->getFile() : 'n/a',
48
            'line'     => $throwable->getLine() !== null ? $throwable->getLine() : 'n/a',
49
            'args'     => [],
50
        ]);
51
 
52
        if (!$includePsy) {
53
            for ($i = \count($trace) - 1; $i >= 0; $i--) {
54
                $thing = isset($trace[$i]['class']) ? $trace[$i]['class'] : $trace[$i]['function'];
55
                if (\preg_match('/\\\\?Psy\\\\/', $thing)) {
56
                    $trace = \array_slice($trace, $i + 1);
57
                    break;
58
                }
59
            }
60
        }
61
 
62
        for ($i = 0, $count = \min($count, \count($trace)); $i < $count; $i++) {
63
            $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
64
            $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
65
            $function = $trace[$i]['function'];
66
            $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
67
            $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
68
 
69
            // Make file paths relative to cwd
70
            if ($cwd !== false) {
71
                $file = \preg_replace('/^'.\preg_quote($cwd, '/').'/', '', $file);
72
            }
73
 
74
            // Leave execution loop out of the `eval()'d code` lines
75
            if (\preg_match("#/src/Execution(?:Loop)?Closure.php\(\d+\) : eval\(\)'d code$#", \str_replace('\\', '/', $file))) {
76
                $file = "eval()'d code";
77
            }
78
 
79
            // Skip any lines that don't match our filter options
80
            if ($filter !== null && !$filter->match(\sprintf('%s%s%s() at %s:%s', $class, $type, $function, $file, $line))) {
81
                continue;
82
            }
83
 
84
            $lines[] = \sprintf(
85
                ' <class>%s</class>%s%s() at <info>%s:%s</info>',
86
                OutputFormatter::escape($class),
87
                OutputFormatter::escape($type),
88
                OutputFormatter::escape($function),
89
                OutputFormatter::escape($file),
90
                OutputFormatter::escape($line)
91
            );
92
        }
93
 
94
        return $lines;
95
    }
96
}