Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Spatie\Backtrace;
4
 
5
use Closure;
6
use Throwable;
7
 
8
class Backtrace
9
{
10
    /** @var bool */
11
    protected $withArguments = false;
12
 
13
    /** @var bool */
14
    protected $withObject = false;
15
 
16
    /** @var string|null */
17
    protected $applicationPath;
18
 
19
    /** @var int */
20
    protected $offset = 0;
21
 
22
    /** @var int */
23
    protected $limit = 0;
24
 
25
    /** @var \Closure|null */
26
    protected $startingFromFrameClosure = null;
27
 
28
    /** @var \Throwable|null */
29
    protected $throwable = null;
30
 
31
    public static function create(): self
32
    {
33
        return new static();
34
    }
35
 
36
    public static function createForThrowable(Throwable $throwable): self
37
    {
38
        return (new static())->forThrowable($throwable);
39
    }
40
 
41
    protected function forThrowable(Throwable $throwable): self
42
    {
43
        $this->throwable = $throwable;
44
 
45
        return $this;
46
    }
47
 
48
    public function withArguments(): self
49
    {
50
        $this->withArguments = true;
51
 
52
        return $this;
53
    }
54
 
55
    public function withObject(): self
56
    {
57
        $this->withObject = true;
58
 
59
        return $this;
60
    }
61
 
62
    public function applicationPath(string $applicationPath): self
63
    {
64
        $this->applicationPath = $applicationPath;
65
 
66
        return $this;
67
    }
68
 
69
    public function offset(int $offset): self
70
    {
71
        $this->offset = $offset;
72
 
73
        return $this;
74
    }
75
 
76
    public function limit(int $limit): self
77
    {
78
        $this->limit = $limit;
79
 
80
        return $this;
81
    }
82
 
83
    public function startingFromFrame(Closure $startingFromFrameClosure)
84
    {
85
        $this->startingFromFrameClosure = $startingFromFrameClosure;
86
 
87
        return $this;
88
    }
89
 
90
    /**
91
     * @return \Spatie\Backtrace\Frame[]
92
     */
93
    public function frames(): array
94
    {
95
        $rawFrames = $this->getRawFrames();
96
 
97
        return $this->toFrameObjects($rawFrames);
98
    }
99
 
100
    public function firstApplicationFrameIndex(): ?int
101
    {
102
        foreach ($this->frames() as $index => $frame) {
103
            if ($frame->applicationFrame) {
104
                return $index;
105
            }
106
        }
107
 
108
        return null;
109
    }
110
 
111
    protected function getRawFrames(): array
112
    {
113
        if ($this->throwable) {
114
            return $this->throwable->getTrace();
115
        }
116
 
117
        $options = null;
118
 
119
        if (! $this->withArguments) {
120
            $options = $options | DEBUG_BACKTRACE_IGNORE_ARGS;
121
        }
122
 
123
        if ($this->withObject()) {
124
            $options = $options | DEBUG_BACKTRACE_PROVIDE_OBJECT;
125
        }
126
 
127
        $limit = $this->limit;
128
 
129
        if ($limit !== 0) {
130
            $limit += 3;
131
        }
132
 
133
        return debug_backtrace($options, $limit);
134
    }
135
 
136
    /**
137
     * @return \Spatie\Backtrace\Frame[]
138
     */
139
    protected function toFrameObjects(array $rawFrames): array
140
    {
141
        $currentFile = $this->throwable ? $this->throwable->getFile() : '';
142
        $currentLine = $this->throwable ? $this->throwable->getLine() : 0;
143
 
144
        $frames = [];
145
 
146
        foreach ($rawFrames as $rawFrame) {
147
            $frames[] = new Frame(
148
                $currentFile,
149
                $currentLine,
150
                $rawFrame['args'] ?? null,
151
                $rawFrame['function'] ?? null,
152
                $rawFrame['class'] ?? null,
153
                $this->isApplicationFrame($currentFile)
154
            );
155
 
156
            $currentFile = $rawFrame['file'] ?? 'unknown';
157
            $currentLine = $rawFrame['line'] ?? 0;
158
        }
159
 
160
        $frames[] = new Frame(
161
            $currentFile,
162
            $currentLine,
163
            [],
164
            '[top]'
165
        );
166
 
167
        $frames = $this->removeBacktracePackageFrames($frames);
168
 
169
        if ($closure = $this->startingFromFrameClosure) {
170
            $frames = $this->startAtFrameFromClosure($frames, $closure);
171
        }
172
        $frames = array_slice($frames, $this->offset, $this->limit === 0 ? PHP_INT_MAX : $this->limit);
173
 
174
        return array_values($frames);
175
    }
176
 
177
    protected function isApplicationFrame(string $frameFilename): bool
178
    {
179
        $relativeFile = str_replace('\\', DIRECTORY_SEPARATOR, $frameFilename);
180
 
181
        if (! empty($this->applicationPath)) {
182
            $relativeFile = array_reverse(explode($this->applicationPath ?? '', $frameFilename, 2))[0];
183
        }
184
 
185
        if (strpos($relativeFile, DIRECTORY_SEPARATOR . 'vendor') === 0) {
186
            return false;
187
        }
188
 
189
        return true;
190
    }
191
 
192
    protected function removeBacktracePackageFrames(array $frames): array
193
    {
194
        return $this->startAtFrameFromClosure($frames, function (Frame $frame) {
195
            return $frame->class !== static::class;
196
        });
197
    }
198
 
199
    /**
200
     * @param \Spatie\Backtrace\Frame[] $frames
201
     * @param \Closure $closure
202
     *
203
     * @return array
204
     */
205
    protected function startAtFrameFromClosure(array $frames, Closure $closure): array
206
    {
207
        foreach ($frames as $i => $frame) {
208
            $foundStartingFrame = $closure($frame);
209
 
210
            if ($foundStartingFrame) {
211
                return $frames;
212
            }
213
 
214
            unset($frames[$i]);
215
        }
216
 
217
        return $frames;
218
    }
219
}