Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
199 lars 1
<?php namespace Clockwork\Helpers;
2
 
3
// A stack trace
4
class StackTrace
5
{
6
	use Concerns\ResolvesViewName;
7
 
8
	protected $frames;
9
 
10
	protected $basePath;
11
	protected $vendorPath;
12
 
13
	// Capture a new stack trace, accepts an array of options, "arguments" to include arguments in the trace and "limit"
14
	// to limit the trace length
15
	public static function get($options = [])
16
	{
17
		$backtraceOptions = isset($options['arguments'])
18
			? DEBUG_BACKTRACE_PROVIDE_OBJECT : DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS;
19
		$limit = isset($options['limit']) ? $options['limit'] : 0;
20
 
21
		return static::from(debug_backtrace($backtraceOptions, $limit));
22
	}
23
 
24
	// Create a stack trace from an existing debug_backtrace output
25
	public static function from(array $trace)
26
	{
27
		$basePath = static::resolveBasePath();
28
		$vendorPath = static::resolveVendorPath();
29
 
30
		return new static(array_map(function ($frame, $index) use ($basePath, $vendorPath, $trace) {
31
			return new StackFrame(
32
				static::fixCallUserFuncFrame($frame, $trace, $index), $basePath, $vendorPath
33
			);
34
		}, $trace, array_keys($trace)), $basePath, $vendorPath);
35
	}
36
 
37
	public function __construct(array $frames, $basePath, $vendorPath)
38
	{
39
		$this->frames = $frames;
40
		$this->basePath = $basePath;
41
		$this->vendorPath = $vendorPath;
42
	}
43
 
44
	// Get all frames
45
	public function frames()
46
	{
47
		return $this->frames;
48
	}
49
 
50
	// Get the first frame, optionally filtered by a stack filter or a closure
51
	public function first($filter = null)
52
	{
53
		if (! $filter) return reset($this->frames);
54
 
55
		if ($filter instanceof StackFilter) $filter = $filter->closure();
56
 
57
		foreach ($this->frames as $frame) {
58
			if ($filter($frame)) return $frame;
59
		}
60
	}
61
 
62
	// Get the last frame, optionally filtered by a stack filter or a closure
63
	public function last($filter = null)
64
	{
65
		if (! $filter) return $this->frames[count($this->frames) - 1];
66
 
67
		if ($filter instanceof StackFilter) $filter = $filter->closure();
68
 
69
		foreach (array_reverse($this->frames) as $frame) {
70
			if ($filter($frame)) return $frame;
71
		}
72
	}
73
 
74
	// Get trace filtered by a stack filter or a closure
75
	public function filter($filter = null)
76
	{
77
		if ($filter instanceof StackFilter) $filter = $filter->closure();
78
 
79
		return $this->copy(array_values(array_filter($this->frames, $filter)));
80
	}
81
 
82
	// Get trace skipping a number of frames or frames matching a stack filter or a closure
83
	public function skip($count = null)
84
	{
85
		if ($count instanceof StackFilter) $count = $count->closure();
86
		if ($count instanceof \Closure) $count = array_search($this->first($count), $this->frames);
87
 
88
		return $this->copy(array_slice($this->frames, $count));
89
	}
90
 
91
	// Get trace with a number of frames from the top
92
	public function limit($count = null)
93
	{
94
		return $this->copy(array_slice($this->frames, 0, $count));
95
	}
96
 
97
	// Get a copy of the trace
98
	public function copy($frames = null)
99
	{
100
		return new static($frames ?: $this->frames, $this->basePath, $this->vendorPath);
101
	}
102
 
103
	protected static function resolveBasePath()
104
	{
105
		return substr(__DIR__, 0, strpos(__DIR__, DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR));
106
	}
107
 
108
	protected static function resolveVendorPath()
109
	{
110
		return static::resolveBasePath() . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR;
111
	}
112
 
113
	// Fixes call_user_func stack frames missing file and line
114
	protected static function fixCallUserFuncFrame($frame, array $trace, $index)
115
	{
116
		if (isset($frame['file'])) return $frame;
117
 
118
		$nextFrame = isset($trace[$index + 1]) ? $trace[$index + 1] : null;
119
 
120
		if (! $nextFrame || ! in_array($nextFrame['function'], [ 'call_user_func', 'call_user_func_array' ])) return $frame;
121
 
122
		$frame['file'] = $nextFrame['file'];
123
		$frame['line'] = $nextFrame['line'];
124
 
125
		return $frame;
126
	}
127
}