Completed
Pull Request — master (#546)
by Richard
09:47
created

Kint_Renderer_Rich::renderHeader()   F

Complexity

Conditions 12
Paths 270

Size

Total Lines 46
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 24
nc 270
nop 1
dl 0
loc 46
rs 3.7956
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
class Kint_Renderer_Rich extends Kint_Renderer
4
{
5
    public static $object_renderers = array(
6
        'blacklist' => 'Kint_Renderer_Rich_Blacklist',
7
        'callable' => 'Kint_Renderer_Rich_Callable',
8
        'closure' => 'Kint_Renderer_Rich_Closure',
9
        'color' => 'Kint_Renderer_Rich_Color',
10
        'depth_limit' => 'Kint_Renderer_Rich_DepthLimit',
11
        'nothing' => 'Kint_Renderer_Rich_Nothing',
12
        'recursion' => 'Kint_Renderer_Rich_Recursion',
13
        'simplexml_element' => 'Kint_Renderer_Rich_SimpleXMLElement',
14
        'trace_frame' => 'Kint_Renderer_Rich_TraceFrame',
15
    );
16
    public static $tab_renderers = array(
17
        'binary' => 'Kint_Renderer_Rich_Binary',
18
        'color' => 'Kint_Renderer_Rich_ColorDetails',
19
        'docstring' => 'Kint_Renderer_Rich_Docstring',
20
        'microtime' => 'Kint_Renderer_Rich_Microtime',
21
        'source' => 'Kint_Renderer_Rich_Source',
22
        'table' => 'Kint_Renderer_Rich_Table',
23
        'timestamp' => 'Kint_Renderer_Rich_Timestamp',
24
    );
25
    public static $pre_render_sources = array(
26
        'script' => array(
27
            array('Kint_Renderer_Rich', 'renderJs'),
28
            array('Kint_Renderer_Rich_Microtime', 'renderJs'),
29
        ),
30
        'style' => array(
31
            array('Kint_Renderer_Rich', 'renderCss'),
32
        ),
33
        'raw' => array(),
34
    );
35
36
    /**
37
     * Whether or not to render access paths.
38
     *
39
     * Access paths can become incredibly heavy with very deep and wide
40
     * structures. Given mostly public variables it will typically make
41
     * up one quarter of the output HTML size.
42
     *
43
     * If this is an unacceptably large amount and your browser is groaning
44
     * under the weight of the access paths - your first order of buisiness
45
     * should be to get a new browser. Failing that, use this to turn them off.
46
     *
47
     * @var bool
48
     */
49
    public static $access_paths = true;
50
51
    /**
52
     * The maximum length of a string before it is truncated.
53
     *
54
     * Falsey to disable
55
     *
56
     * @var int
57
     */
58
    public static $strlen_max = 80;
59
60
    /**
61
     * Path to the CSS file to load by default.
62
     *
63
     * @var string
64
     */
65
    public static $theme = 'original.css';
66
67
    /**
68
     * Assume types and sizes don't need to be escaped.
69
     *
70
     * Turn this off if you use anything but ascii in your class names,
71
     * but it'll cause a slowdown of around 10%
72
     *
73
     * @var bool
74
     */
75
    public static $escape_types = false;
76
77
    protected static $been_run = false;
78
79
    protected $plugin_objs = array();
80
    protected $mod_return = false;
81
    protected $callee;
82
    protected $mini_trace;
83
    protected $previous_caller;
84
    protected $file_link_format = false;
85
    protected $show_minitrace = true;
86
    protected $auto_expand = false;
87
88
    public function __construct(array $params = array())
89
    {
90
        parent::__construct($params);
91
92
        $params += array(
93
            'modifiers' => array(),
94
            'minitrace' => array(),
95
            'callee' => null,
96
            'caller' => null,
97
        );
98
99
        $this->callee = $params['callee'];
100
        $this->mini_trace = $params['minitrace'];
101
        $this->previous_caller = $params['caller'];
102
103
        if (isset($params['settings']['return'])) {
104
            $this->mod_return = $params['settings']['return'];
105
        }
106
107
        if (isset($params['settings']['file_link_format'])) {
108
            $this->file_link_format = $params['settings']['file_link_format'];
109
        }
110
111
        if (empty($params['settings']['display_called_from'])) {
112
            $this->show_minitrace = false;
113
        }
114
115
        if (!empty($params['settings']['expanded'])) {
116
            $this->auto_expand = true;
117
        }
118
    }
119
120
    public function render(Kint_Object $o)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
121
    {
122 View Code Duplication
        if ($plugin = $this->getPlugin(self::$object_renderers, $o->hints)) {
123
            if (strlen($output = $plugin->render($o))) {
124
                return $output;
125
            }
126
        }
127
128
        $children = $this->renderChildren($o);
129
        $header = $this->renderHeaderWrapper($o, (bool) strlen($children), $this->renderHeader($o));
130
131
        return '<dl>'.$header.$children.'</dl>';
132
    }
133
134
    public function renderHeaderWrapper(Kint_Object $o, $has_children, $contents)
135
    {
136
        $out = '<dt';
137
138
        if ($has_children) {
139
            $out .= ' class="kint-parent';
140
141
            if ($this->auto_expand) {
142
                $out .= ' kint-show';
143
            }
144
145
            $out .= '"';
146
        }
147
148
        $out .= '>';
149
150 View Code Duplication
        if (self::$access_paths && $o->depth > 0 && $ap = $o->getAccessPath()) {
151
            $out .= '<span class="kint-access-path-trigger" title="Show access path">&rlarr;</span>';
152
        }
153
154
        if ($has_children) {
155
            $out .= '<span class="kint-popup-trigger" title="Open in new window">&rarr;</span><nav></nav>';
156
        }
157
158
        $out .= $contents;
159
160
        if (!empty($ap)) {
161
            $out .= '<div class="access-path">'.$this->escape($ap).'</div>';
162
        }
163
164
        return $out.'</dt>';
165
    }
166
167
    public function renderHeader(Kint_Object $o)
168
    {
169
        $output = '';
170
171
        if (($s = $o->getModifiers()) !== null) {
172
            $output .= '<var>'.$s.'</var> ';
173
        }
174
175
        if (($s = $o->getName()) !== null) {
176
            $output .= '<dfn>'.$this->escape($s).'</dfn> ';
177
178
            if ($s = $o->getOperator()) {
179
                $output .= $this->escape($s, 'ASCII').' ';
180
            }
181
        }
182
183
        if (($s = $o->getType()) !== null) {
184
            if (self::$escape_types) {
185
                $s = $this->escape($s);
186
            }
187
188
            if ($o->reference) {
189
                $s = '&amp;'.$s;
190
            }
191
192
            $output .= '<var>'.$s.'</var> ';
193
        }
194
195
        if (($s = $o->getSize()) !== null) {
196
            if (self::$escape_types) {
197
                $s = $this->escape($s);
198
            }
199
            $output .= '('.$s.') ';
200
        }
201
202
        if (($s = $o->getValueShort()) !== null) {
203
            $s = preg_replace('/\s+/', ' ', $s);
204
205
            if (self::$strlen_max && Kint_Object_Blob::strlen($s) > self::$strlen_max) {
206
                $s = substr($s, 0, self::$strlen_max).'...';
207
            }
208
            $output .= $this->escape($s);
209
        }
210
211
        return trim($output);
212
    }
213
214
    public function renderChildren(Kint_Object $o)
215
    {
216
        $contents = array();
217
        $tabs = array();
218
219
        foreach ($o->getRepresentations() as $rep) {
220
            $result = $this->renderTab($o, $rep);
221
            if (strlen($result)) {
222
                $contents[] = $result;
223
                $tabs[] = $rep;
224
            }
225
        }
226
227
        if (empty($tabs)) {
228
            return '';
229
        }
230
231
        $output = '<dd>';
232
233
        if (count($tabs) === 1 && $tabs[0]->labelIsImplicit()) {
234
            $output .= reset($contents);
235
        } else {
236
            $output .= '<ul class="kint-tabs">';
237
238
            foreach ($tabs as $i => $tab) {
239
                if ($i === 0) {
240
                    $output .= '<li class="kint-active-tab">';
241
                } else {
242
                    $output .= '<li>';
243
                }
244
245
                $output .= $this->escape($tab->getLabel()).'</li>';
246
            }
247
248
            $output .= '</ul><ul>';
249
250
            foreach ($contents as $tab) {
251
                $output .= '<li>'.$tab.'</li>';
252
            }
253
254
            $output .= '</ul>';
255
        }
256
257
        return $output.'</dd>';
258
    }
259
260
    protected function renderTab(Kint_Object $o, Kint_Object_Representation $rep)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
261
    {
262 View Code Duplication
        if ($plugin = $this->getPlugin(self::$tab_renderers, $rep->hints)) {
263
            if (strlen($output = $plugin->render($rep))) {
264
                return $output;
265
            }
266
        }
267
268
        if (is_array($rep->contents)) {
269
            $output = '';
270
            foreach ($rep->contents as $obj) {
271
                $output .= $this->render($obj);
272
            }
273
274
            return $output;
275
        } elseif (is_string($rep->contents)) {
276
            $show_contents = false;
277
278
            // If it is the value representation of a string and its whitespace
279
            // was truncated in the header, always display the full string
280
            if ($o->type !== 'string' || $o->value !== $rep) {
281
                $show_contents = true;
282
            } elseif (preg_match('/(:?[\r\n\t\f\v]| {2})/', $rep->contents)) {
283
                $show_contents = true;
284
            } elseif (self::$strlen_max && Kint_Object_Blob::strlen($rep->contents) > self::$strlen_max) {
285
                $show_contents = true;
286
            }
287
288
            if ($o->type === 'string' && $o->value === $rep && $o->encoding === false) {
0 ignored issues
show
Bug introduced by
The property encoding does not seem to exist in Kint_Object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
289
                $show_contents = false;
290
            }
291
292
            if ($show_contents) {
293
                return '<pre>'.$this->escape($rep->contents)."\n</pre>";
294
            }
295
        } elseif ($rep->contents instanceof Kint_Object) {
296
            return $this->render($rep->contents);
297
        }
298
299
        return;
300
    }
301
302
    protected static function renderJs()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
303
    {
304
        return file_get_contents(KINT_DIR.'/resources/compiled/rich.js');
305
    }
306
307 View Code Duplication
    protected static function renderCss()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
308
    {
309
        if (file_exists(KINT_DIR.'/resources/compiled/'.self::$theme)) {
310
            return file_get_contents(KINT_DIR.'/resources/compiled/'.self::$theme);
311
        } else {
312
            return file_get_contents(self::$theme);
313
        }
314
    }
315
316 View Code Duplication
    public function preRender()
317
    {
318
        $output = '';
319
320
        if (!self::$been_run || $this->mod_return) {
321
            foreach (self::$pre_render_sources as $type => $values) {
322
                $contents = '';
323
                foreach ($values as $v) {
324
                    if (is_callable($v)) {
325
                        $contents .= call_user_func($v, $this);
326
                    } elseif (is_string($v)) {
327
                        $contents .= $v;
328
                    }
329
                }
330
331
                if (!strlen($contents)) {
332
                    continue;
333
                }
334
335
                switch ($type) {
336
                    case 'script':
337
                        $output .= '<script class="kint-script">'.$contents.'</script>';
338
                        break;
339
                    case 'style':
340
                        $output .= '<style class="kint-style">'.$contents.'</style>';
341
                        break;
342
                    default:
343
                        $output .= $contents;
344
                }
345
            }
346
347
            if (!$this->mod_return) {
348
                self::$been_run = true;
349
            }
350
        }
351
352
        return $output.'<div class="kint-rich">';
353
    }
354
355
    public function postRender()
356
    {
357
        if (!$this->show_minitrace) {
358
            return '</div>';
359
        }
360
361
        $output = '<footer>';
362
        $output .= '<span class="kint-popup-trigger" title="Open in new window">&rarr;</span> ';
363
364
        if (isset($this->callee['file'])) {
365
            if (!empty($this->mini_trace)) {
366
                $output .= '<nav></nav>';
367
            }
368
369
            $output .= 'Called from '.$this->ideLink($this->callee['file'], $this->callee['line']);
370
        }
371
372
        $caller = '';
373
374
        if (isset($this->previous_caller['class'])) {
375
            $caller .= $this->previous_caller['class'];
376
        }
377
        if (isset($this->previous_caller['type'])) {
378
            $caller .= $this->previous_caller['type'];
379
        }
380 View Code Duplication
        if (isset($this->previous_caller['function'])
381
            && !in_array($this->previous_caller['function'], array('include', 'include_once', 'require', 'require_once'))
382
        ) {
383
            $caller .= $this->previous_caller['function'].'()';
384
        }
385
386
        if ($caller) {
387
            $output .= ' ['.$caller.']';
388
        }
389
390
        if (!empty($this->mini_trace)) {
391
            $output .= '<ol>';
392
            foreach ($this->mini_trace as $step) {
393
                $output .= '<li>'.$this->ideLink($step['file'], $step['line']); // closing tag not required
394
                if (isset($step['function'])
395
                    && !in_array($step['function'], array('include', 'include_once', 'require', 'require_once'))
396
                ) {
397
                    $output .= ' [';
398
                    if (isset($step['class'])) {
399
                        $output .= $step['class'];
400
                    }
401
                    if (isset($step['type'])) {
402
                        $output .= $step['type'];
403
                    }
404
                    $output .= $step['function'].'()]';
405
                }
406
            }
407
            $output .= '</ol>';
408
        }
409
410
        $output .= '</footer></div>';
411
412
        return $output;
413
    }
414
415 View Code Duplication
    public function escape($string, $encoding = false)
416
    {
417
        if ($encoding === false) {
418
            $encoding = Kint_Object_Blob::detectEncoding($string);
419
        }
420
421
        $original_encoding = $encoding;
422
423
        if ($encoding === false || $encoding === 'ASCII') {
424
            $encoding = 'UTF-8';
425
        }
426
427
        $string = htmlspecialchars($string, ENT_NOQUOTES, $encoding);
428
429
        // this call converts all non-ASCII characters into numeirc htmlentities
430
        if (extension_loaded('mbstring') && $original_encoding !== 'ASCII') {
431
            $string = mb_encode_numericentity($string, array(0x80, 0xffff, 0, 0xffff), $encoding);
432
        }
433
434
        return $string;
435
    }
436
437 View Code Duplication
    protected function getPlugin(array $plugins, array $hints)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
438
    {
439
        if ($plugins = $this->matchPlugins($plugins, $hints)) {
440
            $plugin = end($plugins);
441
442
            if (!isset($this->plugin_objs[$plugin])) {
443
                $this->plugin_objs[$plugin] = new $plugin($this);
444
            }
445
446
            return $this->plugin_objs[$plugin];
447
        }
448
    }
449
450 View Code Duplication
    protected function ideLink($file, $line)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
451
    {
452
        $shortenedPath = $this->escape(Kint::shortenPath($file));
453
        if (!$this->file_link_format) {
454
            return $shortenedPath.':'.$line;
455
        }
456
457
        $ideLink = Kint::getIdeLink($file, $line);
458
        $class = (strpos($ideLink, 'http://') === 0) ? 'class="kint-ide-link" ' : '';
459
460
        return "<a {$class}href=\"{$ideLink}\">{$shortenedPath}:{$line}</a>";
461
    }
462
}
463