Completed
Push — master ( 9792a6...aaaf86 )
by recca
10:22
created

DebuggerManager::exceptionHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
ccs 5
cts 5
cp 1
crap 1
1
<?php
2
3
namespace Recca0120\LaravelTracy;
4
5
use ErrorException;
6
use Illuminate\Contracts\Routing\UrlGenerator;
7
use Illuminate\Support\Arr;
8
use Throwable;
9
use Tracy\Bar;
10
use Tracy\BlueScreen;
11
use Tracy\Debugger;
12
use Tracy\Helpers;
13
14
class DebuggerManager
15
{
16
    /**
17
     * $config.
18
     *
19
     * @var array
20
     */
21
    protected $config;
22
23
    /**
24
     * $bar.
25
     *
26
     * @var \Tracy\Bar
27
     */
28
    protected $bar;
29
30
    /**
31
     * $blueScreen.
32
     *
33
     * @var \Tracy\BlueScreen
34
     */
35
    protected $blueScreen;
36
37
    /**
38
     * $session.
39
     *
40
     * @var \Recca0120\LaravelTracy\Session
41
     */
42
    protected $session;
43
44
    /**
45
     * $urlGenerator.
46
     *
47
     * @var \Illuminate\Contracts\Routing\UrlGenerator
48
     */
49
    protected $urlGenerator;
50
51
    /**
52
     * __construct.
53
     *
54
     * @param array $config
55
     * @param \Tracy\Bar $bar
56
     * @param \Tracy\BlueScreen $blueScreen
57
     */
58 13
    public function __construct($config = [], Bar $bar = null, BlueScreen $blueScreen = null, Session $session = null)
59
    {
60 13
        $this->config = $config;
61 13
        $this->bar = $bar ?: Debugger::getBar();
62 13
        $this->blueScreen = $blueScreen ?: Debugger::getBlueScreen();
63 13
        $this->session = $session ?: new Session;
64 13
    }
65
66
    /**
67
     * init.
68
     *
69
     * @param array $config
70
     * @return array
71
     */
72 3
    public static function init($config = [])
73
    {
74 3
        $config = array_merge([
75 3
            'accepts' => [],
76 3
            'appendTo' => 'body',
77
            'showBar' => false,
78 3
            'editor' => Debugger::$editor,
79 3
            'maxDepth' => Debugger::$maxDepth,
0 ignored issues
show
Deprecated Code introduced by
The property Tracy\Debugger::$maxDepth has been deprecated with message: use Tracy\Dumper::$maxDepth

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
80 3
            'maxLength' => Debugger::$maxLength,
0 ignored issues
show
Deprecated Code introduced by
The property Tracy\Debugger::$maxLength has been deprecated with message: use Tracy\Dumper::$maxLength

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
81
            'scream' => true,
82
            'showLocation' => true,
83
            'strictMode' => true,
84 3
            'currentTime' => $_SERVER['REQUEST_TIME_FLOAT'] ?: microtime(true),
85 3
            'editorMapping' => isset(Debugger::$editorMapping) === true ? Debugger::$editorMapping : [],
86
        ], $config);
87
88 3
        Debugger::$editor = $config['editor'];
89 3
        Debugger::$maxDepth = $config['maxDepth'];
0 ignored issues
show
Deprecated Code introduced by
The property Tracy\Debugger::$maxDepth has been deprecated with message: use Tracy\Dumper::$maxDepth

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
90 3
        Debugger::$maxLength = $config['maxLength'];
0 ignored issues
show
Deprecated Code introduced by
The property Tracy\Debugger::$maxLength has been deprecated with message: use Tracy\Dumper::$maxLength

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
91 3
        Debugger::$scream = $config['scream'];
92 3
        Debugger::$showLocation = $config['showLocation'];
0 ignored issues
show
Deprecated Code introduced by
The property Tracy\Debugger::$showLocation has been deprecated with message: use Tracy\Dumper::$showLocation

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
93 3
        Debugger::$strictMode = $config['strictMode'];
94 3
        Debugger::$time = $config['currentTime'];
95
96 3
        if (isset(Debugger::$editorMapping) === true) {
97 3
            Debugger::$editorMapping = $config['editorMapping'];
98
        }
99
100 3
        return $config;
101
    }
102
103
    /**
104
     * enabled.
105
     *
106
     * @return bool
107
     */
108 1
    public function enabled()
109
    {
110 1
        return Arr::get($this->config, 'enabled', true) === true;
111
    }
112
113
    /**
114
     * showBar.
115
     *
116
     * @return bool
117
     */
118 1
    public function showBar()
119
    {
120 1
        return Arr::get($this->config, 'showBar', true) === true;
121
    }
122
123
    /**
124
     * accepts.
125
     *
126
     * @return array
127
     */
128 1
    public function accepts()
129
    {
130 1
        return Arr::get($this->config, 'accepts', []);
131
    }
132
133
    /**
134
     * setUrlGenerator.
135
     *
136
     * @param \Illuminate\Contracts\Routing\UrlGenerator $urlGenerator
137
     * @return $this
138
     */
139 2
    public function setUrlGenerator(UrlGenerator $urlGenerator)
140
    {
141 2
        $this->urlGenerator = $urlGenerator;
142
143 2
        return $this;
144
    }
145
146
    /**
147
     * dispatchAssets.
148
     *
149
     * @param string $type
150
     * @return array
151
     */
152 3
    public function dispatchAssets($type)
153
    {
154 3
        switch ($type) {
155 3
            case 'css':
156 2
            case 'js':
157
                $headers = [
158 2
                    'Content-Type' => $type === 'css' ? 'text/css; charset=utf-8' : 'text/javascript; charset=utf-8',
159 2
                    'Cache-Control' => 'max-age=86400',
160
                ];
161 2
                $content = $this->renderBuffer(function () {
162 2
                    return $this->bar->dispatchAssets();
163 2
                });
164 2
                break;
165
            default:
166
                $headers = [
167 1
                    'Content-Type' => 'text/javascript; charset=utf-8',
168
                ];
169 1
                $content = $this->dispatch();
170 1
                break;
171
        }
172
173
        return [
174 3
            array_merge($headers, [
175 3
                'Content-Length' => strlen($content),
176
            ]),
177 3
            $content,
178
        ];
179
    }
180
181
    /**
182
     * dispatch.
183
     *
184
     * @return string
185
     */
186 1
    public function dispatch()
187
    {
188 1
        if ($this->session->isStarted() === false) {
189 1
            $this->session->start();
190
        }
191
192 1
        return $this->renderBuffer(function () {
193 1
            return $this->bar->dispatchAssets();
194 1
        });
195
    }
196
197
    /**
198
     * shutdownHandler.
199
     *
200
     * @param string $content
201
     * @param bool $ajax
202
     * @param int $error
203
     * @return string
204
     */
205 5
    public function shutdownHandler($content, $ajax = false, $error = null)
206
    {
207 5
        $error = $error ?: error_get_last();
208 5
        if (is_array($error) && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE, E_RECOVERABLE_ERROR, E_USER_ERROR], true)) {
209 1
            return $this->exceptionHandler(
210 1
                Helpers::fixStack(
211 1
                    new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line'])
0 ignored issues
show
Documentation introduced by
new \ErrorException($err...file'], $error['line']) is of type object<ErrorException>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
212
                )
213
            );
214
        }
215
216 4
        return array_reduce(['renderLoader', 'renderBar'], function ($content, $method) use ($ajax) {
217 4
            return call_user_func([$this, $method], $content, $ajax);
218 4
        }, $content);
219
    }
220
221
    /**
222
     * exceptionHandler.
223
     *
224
     * @param \Exception $exception
225
     * @return string
226
     */
227 2
    public function exceptionHandler(Throwable $exception)
228
    {
229 2
        return $this->renderBuffer(function () use ($exception) {
230 2
            Helpers::improveException($exception);
231 2
            $this->blueScreen->render($exception);
232 2
        });
233
    }
234
235
    /**
236
     * renderLoader.
237
     *
238
     * @param string $content
239
     * @param bool $ajax
240
     * @return string
241
     */
242 4
    protected function renderLoader($content, $ajax = false)
243
    {
244 4
        if ($ajax === true || $this->session->isStarted() === false) {
245 1
            return $content;
246
        }
247
248 3
        return $this->render($content, 'renderLoader', ['head', 'body']);
249
    }
250
251
    /**
252
     * renderBar.
253
     *
254
     * @param string $content
255
     * @return string
256
     */
257 4
    protected function renderBar($content)
258
    {
259 4
        return $this->render(
260 4
            $content,
261 4
            'render',
262 4
            [Arr::get($this->config, 'appendTo', 'body'), 'body']
263
        );
264
    }
265
266
    /**
267
     * render.
268
     *
269
     * @param string $content
270
     * @param string $method
271
     * @param array $appendTo
0 ignored issues
show
Bug introduced by
There is no parameter named $appendTo. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
272
     * @return string
273
     */
274 4
    protected function render($content, $method, $appendTags = ['body'])
275
    {
276 4
        $appendHtml = $this->renderBuffer(function () use ($method) {
277 4
            $requestUri = Arr::get($_SERVER, 'REQUEST_URI');
278 4
            Arr::set($_SERVER, 'REQUEST_URI', '');
279 4
            call_user_func([$this->bar, $method]);
280 4
            Arr::set($_SERVER, 'REQUEST_URI', $requestUri);
281 4
        });
282
283 4
        $appendTags = array_unique($appendTags);
284
285 4
        foreach ($appendTags as $appendTag) {
286 4
            $pos = strripos($content, '</'.$appendTag.'>');
287
288 4
            if ($pos !== false) {
289 4
                return substr_replace($content, $appendHtml, $pos, 0);
290
            }
291
        }
292
293
        return $content.$appendHtml;
294
    }
295
296
    /**
297
     * renderBuffer.
298
     *
299
     * @param callable $callback
300
     * @return string
301
     */
302 9
    protected function renderBuffer(callable $callback)
303
    {
304 9
        ob_start();
305 9
        $callback();
306
307 9
        return $this->replacePath(ob_get_clean());
308
    }
309
310
    /**
311
     * replacePath.
312
     *
313
     * @param string $content
314
     * @return string
315
     */
316 9
    protected function replacePath($content)
317
    {
318 9
        $path = is_null($this->urlGenerator) === false
319 1
            ? $this->urlGenerator->route(Arr::get($this->config, 'route.as').'bar')
320 9
            : null;
321
322 9
        return is_null($path) === false
323 1
            ? str_replace('?_tracy_bar', $path.'?_tracy_bar', $content)
324 9
            : $content;
325
    }
326
}
327