Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/**
4
 * Hoa
5
 *
6
 *
7
 * @license
8
 *
9
 * New BSD License
10
 *
11
 * Copyright © 2007-2017, Hoa community. All rights reserved.
12
 *
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 *     * Redistributions of source code must retain the above copyright
16
 *       notice, this list of conditions and the following disclaimer.
17
 *     * Redistributions in binary form must reproduce the above copyright
18
 *       notice, this list of conditions and the following disclaimer in the
19
 *       documentation and/or other materials provided with the distribution.
20
 *     * Neither the name of the Hoa nor the names of its contributors may be
21
 *       used to endorse or promote products derived from this software without
22
 *       specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 */
36
 
37
namespace Psy\Readline\Hoa;
38
 
39
/**
40
 * `Hoa\Exception\Idle` is the mother exception class of libraries. The only
41
 * difference between `Hoa\Exception\Idle` and its direct children
42
 * `Hoa\Exception` is that the latter fires events after beeing constructed.
43
 */
44
class ExceptionIdle extends \Exception
45
{
46
    /**
47
     * Delay processing on arguments.
48
     */
49
    protected $_tmpArguments = null;
50
 
51
    /**
52
     * List of arguments to format message.
53
     */
54
    protected $_arguments = null;
55
 
56
    /**
57
     * Backtrace.
58
     */
59
    protected $_trace = null;
60
 
61
    /**
62
     * Previous exception if any.
63
     */
64
    protected $_previous = null;
65
 
66
    /**
67
     * Original exception message.
68
     */
69
    protected $_rawMessage = null;
70
 
71
    /**
72
     * Allocates a new exception.
73
     *
74
     * An exception is built with a formatted message, a code (an ID) and an
75
     * array that contains the list of formatted strings for the message. If
76
     * chaining, we can add a previous exception.
77
     */
78
    public function __construct(
79
        string $message,
80
        int $code = 0,
81
        $arguments = [],
82
        \Exception $previous = null
83
    ) {
84
        $this->_tmpArguments = $arguments;
85
        parent::__construct($message, $code, $previous);
86
        $this->_rawMessage = $message;
87
        $this->message = @\vsprintf($message, $this->getArguments());
88
 
89
        return;
90
    }
91
 
92
    /**
93
     * Returns the backtrace.
94
     *
95
     * Do not use `Exception::getTrace` any more.
96
     */
97
    public function getBacktrace()
98
    {
99
        if (null === $this->_trace) {
100
            $this->_trace = $this->getTrace();
101
        }
102
 
103
        return $this->_trace;
104
    }
105
 
106
    /**
107
     * Returns the previous exception if any.
108
     *
109
     * Do not use `Exception::getPrevious` any more.
110
     */
111
    public function getPreviousThrow()
112
    {
113
        if (null === $this->_previous) {
114
            $this->_previous = $this->getPrevious();
115
        }
116
 
117
        return $this->_previous;
118
    }
119
 
120
    /**
121
     * Returns the arguments of the message.
122
     */
123
    public function getArguments()
124
    {
125
        if (null === $this->_arguments) {
126
            $arguments = $this->_tmpArguments;
127
 
128
            if (!\is_array($arguments)) {
129
                $arguments = [$arguments];
130
            }
131
 
132
            foreach ($arguments as &$value) {
133
                if (null === $value) {
134
                    $value = '(null)';
135
                }
136
            }
137
 
138
            $this->_arguments = $arguments;
139
            unset($this->_tmpArguments);
140
        }
141
 
142
        return $this->_arguments;
143
    }
144
 
145
    /**
146
     * Returns the raw message.
147
     */
148
    public function getRawMessage(): string
149
    {
150
        return $this->_rawMessage;
151
    }
152
 
153
    /**
154
     * Returns the message already formatted.
155
     */
156
    public function getFormattedMessage(): string
157
    {
158
        return $this->getMessage();
159
    }
160
 
161
    /**
162
     * Returns the source of the exception (class, method, function, main etc.).
163
     */
164
    public function getFrom(): string
165
    {
166
        $trace = $this->getBacktrace();
167
        $from = '{main}';
168
 
169
        if (!empty($trace)) {
170
            $t = $trace[0];
171
            $from = '';
172
 
173
            if (isset($t['class'])) {
174
                $from .= $t['class'].'::';
175
            }
176
 
177
            if (isset($t['function'])) {
178
                $from .= $t['function'].'()';
179
            }
180
        }
181
 
182
        return $from;
183
    }
184
 
185
    /**
186
     * Raises an exception as a string.
187
     */
188
    public function raise(bool $includePrevious = false): string
189
    {
190
        $message = $this->getFormattedMessage();
191
        $trace = $this->getBacktrace();
192
        $file = '/dev/null';
193
        $line = -1;
194
        $pre = $this->getFrom();
195
 
196
        if (!empty($trace)) {
197
            $file = $trace['file'] ?? null;
198
            $line = $trace['line'] ?? null;
199
        }
200
 
201
        $pre .= ': ';
202
 
203
        try {
204
            $out =
205
                $pre.'('.$this->getCode().') '.$message."\n".
206
                'in '.$this->getFile().' at line '.
207
                $this->getLine().'.';
208
        } catch (\Exception $e) {
209
            $out =
210
                $pre.'('.$this->getCode().') '.$message."\n".
211
                'in '.$file.' around line '.$line.'.';
212
        }
213
 
214
        if (true === $includePrevious &&
215
            null !== $previous = $this->getPreviousThrow()) {
216
            $out .=
217
                "\n\n".'    ⬇'."\n\n".
218
                'Nested exception ('.\get_class($previous).'):'."\n".
219
                ($previous instanceof self
220
                    ? $previous->raise(true)
221
                    : $previous->getMessage());
222
        }
223
 
224
        return $out;
225
    }
226
 
227
    /**
228
     * Catches uncaught exception (only `Hoa\Exception\Idle` and children).
229
     */
230
    public static function uncaught(\Throwable $exception)
231
    {
232
        if (!($exception instanceof self)) {
233
            throw $exception;
234
        }
235
 
236
        while (0 < \ob_get_level()) {
237
            \ob_end_flush();
238
        }
239
 
240
        echo 'Uncaught exception ('.\get_class($exception).'):'."\n".
241
            $exception->raise(true);
242
    }
243
 
244
    /**
245
     * String representation of object.
246
     */
247
    public function __toString(): string
248
    {
249
        return $this->raise();
250
    }
251
 
252
    /**
253
     * Enables uncaught exception handler.
254
     *
255
     * This is restricted to Hoa's exceptions only.
256
     */
257
    public static function enableUncaughtHandler(bool $enable = true)
258
    {
259
        if (false === $enable) {
260
            return \restore_exception_handler();
261
        }
262
 
263
        return \set_exception_handler(function ($exception) {
264
            return self::uncaught($exception);
265
        });
266
    }
267
}