7 public $styleFile = __DIR__ .
'/dump.css';
8 public $styleNamespace =
'dump';
9 public $scriptFile = __DIR__ .
'/dump.js';
10 public $scriptNamespace =
'dump';
11 public $extraBefore = 10;
12 public $extraAfter = 5;
13 public $sourceFormat = [
15 '/\\$\\w+/' =>
'<i>$0</i>',
16 '/(?<!\\$)(?<!::)(?<!->)\\b(' .
17 'abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else(if)?|empty|end(declare|for|foreach|' .
18 'if|switch|while)|eval|exit|extends|final|finally|for(each)?|function|global|goto|if|implements|include(_once)?|in(stance|stead)of|interface|isset|list|' .
19 'namespace|new|or|print|private|protected|public|require(_once)?|return|' .
20 'static|switch|throw|trait|try|unset|use|var|while|xor|yield|' .
22 ')\\b/' =>
'<u>$0</u>',
23 '/(<\\?php|\\?\\>)/' =>
'<u><b>$0</b></u>',
24 '/(?<!\\w)\\d+(\\.\\d+)?/' =>
'<b>$0</b>',
25 '/(\'|").*?(?<!\\\\)\\1/' =>
'<p>$0</p>',
26 '/(^\\s*(\\/\\/|\\/\\*|\\*).*|\\/\\/[^\'"]*)$/' =>
'<em>$0</em>' 30 'add( constraint)?|alter( column| table)?|all|and|any|as|asc|backup database|between|case|check|column|constraint|create (database|index|view|table|procedure|(unique )?index|view)|database|default|delete|desc|distinct|drop (column|constraint|database|default|index|table|view)|' .
31 'exec|exists|(foreign |primary )?key|from|((full|left|right) )?(outer )?join|group by|having|in|index|inner join|insert into|is (not )?null|like|limit|not|or|order by|' .
32 'procedure|rownum|select( (distinct|into|top))?|set|(truncate )?table|top|union( all)?|unique|update|values|view|where' .
33 ')\\b/i' =>
'<u>$0</u>',
34 '/(?<!\\w)\\d+(\\.\\d+)?/' =>
'<b>$0</b>',
35 '/(\'|").*?(?<!\\\\)\\1/' =>
'<p>$0</p>',
38 public $memoryLimit = null;
39 public $maxDepth = 16;
40 public $maxLength = 128;
41 public $timeWindow = 315360000;
42 public $timeFormat =
'Y-m-d H:i:s';
43 public $validFilename =
'/^([A-Z]:[\\/\\\\]|\\/|\\\\\\\\)[^\\*\\?\\:\\|\\<\\>\\&\\r\\n]*\\.\\w+$/';
44 public $groupProperties =
true;
45 public $sortProperties =
true;
46 public $remoteDocs =
'https://php.net/manual/en/';
47 public $localDocs = null;
48 public $paramConstsFile = __DIR__ .
'/../../data/consts.php';
50 protected $_index = 0;
51 protected $_propertyDocs = [];
52 protected $_paramConsts = null;
55 $this->configure($config);
64 "<style>\n" . file_get_contents($this->styleFile) .
"\n</style>\n" .
65 "<script>\n" . file_get_contents($this->scriptFile) .
"\n</script>\n";
76 public function source($filename,$line_no = null,$line_to = null,$type = null,$header = null){
77 if(is_array($filename)){
78 $lines = array_values($filename);
81 elseif(!is_readable($filename))
return false;
82 else $lines = file($filename);
84 $max = $count = count($lines);
90 $focus = $line_no - 1;
91 $min = $focus - $this->extraBefore;
92 $max = $focus + $this->extraAfter;
94 $max = min($count - 1,$max);
96 for($i = max(0,$min); $i <= $max; $i++){
97 $line = htmlspecialchars(rtrim($lines[$i]),ENT_NOQUOTES);
98 foreach(($this->sourceFormat[$type ?: File::ext($filename)] ?? []) as $search => $replace) $line = preg_replace($search,$replace,$line);
99 $table .=
"\t\t<tr" . ($i == $focus ?
" class='{$this->styleNamespace}-active'" :
'') .
"><th>" . ($i + 1) .
"</th><td>$line</td></tr>\n";
102 "<table class='{$this->styleNamespace}-source'>\n" . ($filename || $header ?
103 "\t<thead><tr>" . ($header ?
"<th colspan='2'>$header</th>" :
"<th><input class='{$this->styleNamespace}-copy' value='" . htmlspecialchars($filename,ENT_QUOTES) .
"' onclick='{$this->scriptNamespace}.copy(this)'></th><th>" . htmlspecialchars($filename) .
"<span>" . date($this->timeFormat,filemtime($filename)) .
", $count lines</span></th>") .
"</tr></thead>\n" :
'' ) .
104 "\t<tbody>\n$table\t</tbody>\n" .
109 return ($value > time() - $this->timeWindow) && ($value < time() + $this->timeWindow) ? htmlspecialchars(date($this->timeFormat,$value)) : null;
113 $doc = htmlspecialchars($doc);
114 $doc = preg_replace(
'/\\n\\s*\\* /',
"\n",$doc);
115 $doc = preg_replace(
'/\\n\\s*\\*\\s*\\n/',
"\n\n",$doc);
116 $doc = preg_replace(
'/(^\\s*\\/\\*\\*\\s*|\\s*\\*\\/\\s*$)/',
'',$doc);
117 $doc = preg_replace(
'/\\n@(.*? |param \\S+ \\$\\w+( )?|return \\S+( )?)/',
"\n<code>@\$1</code>",$doc);
118 $doc = str_replace(
"\n ",
' ',$doc);
123 if(!$filename)
return false;
124 if(!array_key_exists($key = $filename .
'#' . $property,$this->_propertyDocs)){
126 if(!array_key_exists($filename,$this->_propertyDocs)){
127 $this->_propertyDocs[$filename] = [];
128 if(is_readable($filename))
foreach(token_get_all(file_get_contents($filename)) as $token)
if(is_array($token))
switch($token[0]){
129 case T_FUNCTION:
break 2;
130 case T_WHITESPACE:
break;
131 default: $this->_propertyDocs[$filename][] = $token;
133 $this->_propertyDocs[$filename][] = [null];
134 $this->_propertyDocs[$filename][] = [null];
136 foreach(($tokens = $this->_propertyDocs[$filename]) as $index => $token)
if(($token[0] == T_VARIABLE) && ($token[1] ==
'$' . $property)){
137 if((($tokens[++$index][0] == T_COMMENT) || ($tokens[++$index][0] == T_COMMENT)) && (substr($tokens[$index][1],0,4) ==
' 138 $docs = trim(substr($tokens[$index][1],4));
139 while(($tokens[++$index][0] == T_COMMENT) && (substr($tokens[$index][1],0,2) == '
143 $this->_propertyDocs[$key] = $docs;
145 return $this->_propertyDocs[$key];
150 if($reflect->isPrivate()) $visibility[] =
'private';
151 if($reflect->isProtected()) $visibility[] =
'protected';
152 if($reflect->isPublic()) $visibility[] =
'public';
153 if($reflect->isStatic()) $visibility[] =
'static';
159 "<div class='{$this->styleNamespace}-const'><table class='{$this->styleNamespace}-var'>\n" .
161 "<th onclick='{$this->scriptNamespace}.sort({$this->_index}," . json_encode(array_keys(Record::sort($names = array_keys($constants)))) .
")'>Name</th>" .
162 "<th onclick='{$this->scriptNamespace}.sort({$this->_index}," . json_encode(array_values($names = array_flip($names))) .
")'>Type</th>" .
163 "<th onclick='{$this->scriptNamespace}.sort({$this->_index}," . json_encode(array_values(array_merge(Record::sort($constants),$names))) .
")'>Value</th>" .
164 "</tr></thead>\n\t<tbody id='dump-sort-{$this->_index}'>\n";
165 foreach($constants as $name => $value){
166 $i = strpos($row = $this->varRow($name,null,$value),
'<tr');
167 $table .= substr($row,0,$i) .
"<tr id='dump-sort-{$this->_index}-{$names[$name]}'" . substr($row,$i + 3);
169 return $table .
"\t</tbody>\n</table></div>\n";
173 $size = count($value);
175 if($depth > $this->maxDepth) $sub =
"<div class='{$this->styleNamespace}-depth'>depth too great</div>";
179 foreach($value as $key => $record){
180 if(!is_array($record) || (($keys !== null) && (array_keys($record) !== $keys))){
184 else $keys = array_keys($record);
187 foreach($record as $k => $v){
188 $type = strtolower(gettype($v));
191 (strpos($v,
"\n") !==
false) ||
192 (mb_strlen($str .= $v) > $this->maxLength) ||
193 (array_key_exists($k,$types) && ($type != ($types[$k])))
198 else $types[$k] = $type;
203 $sub .=
"\t<thead>\n\t\t<tr><th class='empty' rowspan='2'></th>";
204 foreach($keys as $key) $sub .=
"<th>" . htmlspecialchars($key) .
"</th>";
205 $sub .=
"</tr>\n\t\t<tr>";
206 foreach($keys as $key) $sub .=
"<td class='{$this->styleNamespace}-type'>{$types[$key]}</td>";
207 $sub .=
"</tr>\n\t</thead>\n\t<tbody>\n";
208 foreach($value as $key => $record){
209 $sub .=
"\t\t<tr><th>" . htmlspecialchars($key) .
"</th>";
210 foreach($record as $v) $sub .=
"<td class='{$this->styleNamespace}-value'>" . $this->varValue($v) .
"</td>";
213 $sub .=
"\t</tbody>\n";
217 if((count($keys = array_keys($value)) > 1) && ($keys == array_keys($keys)) && (strlen(implode($keys)) < $this->maxLength))
foreach($value as $k => $v){
218 if(!is_scalar($v) || (($type !== null) && (gettype($v) != $type))){
222 else $type = gettype($v);
224 if(($type = strtolower($type)) && (mb_strlen($str = implode($value)) < $this->maxLength) && (strpos($str,
"\n") ===
false)){
225 $sub .=
"\t<tr><thead><th class='empty'>";
226 foreach($value as $k => $v) $sub .=
"<th>" . htmlspecialchars($k) .
"</th>";
227 $sub .=
"</thad></tr>\n\t<tr class='{$this->styleNamespace}-var-$type'><tbody><td class='{$this->styleNamespace}-type'>$type</td>";
228 foreach($value as $v) $sub .=
"<td class='{$this->styleNamespace}-value'>" . $this->varValue($v) .
"</td>";
229 $sub .=
"</tr></tbody>\n";
233 foreach($value as $k => $v) $sub .= $this->varRow($k,null,$v,$depth + 1,$hashes);
236 $sub =
"<table" . ($keys ?
" class='{$this->styleNamespace}-records'" :
'') .
">\n$sub</table>\n";
243 return $value ?
'true' :
'false';
247 if($time = $this->valueAsTime($value)) $value .=
"<span>$time</span>";
252 if($time = $this->valueAsTime($value)) $value .=
"<span>$time</span>";
256 protected function varTypeNull($value,&$size,&$sub,$depth,$hashes){
261 $class = $reflect = new \ReflectionObject($value);
262 if(memory_get_usage() > $this->memoryLimit) $sub .=
"<div class='{$this->styleNamespace}-memory'>out of memory</div>";
263 elseif(array_key_exists($hash = md5(print_r($value,
true)),$hashes)) $sub .=
"<a href='#dump-sub-{$hashes[$hash]}' class='{$this->styleNamespace}-recursion'>recursion</a>";
264 elseif($depth > $this->maxDepth) $sub .=
"<div class='{$this->styleNamespace}-depth'>depth too great</div>";
266 $docs = ($doc = $reflect->getDocComment()) ? $this->escapeDoc($doc) : null;
267 $hashes[$hash] = Str::random();
269 $default = [
'type' => null,
'docs' => null,
'class' => null,
'depth' => 0];
270 foreach($reflect->getProperties() as $property){
271 $property->setAccessible(
true);
272 $properties[$property->name] = [
273 'type' =>
'property',
274 'visibility' => array_merge($this->reflectVisibility($property),$property->isDefault() ? [] : [
'dynamic']),
275 'value' => $property->getValue($value),
276 'docs' => $property->getDocComment() ?: $this->propertyDoc($reflect->getFilename(),$property->name),
277 'sort' => $this->sortProperties ? strtolower(ltrim($property->name,
'_')) : null
280 foreach($reflect->getMethods() as $method)
if(preg_match(
'/^get[A-Z]/',$method->name) && !$method->getNumberOfParameters() && $method->isInternal())
try{
281 $method->setAccessible(
true);
282 $properties[$method->name] = [
284 'visibility' => $this->reflectVisibility($method),
285 'value' => $method->invoke($value),
286 'docs' => $method->getDocComment(),
287 'sort' => $this->sortProperties ? strtolower(substr($method->name,4)) : null
290 catch(\Exception $e){}
291 while($class = $class->getParentClass()){
292 if($doc = $class->GetDocComment()) $docs .=
"<h1>{$class->name}</h1>" . $this->escapeDoc($doc);
293 foreach($properties as $name => &$property)
if(call_user_func([$class,
'has' . ucfirst($property[
'type'])],$name)){
294 if($this->groupProperties){
295 $property[
'class'] = $class->name;
296 $property[
'depth']++;
298 if(!$property[
'docs']) $property[
'docs'] = ($property[
'type'] ==
'property' ? $class->getProperty($name) : $class->getMethod($name))->getDocComment() ?: ($property[
'type'] ==
'property' ? $this->propertyDoc($class->getFilename(),$name) : null);
302 if($reflect->hasMethod(
'__toString'))
try{
303 $properties[
'{string}'] = [
304 'visibility' => [
'public'],
305 'value' => (string)$value,
309 catch(\Exception $e){}
311 uasort($properties,
function($a,$b){
312 return ($a[
'depth'] <=> $b[
'depth']) ?: ($a[
'sort'] <=> $b[
'sort']);
314 if($docs) $sub .=
"\t<tr class='{$this->styleNamespace}-docs'><td colspan='4'><div>$docs</div></td></tr>\n";
316 foreach($properties as $name => $property){
317 if($property[
'class'] != $class) $sub .=
"\t<tr class='{$this->styleNamespace}-class'><td colspan='4'>" . htmlspecialchars($class = $property[
'class']) .
"</td></tr>\n";
318 $sub .= $this->varRow($name . ($property[
'type'] ==
'method' ?
'()' :
''),$property[
'visibility'],$property[
'value'],$depth + 1,$hashes,$property[
'docs']);
320 $sub =
"<table>\n" . str_replace($hashes[$hash],$this->_index + 1,$sub) .
"</table>\n";
323 if($constants = $reflect->getConstants()) $sub .= $this->varConstTable($constants);
324 return $reflect->name;
329 switch($type = get_resource_type($value)){
330 case 'curl': $info = curl_getinfo($value);
break;
331 case 'gd': $info = [
'width' => imagesx($value),
'height' => imagesy($value),
'colors' => imagecolorstotal($value)];
break;
332 case 'stream': $info = stream_get_meta_data($value);
break;
335 if($this->sortProperties) ksort($info);
336 foreach($info as $k => $v) $sub .= $this->varRow($k,null,$v);
337 $sub =
"<table>\n$sub</table>\n";
343 $size = strlen($value);
345 if(is_array($data = json_decode($value,
true))) $this->varTypeArray($data,$skip,$sub,$depth,$hashes);
346 elseif($this->validFilename && preg_match($this->validFilename,$value) && is_file($value)) $filename = $value;
347 if((mb_strlen($value) > $this->maxLength) || (strpos($value,
"\n") !==
false)){
348 if(!$sub) $sub =
"<pre>" . htmlspecialchars($value) .
"</pre>";
349 $value = mb_substr($value,0,$this->maxLength);
351 $value = htmlspecialchars($value);
352 foreach([
"\n" =>
'\\n',
"\r" =>
'\\r',
"\t" =>
'\\t'] as $s => $r) $value = str_replace($s,
"<code>$r</code>",$value);
353 if($filename) $value .=
"<span>" . htmlspecialchars(implode(
', ',[date($this->timeFormat,filemtime($filename)),Number::formatBytes(filesize($filename))])) .
"</span>";
358 return 'unknown type';
361 protected function varValue($value,&$size = null,&$sub = null,$depth = 0,$hashes = []){
363 return call_user_func_array(
364 [$this,method_exists($this,$method =
'varType' . ucfirst(strtolower(gettype($value)))) ? $method :
'varTypeUnknown'],
365 [$value,&$size,&$sub,$depth,$hashes]
369 protected function varRow($name,$visibility,$value,$depth = 0,$hashes = [],$docs = null){
370 $from = $this->_index + 1;
371 $type = strtolower(gettype($value));
372 $value = $this->varValue($value,$size,$sub,$depth,$hashes);
374 $index = ++$this->_index;
376 "<div class='{$this->styleNamespace}-actions'>" .
377 "<button type='button' class='{$this->styleNamespace}-show' id='dump-show-$index'" . ($index >= $from ?
" onclick='{$this->scriptNamespace}.showSubs($from,$index,event)'" :
'') .
">+</button>" .
378 "<button type='button' class='{$this->styleNamespace}-hide' id='dump-hide-$index' onclick='{$this->scriptNamespace}.hideSub($index,event)'>-</button>" .
381 "\t<tr class='{$this->styleNamespace}-sub' id='dump-sub-$index'><td colspan='" . ($visibility ? 4 : 3) .
"' class='{$this->styleNamespace}-sub'>" .
382 "<div class='{$this->styleNamespace}-name'>" . (substr_count($sub,
'<tr') * 2 >= strlen($name) ?
"<div>" . htmlspecialchars($name) .
"</div>" :
'') .
"</div>" .
387 "\t<tr class='{$this->styleNamespace}-var-$type'>" .
388 "<th" . ($docs ?
" title='" . htmlspecialchars($this->escapeDoc($docs),ENT_QUOTES) .
"'" :
'') .
">" . htmlspecialchars($name) .
"</th>" .
389 ($visibility ?
"<td class='{$this->styleNamespace}-visibility" . implode(
" {$this->styleNamespace}-visibility-",array_merge([null],$visibility)) .
"'>" . implode(
' ',$visibility) .
"</td>" :
'') .
390 "<td class='{$this->styleNamespace}-type'>$type" . ($size === null ?
'' :
"<span>$size</span>") .
"</td>" .
391 "<td class='{$this->styleNamespace}-value'" . ($sub ?
" onclick='{$this->scriptNamespace}.showSub($index,event)'" :
'') .
">$value</td>" .
402 public function var($name,$value,$docs = null){
403 return "<table class='{$this->styleNamespace}-var'>\n" . $this->varRow($name,null,$value,0,[],$docs) .
"</table>\n";
407 if(array_key_exists(
'file',$step)) $tabs[
'source'] = [
'caption' =>
'Source',
'tab' => $this->source($step[
'file'],$step[
'line'])];
408 $filename = $reflect ? strtolower($step[
'class'] ??
'function') .
'.' . str_replace(
'_',
'-',$reflect->name) : null;
409 if($args = $step[
'args'] ?? null){
411 if($reflect)
foreach($reflect->getParameters() as $param) $params[] = $param->name;
413 foreach($args as $index => $arg){
415 if(is_numeric($arg)){
416 if($this->_paramConsts === null) $this->_paramConsts = $this->paramConstsFile ? require($this->paramConstsFile) : [];
417 foreach(($this->_paramConsts[$filename][$params[$index] ?? null] ?? []) as $const => $value)
if($arg & $value) $consts[$const] = $value;
418 if($consts && (array_sum($consts) != $arg)) $consts[
'???'] = null;
420 $tab .= $this->var(array_key_exists($index,$params) ?
'$' . $params[$index] :
'#' . $index,$arg,implode(
' + ',array_keys($consts)));
422 $tabs[
'args'] = [
'caption' =>
'Parameters',
'tab' => $tab];
424 if(array_key_exists(
'object',$step)) $tabs[
'object'] = [
'caption' =>
'Object',
'tab' => $this->var($step[
'class'] ?? null,$step[
'object'])];
426 $docs = [($prev = null) => $reflect->isInternal() ? true : $reflect->getDocComment()];
428 if($reflect instanceof \ReflectionMethod){
429 $class = $reflect->getDeclaringClass();
430 while($class = $class->getParentClass()){
431 if($method = $class->hasMethod($reflect->name)){
432 if(($docs[$class->name] = $class->getMethod($reflect->name)->getDocComment()) == $docs[$prev]) $docs[$prev] =
false;
433 $prev = $class->name;
436 "<span title='" . htmlspecialchars($class->getFileName()) .
"'" . ($method ?
'' :
" class='{$this->styleNamespace}-parent-base'") .
">" .
437 ($class->isInternal() ?
"<a href='{$this->remoteDocs}class." . strtolower($class->name) .
".php' target='_blank'>" :
'') .
439 ($class->isInternal() ?
"</a>" :
'') .
440 (($traits = $class->getTraitNames()) ?
" <span class='{$this->styleNamespace}-traits'>(traits: " . implode(
', ',$traits) .
")</span>" :
'') .
441 (($interfaces = $class->getInterfaceNames()) ?
" <span class='{$this->styleNamespace}-interfaces'>(interfaces: " . implode(
', ',$interfaces) .
")</span>" :
'') .
445 if($docs = array_filter($docs)){
446 foreach($docs as &$doc) $doc = $doc ===
true 447 ?
"<a href='{$this->remoteDocs}$filename.php' target='_blank'>" . preg_replace(
'~^.*?://~',
'',$this->remoteDocs) .
"$filename.php</a>" .
448 ($this->localDocs ?
" / " . preg_replace(
'~^.*?://~',
'',$this->localDocs) .
"$filename.html: <iframe src='{$this->localDocs}$filename.html'></iframe>" :
'')
449 : $this->escapeDoc($doc);
451 $tabs[
'docs'] = [
'caption' =>
'Documentation',
'tab' =>
"<div class='{$this->styleNamespace}-docs'><h1>" . Record::implode($docs,
"</p>\n\t<h1>",
"</h1>\n\t<p>") .
"</p></div>"];
453 if($filename = $reflect->getFilename()) $tabs[
'function'] = [
'caption' =>
'Function',
'tab' => $this->source($filename,$reflect->getStartLine(),$reflect->getEndLine())];
455 if(array_key_exists(
'class',$step)){
456 $class = new \ReflectionClass($step[
'class']);
457 if($constants = $class->getConstants()) $tabs[
'const'] = [
'caption' =>
'Constants',
'tab' => $this->varConstTable($constants)];
459 if($reflect && ($misc = array_filter($misc = [
460 'Return type' => $reflect->getReturnType(),
461 'Parents' => implode(
', ',array_filter($protos)),
462 'Deprecated' => $reflect->isDeprecated() ?
'yes' : null
463 ]))) $tabs[
'misc'] = [
'caption' =>
'Other',
'tab' =>
"<ul class='{$this->styleNamespace}-misc'><li><b>" . Record::implode($misc,
"</li>\n\t<li><b>",
':</b> ') .
"</li></ul>"];
468 return array_key_exists($key,$tabs) ?
" onclick='{$this->scriptNamespace}.showTab($index,\"$key\"," . json_encode(array_keys($tabs)) .
")'" : null;
475 public function trace($trace = null){
476 if($trace === null) $trace = debug_backtrace();
478 foreach($trace as $step){
479 $index = ++$this->_index;
480 $actions = $sub = $nav = $params = $reflect = null;
481 if(array_key_exists(
'function',$step))
try{
482 $reflect = array_key_exists(
'class',$step) ? new \ReflectionMethod($step[
'class'],$step[
'function']) : new \ReflectionFunction($step[
'function']);
484 catch(\Exception $e){
487 if($reflect && ($args = $step[
'args'] ?? null))
foreach($reflect->getParameters() as $param) $params .=
488 ($params ?
',' :
'') .
489 ($param->isPassedByReference() ?
'&' :
'') .
490 "<span class='{$this->styleNamespace}-name'>\$" . htmlspecialchars($param->name) .
"</span>" .
491 ($param->isDefaultValueAvailable() ?
' = ' . htmlspecialchars(var_export($param->getDefaultValue(),
true)) :
'');
492 if($tabs = $this->traceTabs($step,$reflect)){
494 "<div class='{$this->styleNamespace}-actions'>" .
495 "<button type='button' class='{$this->styleNamespace}-show' id='dump-show-$index' onclick='{$this->scriptNamespace}.showSub($index)'>+</button>" .
496 "<button type='button' class='{$this->styleNamespace}-hide' id='dump-hide-$index' onclick='{$this->scriptNamespace}.hideSub($index)'>-</button>" .
498 foreach($tabs as $key => $tab){
499 $nav .=
"<button type='button' class='{$this->styleNamespace}-tab-$key" . ($nav ?
'' :
" {$this->styleNamespace}-active") .
"' id='dump-nav-$index-$key'" . $this->traceShowTab($tabs,$index,$key) .
">" . ($tab[
'caption'] ?? $key) .
"</button>";
500 $sub .=
"\t\t<div id='dump-tab-$index-$key' class='{$this->styleNamespace}-tab-$key'>{$tab['tab']}</div>\n";
502 $sub =
"\t<tr class='{$this->styleNamespace}-sub' id='dump-sub-$index'><td colspan='3' class='{$this->styleNamespace}-tabs'>\n\t\t<nav>$nav</nav>\n$sub\t</td></tr>\n";
505 "\t<tr class='{$this->styleNamespace}-step'>\n" .
506 "\t\t<td>$actions</td>\n" .
507 "\t\t<td>" . (array_key_exists(
'file',$step) ?
"<span class='{$this->styleNamespace}-file'" . $this->traceShowTab($tabs,$index,
'source') .
">" . htmlspecialchars($step[
'file'] .
"#" . $step[
'line']) .
" <input class='{$this->styleNamespace}-copy' value='" . htmlspecialchars($step[
'file'],ENT_QUOTES) .
"' onclick='{$this->scriptNamespace}.copy(this)'></span>" :
'') .
"</td>\n" .
509 (array_key_exists(
'class',$step) ?
"<span class='{$this->styleNamespace}-class'" . $this->traceShowTab($tabs,$index,
'object') .
">" . htmlspecialchars($step[
'class'] . ($step[
'type'] ?? null)) .
"</span>" :
'') .
510 (array_key_exists(
'function',$step)
511 ?
"<span class='{$this->styleNamespace}-function'" . ($this->traceShowTab($tabs,$index,
'docs') ?: $this->traceShowTab($tabs,$index,
'function')) .
">" . htmlspecialchars($step[
'function']) .
"</span>" .
512 "<span class='{$this->styleNamespace}-args'" . $this->traceShowTab($tabs,$index,
'args') .
">($params)</span>" 519 return "<table class='{$this->styleNamespace}-trace'>\n$table</table>\n";
525 public static function die($value = null){
528 "<!DOCTYPE html>\n<html>\n" .
529 "\t<head><title>Dump</title>" . $dump->head() .
"</head>\n" .
530 "\t<body>" . (func_num_args() ? $dump->var(
'value',$value) : $dump->trace()) .
"</body>\n" .
traceShowTab($tabs, $index, $key)
head()
Head for dumps (style and script tags).
varTypeNull($value, &$size, &$sub, $depth, $hashes)
varConstTable($constants)
reflectVisibility($reflect)
varTypeString($value, &$size, &$sub, $depth, $hashes)
__construct($config=null)
varTypeInteger($value, &$size, &$sub, $depth, $hashes)
varTypeDouble($value, &$size, &$sub, $depth, $hashes)
trace($trace=null)
Dump a (back-) trace.
varRow($name, $visibility, $value, $depth=0, $hashes=[], $docs=null)
var($name, $value, $docs=null)
Dump a variable.
static memoryLimit()
Script memory limit.
varTypeObject($value, &$size, &$sub, $depth, $hashes)
varValue($value, &$size=null, &$sub=null, $depth=0, $hashes=[])
source($filename, $line_no=null, $line_to=null, $type=null, $header=null)
Dump source code.
varTypeArray($value, &$size, &$sub, $depth, $hashes)
static die($value=null)
Dump and die.
propertyDoc($filename, $property)
varTypeUnknown($value, &$size, &$sub, $depth, $hashes)
varTypeBoolean($value, &$size, &$sub, $depth, $hashes)
traceTabs($step, $reflect)
varTypeResource($value, &$size, &$sub, $depth, $hashes)