/** * Helper for Kohana::dump(), handles recursion in arrays and objects. * * @param mixed variable to dump * @param integer maximum length of strings * @param integer recursion level (internal) * @return string */ protected static function _dump(&$var, $length = 128, $level = 0) { if ($var === NULL) { return '<small>NULL</small>'; } elseif (is_bool($var)) { return '<small>bool</small> ' . ($var ? 'TRUE' : 'FALSE'); } elseif (is_float($var)) { return '<small>float</small> ' . $var; } elseif (is_resource($var)) { if (($type = get_resource_type($var)) === 'stream' and $meta = stream_get_meta_data($var)) { $meta = stream_get_meta_data($var); if (isset($meta['uri'])) { $file = $meta['uri']; if (function_exists('stream_is_local')) { // Only exists on PHP >= 5.2.4 if (stream_is_local($file)) { $file = Core::debug_path($file); } } return '<small>resource</small><span>(' . $type . ')</span> ' . htmlspecialchars($file, ENT_NOQUOTES, Core::$charset); } } else { return '<small>resource</small><span>(' . $type . ')</span>'; } } elseif (is_string($var)) { // Clean invalid multibyte characters. iconv is only invoked // if there are non ASCII characters in the string, so this // isn't too much of a hit. $var = UTF8::clean($var); if (UTF8::strlen($var) > $length) { // Encode the truncated string $str = htmlspecialchars(UTF8::substr($var, 0, $length), ENT_NOQUOTES, Core::$charset) . ' …'; } else { // Encode the string $str = htmlspecialchars($var, ENT_NOQUOTES, Core::$charset); } return '<small>string</small><span>(' . strlen($var) . ')</span> "' . $str . '"'; } elseif (is_array($var)) { $output = array(); // Indentation for this variable $space = str_repeat($s = ' ', $level); static $marker = null; if ($marker === null) { // Make a unique marker $marker = uniqid(""); } if (empty($var)) { // Do nothing } elseif (isset($var[$marker])) { $output[] = "(\n{$space}{$s}*RECURSION*\n{$space})"; } elseif ($level < 5) { $output[] = "<span>("; $var[$marker] = TRUE; foreach ($var as $key => &$val) { if ($key === $marker) { continue; } if (!is_int($key)) { $key = '"' . htmlspecialchars($key, ENT_NOQUOTES, Core::$charset) . '"'; } $output[] = "{$space}{$s}{$key} => " . Docs::_dump($val, $length, $level + 1); } unset($var[$marker]); $output[] = "{$space})</span>"; } else { // Depth too great $output[] = "(\n{$space}{$s}...\n{$space})"; } return '<small>array</small><span>(' . count($var) . ')</span> ' . implode("\n", $output); } elseif (is_object($var)) { // Copy the object as an array $array = (array) $var; $output = array(); // Indentation for this variable $space = str_repeat($s = ' ', $level); $hash = spl_object_hash($var); // Objects that are being dumped static $objects = array(); if (empty($var)) { // Do nothing } elseif (isset($objects[$hash])) { $output[] = "{\n{$space}{$s}*RECURSION*\n{$space}}"; } elseif ($level < 10) { $output[] = "<code>{"; $objects[$hash] = TRUE; foreach ($array as $key => &$val) { if ($key[0] === "") { // Determine if the access is protected or protected $access = '<small>' . ($key[1] === '*' ? 'protected' : 'private') . '</small>'; // Remove the access level from the variable name $key = substr($key, strrpos($key, "") + 1); } else { $access = '<small>public</small>'; } $output[] = "{$space}{$s}{$access} {$key} => " . Docs::_dump($val, $length, $level + 1); } unset($objects[$hash]); $output[] = "{$space}}</code>"; } else { // Depth too great $output[] = "{\n{$space}{$s}...\n{$space}}"; } return '<small>object</small> <span>' . get_class($var) . '(' . count($array) . ')</span> ' . implode("\n", $output); } else { return '<small>' . gettype($var) . '</small> ' . htmlspecialchars(print_r($var, TRUE), ENT_NOQUOTES, Core::$charset); } }