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
 * Whoops - php errors for cool kids
4
 * @author Filipe Dobreira <http://github.com/filp>
5
 */
6
 
7
namespace Whoops\Exception;
8
 
9
use InvalidArgumentException;
10
use Serializable;
11
 
12
class Frame implements Serializable
13
{
14
    /**
15
     * @var array
16
     */
17
    protected $frame;
18
 
19
    /**
20
     * @var string
21
     */
22
    protected $fileContentsCache;
23
 
24
    /**
25
     * @var array[]
26
     */
27
    protected $comments = [];
28
 
29
    /**
30
     * @var bool
31
     */
32
    protected $application;
33
 
34
    public function __construct(array $frame)
35
    {
36
        $this->frame = $frame;
37
    }
38
 
39
    /**
40
     * @param  bool        $shortened
41
     * @return string|null
42
     */
43
    public function getFile($shortened = false)
44
    {
45
        if (empty($this->frame['file'])) {
46
            return null;
47
        }
48
 
49
        $file = $this->frame['file'];
50
 
51
        // Check if this frame occurred within an eval().
52
        // @todo: This can be made more reliable by checking if we've entered
53
        // eval() in a previous trace, but will need some more work on the upper
54
        // trace collector(s).
55
        if (preg_match('/^(.*)\((\d+)\) : (?:eval\(\)\'d|assert) code$/', $file, $matches)) {
56
            $file = $this->frame['file'] = $matches[1];
57
            $this->frame['line'] = (int) $matches[2];
58
        }
59
 
60
        if ($shortened && is_string($file)) {
61
            // Replace the part of the path that all frames have in common, and add 'soft hyphens' for smoother line-breaks.
62
            $dirname = dirname(dirname(dirname(dirname(dirname(dirname(__DIR__))))));
63
            if ($dirname !== '/') {
64
                $file = str_replace($dirname, "&hellip;", $file);
65
            }
66
            $file = str_replace("/", "/&shy;", $file);
67
        }
68
 
69
        return $file;
70
    }
71
 
72
    /**
73
     * @return int|null
74
     */
75
    public function getLine()
76
    {
77
        return isset($this->frame['line']) ? $this->frame['line'] : null;
78
    }
79
 
80
    /**
81
     * @return string|null
82
     */
83
    public function getClass()
84
    {
85
        return isset($this->frame['class']) ? $this->frame['class'] : null;
86
    }
87
 
88
    /**
89
     * @return string|null
90
     */
91
    public function getFunction()
92
    {
93
        return isset($this->frame['function']) ? $this->frame['function'] : null;
94
    }
95
 
96
    /**
97
     * @return array
98
     */
99
    public function getArgs()
100
    {
101
        return isset($this->frame['args']) ? (array) $this->frame['args'] : [];
102
    }
103
 
104
    /**
105
     * Returns the full contents of the file for this frame,
106
     * if it's known.
107
     * @return string|null
108
     */
109
    public function getFileContents()
110
    {
111
        if ($this->fileContentsCache === null && $filePath = $this->getFile()) {
112
            // Leave the stage early when 'Unknown' or '[internal]' is passed
113
            // this would otherwise raise an exception when
114
            // open_basedir is enabled.
115
            if ($filePath === "Unknown" || $filePath === '[internal]') {
116
                return null;
117
            }
118
 
119
            try {
120
                $this->fileContentsCache = file_get_contents($filePath);
121
            } catch (ErrorException $exception) {
122
                // Internal file paths of PHP extensions cannot be opened
123
            }
124
        }
125
 
126
        return $this->fileContentsCache;
127
    }
128
 
129
    /**
130
     * Adds a comment to this frame, that can be received and
131
     * used by other handlers. For example, the PrettyPage handler
132
     * can attach these comments under the code for each frame.
133
     *
134
     * An interesting use for this would be, for example, code analysis
135
     * & annotations.
136
     *
137
     * @param string $comment
138
     * @param string $context Optional string identifying the origin of the comment
139
     */
140
    public function addComment($comment, $context = 'global')
141
    {
142
        $this->comments[] = [
143
            'comment' => $comment,
144
            'context' => $context,
145
        ];
146
    }
147
 
148
    /**
149
     * Returns all comments for this frame. Optionally allows
150
     * a filter to only retrieve comments from a specific
151
     * context.
152
     *
153
     * @param  string  $filter
154
     * @return array[]
155
     */
156
    public function getComments($filter = null)
157
    {
158
        $comments = $this->comments;
159
 
160
        if ($filter !== null) {
161
            $comments = array_filter($comments, function ($c) use ($filter) {
162
                return $c['context'] == $filter;
163
            });
164
        }
165
 
166
        return $comments;
167
    }
168
 
169
    /**
170
     * Returns the array containing the raw frame data from which
171
     * this Frame object was built
172
     *
173
     * @return array
174
     */
175
    public function getRawFrame()
176
    {
177
        return $this->frame;
178
    }
179
 
180
    /**
181
     * Returns the contents of the file for this frame as an
182
     * array of lines, and optionally as a clamped range of lines.
183
     *
184
     * NOTE: lines are 0-indexed
185
     *
186
     * @example
187
     *     Get all lines for this file
188
     *     $frame->getFileLines(); // => array( 0 => '<?php', 1 => '...', ...)
189
     * @example
190
     *     Get one line for this file, starting at line 10 (zero-indexed, remember!)
191
     *     $frame->getFileLines(9, 1); // array( 9 => '...' )
192
     *
193
     * @throws InvalidArgumentException if $length is less than or equal to 0
194
     * @param  int                      $start
195
     * @param  int                      $length
196
     * @return string[]|null
197
     */
198
    public function getFileLines($start = 0, $length = null)
199
    {
200
        if (null !== ($contents = $this->getFileContents())) {
201
            $lines = explode("\n", $contents);
202
 
203
            // Get a subset of lines from $start to $end
204
            if ($length !== null) {
205
                $start  = (int) $start;
206
                $length = (int) $length;
207
                if ($start < 0) {
208
                    $start = 0;
209
                }
210
 
211
                if ($length <= 0) {
212
                    throw new InvalidArgumentException(
213
                        "\$length($length) cannot be lower or equal to 0"
214
                    );
215
                }
216
 
217
                $lines = array_slice($lines, $start, $length, true);
218
            }
219
 
220
            return $lines;
221
        }
222
    }
223
 
224
    /**
225
     * Implements the Serializable interface, with special
226
     * steps to also save the existing comments.
227
     *
228
     * @see Serializable::serialize
229
     * @return string
230
     */
231
    public function serialize()
232
    {
233
        $frame = $this->frame;
234
        if (!empty($this->comments)) {
235
            $frame['_comments'] = $this->comments;
236
        }
237
 
238
        return serialize($frame);
239
    }
240
 
241
    public function __serialize()
242
    {
243
        $frame = $this->frame;
244
        if (!empty($this->comments)) {
245
            $frame['_comments'] = $this->comments;
246
        }
247
        return $frame;
248
    }
249
 
250
    /**
251
     * Unserializes the frame data, while also preserving
252
     * any existing comment data.
253
     *
254
     * @see Serializable::unserialize
255
     * @param string $serializedFrame
256
     */
257
    public function unserialize($serializedFrame)
258
    {
259
        $frame = unserialize($serializedFrame);
260
 
261
        if (!empty($frame['_comments'])) {
262
            $this->comments = $frame['_comments'];
263
            unset($frame['_comments']);
264
        }
265
 
266
        $this->frame = $frame;
267
    }
268
 
269
    public function __unserialize($frame)
270
    {
271
        if (!empty($frame['_comments'])) {
272
            $this->comments = $frame['_comments'];
273
            unset($frame['_comments']);
274
        }
275
 
276
        $this->frame = $frame;
277
    }
278
 
279
    /**
280
     * Compares Frame against one another
281
     * @param  Frame $frame
282
     * @return bool
283
     */
284
    public function equals(Frame $frame)
285
    {
286
        if (!$this->getFile() || $this->getFile() === 'Unknown' || !$this->getLine()) {
287
            return false;
288
        }
289
        return $frame->getFile() === $this->getFile() && $frame->getLine() === $this->getLine();
290
    }
291
 
292
    /**
293
     * Returns whether this frame belongs to the application or not.
294
     *
295
     * @return boolean
296
     */
297
    public function isApplication()
298
    {
299
        return $this->application;
300
    }
301
 
302
    /**
303
     * Mark as an frame belonging to the application.
304
     *
305
     * @param boolean $application
306
     */
307
    public function setApplication($application)
308
    {
309
        $this->application = $application;
310
    }
311
}