public function getHandler($obj) { if (!is_object($obj)) { return $this->getHandlerByName(gettype($obj)); } $class = get_class($obj); $handler = null; $ex = null; while (true) { try { $handler = $this->getHandlerByName($class); return $handler; } catch (\Exception $e) { if (!$ex) { $ex = $e; } $class = get_parent_class($class); if (!$class) { break; } } } $rObj = new \ReflectionObject($obj); $interfaces = $rObj->getInterfaceNames(); foreach ($interfaces as $interface) { try { $handler = $this->getHandlerByName($interface); return $handler; } catch (\Exception $e) { continue; } } throw $ex; }
/** * Method that checks if the current instance implementing Serializable interface */ public function testSerializable() { if ($this instanceof \Serializable) { echo get_class($this), ' implements `Serializable` interface now!', PHP_EOL; $reflection = new \ReflectionObject($this); var_dump($reflection->getInterfaceNames(), $reflection->getTraitNames()); } else { echo get_class($this), ' does not implement `Serializable` interface', PHP_EOL; } }
/** * Method that checks if the current instance implementing Serializable interface */ public function testSerializable() { if ($this instanceof \Serializable) { echo get_class($this), ' implements `Serializable` interface now!', PHP_EOL; $reflection = new \ReflectionObject($this); echo "List of interfaces:", PHP_EOL; foreach ($reflection->getInterfaceNames() as $interfaceName) { echo '-> ', $interfaceName, PHP_EOL; } echo "List of traits:", PHP_EOL; foreach ($reflection->getTraitNames() as $traitName) { echo '-> ', $traitName, PHP_EOL; } } else { echo get_class($this), ' does not implement `Serializable` interface', PHP_EOL; } }
protected function typedGetTransformer($name, $type) { $transformer = $this->getTransformer($name); if (!$transformer instanceof $type) { $reflection = new \ReflectionObject($transformer); throw new \InvalidArgumentException(sprintf("The transformer '%s' doesn't implement %s but is implements %s", $name, $type, implode(",", $reflection->getInterfaceNames()))); } return $transformer; }
public function dumpServerMemory($outputFolder, $maxNesting, $maxStringSize) { gc_disable(); if (!file_exists($outputFolder)) { mkdir($outputFolder, 0777, true); } $this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash"); $obData = fopen($outputFolder . "/objects.js", "wb+"); $staticProperties = []; $data = []; $objects = []; $refCounts = []; $this->continueDump($this->server, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize); do { $continue = false; foreach ($objects as $hash => $object) { if (!is_object($object)) { continue; } $continue = true; $className = get_class($object); $objects[$hash] = true; $reflection = new \ReflectionObject($object); $info = ["information" => "{$hash}@{$className}", "properties" => []]; if ($reflection->getParentClass()) { $info["parent"] = $reflection->getParentClass()->getName(); } if (count($reflection->getInterfaceNames()) > 0) { $info["implements"] = implode(", ", $reflection->getInterfaceNames()); } foreach ($reflection->getProperties() as $property) { if ($property->isStatic()) { continue; } if (!$property->isPublic()) { $property->setAccessible(true); } $this->continueDump($property->getValue($object), $info["properties"][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize); } fwrite($obData, "{$hash}@{$className}: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n"); if (!isset($objects["staticProperties"][$className])) { $staticProperties[$className] = []; foreach ($reflection->getProperties() as $property) { if (!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className) { continue; } if (!$property->isPublic()) { $property->setAccessible(true); } $this->continueDump($property->getValue($object), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize); } } } echo "[Dump] Wrote " . count($objects) . " objects\n"; } while ($continue); file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); file_put_contents($outputFolder . "/serverEntry.js", json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); file_put_contents($outputFolder . "/referenceCounts.js", json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); echo "[Dump] Finished!\n"; gc_enable(); $this->server->forceShutdown(); }
/** * cfdump-style debugging output * @param $var The variable to output. * @param $limit Maximum recursion depth for arrays (default 0 = all) * @param $label text to display in complex data type header * @param $depth Current depth (default 0) */ public function dump(&$var, $limit = 0, $label = '', $depth = 0) { if (!is_int($depth)) $depth = 0; if (!is_int($limit)) $limit = 0; if (($limit > 0) && ($depth >= $limit)) return; static $seen = array(); $he = function ($s) { return htmlentities($s); }; $tabs = "\n" . str_repeat("\t", $depth); $depth++; $printCount = 0; $self = $this; $echoFunction = function($var, $tabs, $limit = 0, $label = '', $depth = 0) use ($self) { if (!is_subclass_of($var, 'ReflectionFunctionAbstract')) { $var = new \ReflectionFunction($var); } echo "$tabs<table class=\"dump function depth${depth}\">$tabs<thead><tr><th>" . ($label != '' ? $label . ' - ' : '') . (is_callable(array($var, 'getModifiers')) ? htmlentities(implode(' ', \Reflection::getModifierNames($var->getModifiers()))) : '') . " function " . htmlentities($var->getName()) . "</th></tr></thead>$tabs<tbody>"; echo "$tabs<tr><td class=\"value\">$tabs<table class=\"dump layout\">$tabs<tr><th>Parameters:</th><td>"; $params = $var->getParameters(); if (count($params) > 0) { echo "</td></tr>$tabs<tr><td colspan=\"2\">$tabs<table class=\"dump param\">$tabs<thead><tr><th>Name</th><th>Array/Ref</th><th>Required</th><th>Default</th></tr></thead>$tabs<tbody>"; foreach ($params as $param) { echo "$tabs<tr><td>" . htmlentities($param->getName()) . "</td><td>" . ($param->isArray() ? "Array " : "") . ($param->isPassedByReference() ? "Reference" : "") . "</td><td>" . ($param->isOptional() ? "Optional" : "Required") . "</td><td>"; if ($param->isOptional() && $param->isDefaultValueAvailable()) { $self->dump($param->getDefaultValue(), $limit, $label, $depth); } echo "</td></tr>"; } echo "$tabs</tbody>$tabs</table>"; } else { echo "none</td></tr>"; } $comment = trim($var->getDocComment()); if (($comment !== NULL) && ($comment !== '')) { echo "$tabs<tr><th>Doc Comment:</th><td><kbd>" . str_replace("\n", "<br/>", htmlentities($comment)) . "</kbd></td></tr>"; } echo "</table>$tabs</td></tr>"; echo "$tabs</tbody>$tabs</table>"; }; if (!array_key_exists('fw1dumpstarted', $_REQUEST)) { $_REQUEST['fw1dumpstarted'] = TRUE; echo<<<DUMPCSSJS <style type="text/css">/* fw/1 dump */ table.dump { color: black; background-color: white; font-size: xx-small; font-family: verdana,arial,helvetica,sans-serif; border-spacing: 0; border-collapse: collapse; } table.dump th { text-indent: -2em; padding: 0.25em 0.25em 0.25em 2.25em; color: #fff; } table.dump td { padding: 0.25em; } table.dump .key { cursor: pointer; } table.dump td.shh { background-color: #ddd; } table.dump td.shh div { display: none; } table.dump td.shh:before { content: "..."; } table.dump th, table.dump td { border-width: 2px; border-style: solid; border-spacing: 0; vertical-align: top; text-align: left; } table.dump.object, table.dump.object > * > tr > td, table.dump.object > thead > tr > th { border-color: #f00; } table.dump.object > thead > tr > th { background-color: #f44; } table.dump.object > tbody > tr > .key { background-color: #fcc; } table.dump.array, table.dump.array > * > tr > td, table.dump.array > thead > tr > th { border-color: #060; } table.dump.array > thead > tr > th { background-color: #090; } table.dump.array > tbody > tr > .key { background-color: #cfc; } table.dump.struct, table.dump.struct > * > tr > td, table.dump.struct > thead > tr > th { border-color: #00c; } table.dump.struct > thead > tr > th { background-color: #44c; } table.dump.struct > tbody > tr > .key { background-color: #cdf; } table.dump.function, table.dump.function > * > tr > td, table.dump.function > thead > tr > th { border-color: #a40; } table.dump.function > thead > tr > th { background-color: #c60; } table.dump.layout, table.dump.layout > * > tr > td, table.dump.layout > thead > tr > th { border-color: #fff; } table.dump.layout > * > tr > th { font-style: italic; background-color: #fff; color: #000; font-weight: normal; border: none; } table.dump.param, table.dump.param > * > tr > td, table.dump.param > thead > tr > th { border-color: #ddd; } table.dump.param > thead > tr > th { background-color: #eee; color: black; font-weight: bold; } </style> <script type="text/javascript" language="JavaScript"> (function(w,d){ var addEvent = function(o,t,f) { if (o.addEventListener) o.addEventListener(t,f,false); else if (o.attachEvent) { o['e' + t + f] = f; o[t + f] = function() { o['e' + t + f](w.event); } o.attachEvent('on' + t, o[t + f]); } }; // addEvent var clickCell = function(e) { var target = e.target || this; var sib = target.nextSibling; if (sib && sib.tagName && (sib.tagName.toLowerCase() === 'td')) { if (/(^|\s)shh(\s|$)/.test(sib.className)) sib.className = sib.className.replace(/(^|\s)shh(\s|$)/, ' '); else sib.className += ' shh'; } if (e && e.stopPropagation) e.stopPropagation(); else w.event.cancelBubble = true; return false; }; // clickCell var collapsifyDumps = function() { setTimeout(function() { var tables = document.getElementsByTagName('table'); for(var t = 0; t < tables.length; t++) { var table = tables[t]; var dumpPattern = /(^|\s)dump(\s|$)/; var depthPattern = /(^|\s)depth1(\s|$)/; if (! (dumpPattern.test(table.className) && depthPattern.test(table.className) )) continue; var cells = table.getElementsByTagName('td'); var keyPattern = /(^|\s)key(\s|$)/; var keyCount = 0; for (var c = 0; c < cells.length; c++) { var cell = cells[c]; if (! (keyPattern.test(cell.className))) continue; addEvent(cell, 'click', clickCell); } // for k } // for t }, 250); }; // collapsify dumps if (d.addEventListener) d.addEventListener("DOMContentLoaded", collapsifyDumps, false); else d.onreadystatechange = function() { if (d.readyState === 'interactive') collapsifyDumps(this); }; })(window,document); </script> DUMPCSSJS; } if (is_array($var)) { // It turns out that identity (===) in PHP isn't actually identity. It's more like "do you look similar enough to fool an untrained observer?". Lame! // $label = $label === '' ? (($var === $_POST) ? '$_POST' : (($var === $_GET) ? '$_GET' : (($var === $_COOKIE) ? '$_COOKIE' : (($var === $_ENV) ? '$_ENV' : (($var === $_FILES) ? '$_FILES' : (($var === $_REQUEST) ? '$_REQUEST' : (($var === $_SERVER) ? '$_SERVER' : (isset($_SESSION) && ($var === $_SESSION) ? '$_SESSION' : '')))))))) : $label; $c = count($var); if(isset($var['fw1recursionsentinel'])) { echo "(Recursion)"; } $aclass = (($c > 0) && array_key_exists(0, $var) && array_key_exists($c - 1, $var)) ? 'array' : 'struct'; $var['fw1recursionsentinel'] = TRUE; echo "$tabs<table class=\"dump ${aclass} depth${depth}\">$tabs<thead><tr><th colspan=\"2\">" . ($label != '' ? $label . ' - ' : '') . "array" . ($c > 0 ? "" : " [empty]") . "</th></tr></thead>$tabs<tbody>"; foreach ($var as $index => $aval) { if ($index === 'fw1recursionsentinel') continue; echo "$tabs<tr><td class=\"key\">" . $he($index) . "</td><td class=\"value\"><div>"; $this->dump($aval, $limit, '', $depth); echo "</div></td></tr>"; $printCount++; if (($limit > 0) && ($printCount >= $limit) && ($aclass === 'array')) break; } echo "$tabs</tbody>$tabs</table>"; // unset($var['fw1recursionsentinel']); } elseif (is_string($var)) { echo $var === '' ? '[EMPTY STRING]' : htmlentities($var); } elseif (is_bool($var)) { echo $var ? "TRUE" : "FALSE"; } elseif (is_callable($var) || (is_object($var) && is_subclass_of($var, 'ReflectionFunctionAbstract'))) { $echoFunction($var, $tabs, $limit, $label, $depth); } elseif (is_float($var)) { echo "(float) " . htmlentities($var); } elseif (is_int($var)) { echo "(int) " . htmlentities($var); } elseif (is_null($var)) { echo "NULL"; } elseif (is_object($var)) { $ref = new \ReflectionObject($var); $parent = $ref->getParentClass(); $interfaces = implode("<br/>implements ", $ref->getInterfaceNames()); /* try { $serial = serialize($var); } catch (\Exception $e) { $serial = 'hasclosure' . $ref->getName(); } $objHash = 'o' . md5($serial); */ $objHash = spl_object_hash($var); $refHash = 'r' . md5($ref); echo "$tabs<table class=\"dump object depth${depth}\"" . (isset($seen[$refHash]) ? "" : "id=\"$refHash\"") . ">$tabs<thead>$tabs<tr><th colspan=\"2\">" . ($label != '' ? $label . ' - ' : '') . "object " . htmlentities($ref->getName()) . ($parent ? "<br/>extends " .$parent->getName() : "") . ($interfaces !== '' ? "<br/>implements " . $interfaces : "") . "</th></tr>$tabs<tbody>"; if (isset($seen[$objHash])) { echo "$tabs<tr><td colspan=\"2\"><a href=\"#$refHash\">[see above for details]</a></td></tr>"; } else { $seen[$objHash] = TRUE; $constants = $ref->getConstants(); if (count($constants) > 0) { echo "$tabs<tr><td class=\"key\">CONSTANTS</td><td class=\"values\"><div>$tabs<table class=\"dump object\">"; foreach ($constants as $constant => $cval) { echo "$tabs<tr><td class=\"key\">" . htmlentities($constant) . "</td><td class=\"value constant\"><div>"; $this->dump($cval, $limit, '', $depth + 1); echo "</div></td></tr>"; } echo "$tabs</table>$tabs</div></td></tr>"; } $properties = $ref->getProperties(); if (count($properties) > 0) { echo "$tabs<tr><td class=\"key\">PROPERTIES</td><td class=\"values\"><div>$tabs<table class=\"dump object\">"; foreach ($properties as $property) { echo "$tabs<tr><td class=\"key\">" . htmlentities(implode(' ', \Reflection::getModifierNames($property->getModifiers()))) . " " . $he($property->getName()) . "</td><td class=\"value property\"><div>"; $wasHidden = $property->isPrivate() || $property->isProtected(); $property->setAccessible(TRUE); $propertyValue = $property->getValue($var); $this->dump($propertyValue, $limit, '', $depth + 1); if ($wasHidden) { $property->setAccessible(FALSE); } echo "</div></td></tr>"; } echo "$tabs</table>$tabs</div></td></tr>"; } $methods = $ref->getMethods(); if (count($methods) > 0) { echo "$tabs<tr><td class=\"key\">METHODS</td><td class=\"values shh\"><div>"; if (isset($seen[$refHash])) { echo "<a href=\"#$refHash\">[see above for details]</a>"; } else { $seen[$refHash] = TRUE; echo "$tabs<table class=\"dump object\">"; foreach ($methods as $method) { echo "$tabs<tr><td class=\"key\">" . htmlentities($method->getName()) . "</td><td class=\"value function\"><div>"; $echoFunction($method, $tabs, $limit, '', $depth + 1); echo "</div></td></tr>"; } echo "$tabs</table>"; } echo "$tabs</div></td></tr>"; } } echo "$tabs</tbody>$tabs</table>"; } elseif (is_resource($var)) { echo "(Resource)"; } elseif (is_numeric($var)) { echo htmlentities($var); } elseif (is_scalar($var)) { echo htmlentities($var); } else { echo gettype($var); } } // dump
/** * cfdump-style debugging output * @param $var The variable to output. * @param $limit Maximum recursion depth for arrays (default 0 = all) * @param $label text to display in complex data type header * @param $depth Current depth (default 0) */ public function dump(&$var, $limit = 0, $label = '', $depth = 0) { if ($limit > 0 && $depth >= $limit) { return; } static $seen = array(); $he = function ($s) { return htmlentities($s); }; $self = $this; $echoFunction = function ($var, $tabs, $label = '') use($self) { if (!is_subclass_of($var, 'ReflectionFunctionAbstract')) { $var = new \ReflectionFunction($var); } echo "{$tabs}<table class=\"dump function\">{$tabs}<thead><tr><th>" . ($label != '' ? $label . ' - ' : '') . (is_callable(array($var, 'getModifiers')) ? htmlentities(implode(' ', \Reflection::getModifierNames($var->getModifiers()))) : '') . " function " . htmlentities($var->getName()) . "</th></tr></thead>{$tabs}<tbody>"; echo "{$tabs}<tr><td class=\"value\">{$tabs}<table class=\"dump layout\">{$tabs}<tr><th>Parameters:</th><td>"; $params = $var->getParameters(); if (count($params) > 0) { echo "</td></tr>{$tabs}<tr><td colspan=\"2\">{$tabs}<table class=\"dump param\">{$tabs}<thead><tr><th>Name</th><th>Array/Ref</th><th>Required</th><th>Default</th></tr></thead>{$tabs}<tbody>"; foreach ($params as $param) { echo "{$tabs}<tr><td>" . htmlentities($param->getName()) . "</td><td>" . ($param->isArray() ? "Array " : "") . ($param->isPassedByReference() ? "Reference" : "") . "</td><td>" . ($param->isOptional() ? "Optional" : "Required") . "</td><td>"; if ($param->isOptional()) { $self->dump($param->getDefaultValue()); } echo "</td></tr>"; } echo "{$tabs}</tbody>{$tabs}</table>"; } else { echo "none</td></tr>"; } $comment = trim($var->getDocComment()); if ($comment !== NULL && $comment !== '') { echo "{$tabs}<tr><th>Doc Comment:</th><td><kbd>" . str_replace("\n", "<br/>", htmlentities($comment)) . "</kbd></td></tr>"; } echo "</table>{$tabs}</td></tr>"; echo "{$tabs}</tbody>{$tabs}</table>"; }; $tabs = "\n" . str_repeat("\t", $depth); $depth++; $printCount = 0; if (!array_key_exists('fw1dumpstarted', $_REQUEST)) { $_REQUEST['fw1dumpstarted'] = TRUE; echo <<<DUMPCSS <style type="text/css">/* fw/1 dump */ table.dump { color: black; background-color: white; font-size: xx-small; font-family: verdana,arial,helvetica,sans-serif; border-spacing: 0; border-collapse: collapse; } table.dump th { text-indent: -2em; padding: 0.25em 0.25em 0.25em 2.25em; color: #fff; } table.dump td { padding: 0.25em; } table.dump th, table.dump td { border-width: 2px; border-style: solid; border-spacing: 0; vertical-align: top; text-align: left; } table.dump.object, table.dump.object td, table.dump.object th { border-color: #f00; } table.dump.object th { background-color: #f44; } table.dump.object .key { background-color: #fcc; } table.dump.array, table.dump.array td, table.dump.array th { border-color: #060; } table.dump.array th { background-color: #090; } table.dump.array .key { background-color: #cfc; } table.dump.struct, table.dump.struct td, table.dump.struct th { border-color: #00c; } table.dump.struct th { background-color: #44c; } table.dump.struct .key { background-color: #cdf; } table.dump.function, table.dump.function td, table.dump.function th { border-color: #a40; } table.dump.function th { background-color: #c60; } table.dump.layout, table.dump.layout td, table.dump.layout th { border-color: #fff; } table.dump.layout th { font-style: italic; background-color: #fff; color: #000; font-weight: normal; } table.dump.param, table.dump.param td, table.dump.param th { border-color: #ddd; } table.dump.param th { background-color: #eee; color: black; font-weight: bold; } </style> DUMPCSS; } if (is_array($var)) { $label = $label === '' ? $var === $_POST ? '$_POST' : ($var === $_GET ? '$_GET' : ($var === $_COOKIE ? '$_COOKIE' : ($var === $_ENV ? '$_ENV' : ($var === $_FILES ? '$_FILES' : ($var === $_REQUEST ? '$_REQUEST' : ($var === $_SERVER ? '$_SERVER' : ($var === $_SESSION ? '$_SESSION' : ''))))))) : $label; $c = count($var); if (isset($var['fw1recursionsentinel'])) { echo "(Recursion)"; } $aclass = $c > 0 && array_key_exists(0, $var) && array_key_exists($c - 1, $var) ? 'array' : 'struct'; $var['fw1recursionsentinel'] = true; echo "{$tabs}<table class=\"dump {$aclass}\">{$tabs}<thead><tr><th colspan=\"2\">" . ($label != '' ? $label . ' - ' : '') . "array" . ($c > 0 ? "" : " [empty]") . "</th></tr></thead>{$tabs}<tbody>"; foreach ($var as $index => $aval) { if ($index === 'fw1recursionsentinel') { continue; } echo "{$tabs}<tr><td class=\"key\">" . $he($index) . "</td><td class=\"value\">"; $this->dump($aval, $limit, '', $depth); echo "</td></tr>"; $printCount++; if ($limit > 0 && $printCount >= $limit && $aclass === 'array') { break; } } echo "{$tabs}</tbody>{$tabs}</table>"; // unset($var['fw1recursionsentinel']); } elseif (is_string($var)) { echo $var === '' ? '[EMPTY STRING]' : htmlentities($var); } elseif (is_bool($var)) { echo $var ? "TRUE" : "FALSE"; } elseif (is_callable($var) || is_object($var) && is_subclass_of($var, 'ReflectionFunctionAbstract')) { $echoFunction($var, $tabs, $label); } elseif (is_float($var)) { echo "(float) " . htmlentities($var); } elseif (is_int($var)) { echo "(int) " . htmlentities($var); } elseif (is_null($var)) { echo "NULL"; } elseif (is_object($var)) { $ref = new \ReflectionObject($var); $parent = $ref->getParentClass(); $interfaces = implode("<br/>implements ", $ref->getInterfaceNames()); try { $serial = serialize($var); } catch (\Exception $e) { $serial = 'hasclosure' . $ref->getName(); } $objHash = 'o' . md5($serial); $refHash = 'r' . md5($ref); echo "{$tabs}<table class=\"dump object\"" . (isset($seen[$refHash]) ? "" : "id=\"{$refHash}\"") . ">{$tabs}<thead>{$tabs}<tr><th colspan=\"2\">" . ($label != '' ? $label . ' - ' : '') . "object " . htmlentities($ref->getName()) . ($parent ? "<br/>extends " . $parent->getName() : "") . ($interfaces !== '' ? "<br/>implements " . $interfaces : "") . "</th></tr>{$tabs}<tbody>"; if (isset($seen[$objHash])) { echo "{$tabs}<tr><td colspan=\"2\"><a href=\"#{$refHash}\">[see above for details]</a></td></tr>"; } else { $seen[$objHash] = TRUE; $constants = $ref->getConstants(); if (count($constants) > 0) { echo "{$tabs}<tr><td class=\"key\">CONSTANTS</td><td class=\"values\">{$tabs}<table class=\"dump object\">"; foreach ($constants as $constant => $cval) { echo "{$tabs}<tr><td class=\"key\">" . htmlentities($constant) . "</td><td class=\"value constant\">"; $this->dump($cval, $limit, '', $depth); echo "</td></tr>"; } echo "{$tabs}</table>{$tabs}</td></tr>"; } $properties = $ref->getProperties(); if (count($properties) > 0) { echo "{$tabs}<tr><td class=\"key\">PROPERTIES</td><td class=\"values\">{$tabs}<table class=\"dump object\">"; foreach ($properties as $property) { echo "{$tabs}<tr><td class=\"key\">" . htmlentities(implode(' ', \Reflection::getModifierNames($property->getModifiers()))) . " " . $he($property->getName()) . "</td><td class=\"value property\">"; $wasHidden = $property->isPrivate() || $property->isProtected(); $property->setAccessible(TRUE); $this->dump($property->getValue($var), $limit, '', $depth); if ($wasHidden) { $property->setAccessible(FALSE); } echo "</td></tr>"; } echo "{$tabs}</table>{$tabs}</td></tr>"; } $methods = $ref->getMethods(); if (count($methods) > 0) { echo "{$tabs}<tr><td class=\"key\">METHODS</td><td class=\"values\">"; if (isset($seen[$refHash])) { echo "<a href=\"#{$refHash}\">[see above for details]</a>"; } else { $seen[$refHash] = TRUE; echo "{$tabs}<table class=\"dump object\">"; foreach ($methods as $method) { echo "{$tabs}<tr><td class=\"key\">" . htmlentities($method->getName()) . "</td><td class=\"value function\">"; $echoFunction($method, $tabs, ''); echo "</td></tr>"; } echo "{$tabs}</table>"; } echo "{$tabs}</td></tr>"; } } echo "{$tabs}</tbody>{$tabs}</table>"; } elseif (is_resource($var)) { echo "(Resource)"; } elseif (is_numeric($var)) { echo htmlentities($var); } elseif (is_scalar($var)) { echo htmlentities($var); } else { echo gettype($var); } }
private function _reflectionInterfaces(\ReflectionObject $reflection) { $interfaces = $reflection->getInterfaceNames(); if (count($interfaces)) { $name = '<span class="d-information" title="Interfaces that this object implements"></span> '; $name .= '<span class="d-obj-info">Interfaces</span>'; $inamesstr = implode(', ', $interfaces); $this->render($inamesstr, $name); } }
/** * cfdump-style debugging output * @param $var The variable to output. * @param $limit Maximum recursion depth for arrays (default 0 = all) * @param $label text to display in complex data type header * @param $depth Current depth (default 0) */ public static function dump(&$var, $limit = 0, $label = '', $depth = 0) { if (!is_int($depth)) $depth = 0; if (!is_int($limit)) $limit = 0; if (($limit > 0) && ($depth >= $limit)) return; static $seen = array(); $he = function ($s) { return htmlentities($s); }; $tabs = "\n" . str_repeat("\t", $depth); $depth++; $printCount = 0; self::dumpCssJs(); if (is_array($var)) { // It turns out that identity (===) in PHP isn't actually identity. It's more like "do you look similar enough to fool an untrained observer?". Lame! // $label = $label === '' ? (($var === $_POST) ? '$_POST' : (($var === $_GET) ? '$_GET' : (($var === $_COOKIE) ? '$_COOKIE' : (($var === $_ENV) ? '$_ENV' : (($var === $_FILES) ? '$_FILES' : (($var === $_REQUEST) ? '$_REQUEST' : (($var === $_SERVER) ? '$_SERVER' : (isset($_SESSION) && ($var === $_SESSION) ? '$_SESSION' : '')))))))) : $label; $c = count($var); if(isset($var['fw1recursionsentinel'])) { echo "(Recursion)"; } $aclass = (($c > 0) && array_key_exists(0, $var) && array_key_exists($c - 1, $var)) ? 'array' : 'struct'; $var['fw1recursionsentinel'] = true; echo "$tabs<table class=\"dump ${aclass} depth${depth}\">$tabs<thead><tr><th colspan=\"2\">" . ($label != '' ? $label . ' - ' : '') . "array" . ($c > 0 ? "" : " [empty]") . "</th></tr></thead>$tabs<tbody>"; foreach ($var as $index => $aval) { if ($index === 'fw1recursionsentinel') continue; echo "$tabs<tr><td class=\"key\">" . $he($index) . "</td><td class=\"value\"><div>"; self::dump($aval, $limit, '', $depth); echo "</div></td></tr>"; $printCount++; if (($limit > 0) && ($printCount >= $limit) && ($aclass === 'array')) break; } echo "$tabs</tbody>$tabs</table>"; // unset($var['fw1recursionsentinel']); } elseif (is_string($var)) { echo $var === '' ? '[EMPTY STRING]' : htmlentities($var); } elseif (is_bool($var)) { echo $var ? "TRUE" : "FALSE"; } elseif (is_callable($var) || (is_object($var) && is_subclass_of($var, 'ReflectionFunctionAbstract'))) { self::dumpFunction($var, $tabs, $limit, $label, $depth); } elseif (is_resource($var)) { echo "(Resource)"; } elseif (is_float($var)) { echo "(float) " . htmlentities($var); } elseif (is_int($var)) { echo "(int) " . htmlentities($var); } elseif (is_null($var)) { echo "NULL"; } elseif (is_object($var)) { $ref = new \ReflectionObject($var); $parent = $ref->getParentClass(); $interfaces = implode("<br/>implements ", $ref->getInterfaceNames()); $objHash = spl_object_hash($var); $refHash = 'r' . md5($ref); $objClassName = $ref->getName(); if ($objClassName === 'SimpleXMLElement') { echo "$tabs<table class=\"dump xml depth${depth}\">$tabs<thead>$tabs<tr><th colspan=\"2\">" . ($label != '' ? $label . ' - ' : '') . "xml element</th></tr>$tabs<tbody>"; self::trKeyValue('Name', $var->getName()); // echo "<tr><td class=\"key\">Name</td><td class=\"value\">" . htmlentities($var->getName()) . "</td></tr>\n"; $attribs = array(); foreach ($var->attributes() as $attribName => $attribValue) { $attribs[$attribName] = $attribValue; } if (count($attribs) > 0) { echo "$tabs<tr><td class=\"key\">Attributes</td><td class=\"values\"><div>$tabs<table class=\"dump xml attributes\"><tbody>"; foreach ($attribs as $attribName => $attribValue) { self::trKeyValue($attribName, $attribValue); } echo "$tabs</tbody></table>$tabs</div></td></tr>"; } $xmlText = trim((string) $var); if ($xmlText !== '') { self::trKeyValue('Text', $xmlText); } if ($var->count() > 0) { echo "$tabs<tr><td class=\"key\">Children</td><td class=\"values\"><div>$tabs<table class=\"dump xml children\"><tbody>"; $childNum = 0; foreach ($var->children() as $child) { echo "$tabs<tr><td class=\"key\">" . $childNum . "</td><td class=\"value child\"><div>"; self::dump($child, $limit, '', $depth + 1); echo "</div></td></tr>"; $childNum++; } echo "$tabs</tbody></table>$tabs</div></td></tr>"; } } else { echo "$tabs<table class=\"dump object depth${depth}\"" . (isset($seen[$refHash]) ? "" : "id=\"$refHash\"") . ">$tabs<thead>$tabs<tr><th colspan=\"2\">" . ($label != '' ? $label . ' - ' : '') . "object " . htmlentities($objClassName) . ($parent ? "<br/>extends " .$parent->getName() : "") . ($interfaces !== '' ? "<br/>implements " . $interfaces : "") . "</th></tr>$tabs<tbody>"; if (isset($seen[$objHash])) { echo "$tabs<tr><td colspan=\"2\"><a href=\"#$refHash\">[see above for details]</a></td></tr>"; } else { $seen[$objHash] = TRUE; $constants = $ref->getConstants(); if (count($constants) > 0) { echo "$tabs<tr><td class=\"key\">CONSTANTS</td><td class=\"values\"><div>$tabs<table class=\"dump object\">"; foreach ($constants as $constant => $cval) { echo "$tabs<tr><td class=\"key\">" . htmlentities($constant) . "</td><td class=\"value constant\"><div>"; self::dump($cval, $limit, '', $depth + 1); echo "</div></td></tr>"; } echo "$tabs</table>$tabs</div></td></tr>"; } $properties = $ref->getProperties(); if (count($properties) > 0) { echo "$tabs<tr><td class=\"key\">PROPERTIES</td><td class=\"values\"><div>$tabs<table class=\"dump object\">"; foreach ($properties as $property) { echo "$tabs<tr><td class=\"key\">" . htmlentities(implode(' ', \Reflection::getModifierNames($property->getModifiers()))) . " " . $he($property->getName()) . "</td><td class=\"value property\"><div>"; $wasHidden = $property->isPrivate() || $property->isProtected(); $property->setAccessible(TRUE); $propVal = $property->getValue($var); self::dump($propVal, $limit, '', $depth + 1); if ($wasHidden) { $property->setAccessible(FALSE); } echo "</div></td></tr>"; } echo "$tabs</table>$tabs</div></td></tr>"; } $methods = $ref->getMethods(); if (count($methods) > 0) { echo "$tabs<tr><td class=\"key\">METHODS</td><td class=\"values shh\"><div>"; if (isset($seen[$refHash])) { echo "<a href=\"#$refHash\">[see above for details]</a>"; } else { $seen[$refHash] = TRUE; echo "$tabs<table class=\"dump object\">"; foreach ($methods as $method) { echo "$tabs<tr><td class=\"key\">" . htmlentities($method->getName()) . "</td><td class=\"value function\"><div>"; self::dumpFunction($method, $tabs, $limit, '', $depth + 1); echo "</div></td></tr>"; } echo "$tabs</table>"; } echo "$tabs</div></td></tr>"; } } } echo "$tabs</tbody>$tabs</table>"; } elseif (is_numeric($var)) { echo htmlentities($var); } elseif (is_scalar($var)) { echo htmlentities($var); } else { echo gettype($var); } } // dump