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) |
|
|
|
|
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">⇄</span>'; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
if ($has_children) { |
|
|
|
|
155
|
|
|
$out .= '<span class="kint-popup-trigger" title="Open in new window">→</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 = '&'.$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) |
|
|
|
|
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) { |
|
|
|
|
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() |
303
|
|
|
{ |
304
|
|
|
return file_get_contents(KINT_DIR.'/resources/compiled/rich.js'); |
305
|
|
|
} |
306
|
|
|
|
307
|
|
View Code Duplication |
protected static function renderCss() |
|
|
|
|
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">→</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) |
|
|
|
|
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) |
|
|
|
|
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
|
|
|
|
This check examines a number of code elements and verifies that they conform to the given naming conventions.
You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.