Stacktrace.php
3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<?php
namespace Facade\FlareClient\Stacktrace;
use Throwable;
class Stacktrace
{
    /** @var \Facade\FlareClient\Stacktrace\Frame[] */
    private $frames;
    /** @var string */
    private $applicationPath;
    public static function createForThrowable(Throwable $throwable, ?string $applicationPath = null): self
    {
        return new static($throwable->getTrace(),  $applicationPath, $throwable->getFile(), $throwable->getLine());
    }
    public static function create(?string $applicationPath = null): self
    {
        $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS & ~DEBUG_BACKTRACE_PROVIDE_OBJECT);
        return new static($backtrace, $applicationPath);
    }
    public function __construct(array $backtrace, ?string $applicationPath = null, string $topmostFile = null, string $topmostLine = null)
    {
        $this->applicationPath = $applicationPath;
        $currentFile = $topmostFile;
        $currentLine = $topmostLine;
        foreach ($backtrace as $rawFrame) {
            if (! $this->frameFromFlare($rawFrame) && ! $this->fileIgnored($currentFile)) {
                $this->frames[] = new Frame(
                    $currentFile,
                    $currentLine,
                    $rawFrame['function'] ?? null,
                    $rawFrame['class'] ?? null,
                    $this->frameFileFromApplication($currentFile)
                );
            }
            $currentFile = $rawFrame['file'] ?? 'unknown';
            $currentLine = $rawFrame['line'] ?? 0;
        }
        $this->frames[] = new Frame(
            $currentFile,
            $currentLine,
            '[top]'
        );
    }
    protected function frameFromFlare(array $rawFrame): bool
    {
        return isset($rawFrame['class']) && strpos($rawFrame['class'], 'Facade\\FlareClient\\') === 0;
    }
    protected function frameFileFromApplication(string $frameFilename): bool
    {
        $relativeFile = str_replace('\\', DIRECTORY_SEPARATOR, $frameFilename);
        if (! empty($this->applicationPath)) {
            $relativeFile = array_reverse(explode($this->applicationPath ?? '', $frameFilename, 2))[0];
        }
        if (strpos($relativeFile, DIRECTORY_SEPARATOR . 'vendor') === 0) {
            return false;
        }
        return true;
    }
    protected function fileIgnored(string $currentFile): bool
    {
        $currentFile = str_replace('\\', DIRECTORY_SEPARATOR, $currentFile);
        $ignoredFiles = [
            '/ignition/src/helpers.php',
        ];
        foreach ($ignoredFiles as $ignoredFile) {
            if (strstr($currentFile, $ignoredFile) !== false) {
                return true;
            }
        }
        return false;
    }
    public function firstFrame(): Frame
    {
        return $this->frames[0];
    }
    public function toArray(): array
    {
        return array_map(function (Frame $frame) {
            return $frame->toArray();
        }, $this->frames);
    }
    public function firstApplicationFrame(): ?Frame
    {
        foreach ($this->frames as $index => $frame) {
            if ($frame->isApplicationFrame()) {
                return $frame;
            }
        }
        return null;
    }
    public function firstApplicationFrameIndex(): ?int
    {
        foreach ($this->frames as $index => $frame) {
            if ($frame->isApplicationFrame()) {
                return $index;
            }
        }
        return null;
    }
}