Completed
Push — master ( 674a62...c1df99 )
by recca
20:51 queued 07:10
created

DebuggerManager::render()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3.0327

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 3
dl 0
loc 21
ccs 11
cts 13
cp 0.8462
crap 3.0327
rs 9.584
c 0
b 0
f 0
1
<?php
2
3
namespace Recca0120\LaravelTracy;
4
5
use Exception;
6
use Tracy\Bar;
7
use Tracy\Helpers;
8
use ErrorException;
9
use Tracy\Debugger;
10
use Tracy\BlueScreen;
11
use Illuminate\Support\Arr;
12
use Illuminate\Contracts\Routing\UrlGenerator;
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 3
            'showBar' => false,
78 3
            'editor' => Debugger::$editor,
79 3
            'maxDepth' => Debugger::$maxDepth,
80 3
            'maxLength' => Debugger::$maxLength,
81 3
            'scream' => true,
82 3
            'showLocation' => true,
83 3
            'strictMode' => true,
84 3
            'currentTime' => $_SERVER['REQUEST_TIME_FLOAT'] ?: microtime(true),
85 3
            'editorMapping' => isset(Debugger::$editorMapping) === true ? Debugger::$editorMapping : [],
86 3
        ], $config);
87
88 3
        Debugger::$editor = $config['editor'];
89 3
        Debugger::$maxDepth = $config['maxDepth'];
90 3
        Debugger::$maxLength = $config['maxLength'];
91 3
        Debugger::$scream = $config['scream'];
92 3
        Debugger::$showLocation = $config['showLocation'];
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 3
        }
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
        switch ($type) {
155 3
            case 'css':
156 3
            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 2
                ];
161
                $content = $this->renderBuffer(function () {
162 2
                    return $this->bar->dispatchAssets();
163 2
                });
164 2
                break;
165 1
            default:
166
                $headers = [
167 1
                    'Content-Type' => 'text/javascript; charset=utf-8',
168 1
                ];
169 1
                $content = $this->dispatch();
170 1
                break;
171 1
        }
172
173
        return [
174 3
            array_merge($headers, [
175 3
                'Content-Length' => strlen($content),
176 3
            ]),
177 3
            $content,
178 3
        ];
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 1
        }
191
192
        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 (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 1
                )
213 1
            );
214
        }
215
216
        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(Exception $exception)
228
    {
229
        return $this->renderBuffer(function () use ($exception) {
230 2
            Helpers::improveException($exception);
0 ignored issues
show
Documentation introduced by
$exception is of type object<Exception>, 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...
231 2
            $this->blueScreen->render($exception);
0 ignored issues
show
Documentation introduced by
$exception is of type object<Exception>, 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...
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 4
        );
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
    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
        static $path;
319
320 9
        if (is_null($path) === true) {
321 9
            $path = is_null($this->urlGenerator) === false
322 9
                ? $this->urlGenerator->route(Arr::get($this->config, 'route.as').'bar')
323 9
                : null;
324 9
        }
325
326 9
        return is_null($path) === false
327 9
            ? str_replace('?_tracy_bar', $path.'?_tracy_bar', $content)
328 9
            : $content;
329
    }
330
}
331