public static function decorateTrace($traceData) { $output = ''; foreach ($traceData as $i => $step) { $output .= $i + 1 . ': '; if (isset($step['file'])) { $output .= self::_buildCalleeString($step); } else { $output .= 'PHP internal call'; } $output .= ' ' . $step['function']; if (isset($step['args'])) { $output .= '(' . implode(', ', array_keys($step['args'])) . ')'; } $output .= "\n"; if (!empty($step['object'])) { $calleeDump = kintParser::factory($step['object']); $output .= "## Callee object ##\n"; $output .= self::decorate($calleeDump, 1); } if (!empty($step['args'])) { $output .= "## Arguments ##\n"; foreach ($step['args'] as $k => $arg) { kintParser::reset(); $output .= self::decorate(kintParser::factory($arg, $k), 1); } } } return $output; }
protected function _parse(&$variable) { if (!is_object($variable) || !$variable instanceof Traversable) { return false; } $arrayCopy = iterator_to_array($variable, true); $this->value = kintParser::factory($arrayCopy)->extendedValue; $this->type = 'Iterator contents'; $this->size = count($arrayCopy); }
protected function _parse(&$variable) { try { if (!is_string($variable) || substr($variable, 0, 5) !== '<?xml' || ($xml = simplexml_load_string($variable)) === null) { return false; } } catch (Exception $e) { return false; } $this->value = kintParser::factory($xml)->extendedValue; $this->type = 'XML'; }
protected function _parse(&$variable) { if (!is_string($variable) || !isset($variable[0]) || $variable[0] !== '{' && $variable[0] !== '[' || ($json = json_decode($variable)) === null) { return false; } $val = (array) $json; if (empty($val)) { return false; } $this->value = kintParser::factory($val)->extendedValue; $this->type = 'JSON'; }
protected function _parse(&$variable) { if (!KINT_PHP53 || !is_object($variable) || !$variable instanceof Traversable || stripos(get_class($variable), 'zend') !== false) { return false; } $arrayCopy = iterator_to_array($variable, true); if ($arrayCopy === false) { return false; } $this->value = kintParser::factory($arrayCopy)->extendedValue; $this->type = 'Iterator contents'; $this->size = count($arrayCopy); }
protected function _parse(&$variable) { if (!is_object($variable) || get_class($variable) !== 'SplObjectStorage') { return false; } /** @var $variable SplObjectStorage */ $variable->rewind(); while ($variable->valid()) { $current = $variable->current(); $this->value[] = kintParser::factory($current); $variable->next(); } $this->type = 'Storage contents'; $this->size = $variable->count(); }
protected function _parse(&$variable) { if (!is_object($variable) || !$variable instanceof SplObjectStorage) { return false; } /** @var $variable SplObjectStorage */ $count = $variable->count(); if ($count === 0) { return false; } $variable->rewind(); while ($variable->valid()) { $current = $variable->current(); $this->value[] = kintParser::factory($current); $variable->next(); } $this->type = 'Storage contents'; $this->size = $count; }
protected function _parse(&$variable) { try { if (is_string($variable) && substr($variable, 0, 5) === '<?xml') { $e = libxml_use_internal_errors(true); $xml = simplexml_load_string($variable); libxml_use_internal_errors($e); if (empty($xml)) { return false; } } else { return false; } } catch (Exception $e) { return false; } $this->value = kintParser::factory($xml)->extendedValue; $this->type = 'XML'; }
protected function _parse(&$variable) { if (!is_object($variable)) { return false; } $extendedValue = array(); $reflection = new \ReflectionClass($variable); // first show static values foreach ($reflection->getProperties(\ReflectionProperty::IS_STATIC) as $property) { if ($property->isPrivate()) { if (!method_exists($property, 'setAccessible')) { break; } $property->setAccessible(true); $access = "private"; } elseif ($property->isProtected()) { $property->setAccessible(true); $access = "protected"; } else { $access = 'public'; } if (Kint::$keyFilterCallback && call_user_func(Kint::$keyFilterCallback, $property->getName(), $property->getValue()) === false) { continue; } $_ = $property->getValue(); $output = kintParser::factory($_, '$' . $property->getName()); $output->access = $access; $output->operator = '::'; $extendedValue[] = $output; } foreach ($reflection->getConstants() as $constant => $val) { $output = kintParser::factory($val, $constant); $output->access = 'constant'; $output->operator = '::'; $extendedValue[] = $output; } if (empty($extendedValue)) { return false; } $this->value = $extendedValue; $this->type = 'Static class properties'; $this->size = count($extendedValue); }
protected function _parse(&$variable) { if (!is_object($variable)) { return false; } $reflection = new ReflectionClass($variable); $parentClass = $reflection->getParentClass(); if ($parentClass !== false && $parentClass->name === 'ArrayObject') { $arrayCopy = $variable->getArrayCopy(); foreach ($arrayCopy as $k => $var) { $t = kintParser::factory($var); $t->name = "'{$k}'"; $t->operator = '=>'; $this->value[] = $t; } $this->type = 'ArrayObject contents'; $this->size = count($arrayCopy); } else { return false; } }
private static function _parse_object(&$variable, kintVariableData $variableData) { if (function_exists('spl_object_hash')) { $hash = spl_object_hash($variable); } else { ob_start(); var_dump($variable); preg_match('[#(\\d+)]', ob_get_clean(), $match); $hash = $match[1]; } $castedArray = (array) $variable; $variableData->type = 'object'; $variableData->subtype = get_class($variable); $variableData->size = count($castedArray); if (isset(self::$_objects[$hash])) { $variableData->value = '*RECURSION*'; return false; } if (self::_checkDepth()) { $variableData->extendedValue = "*DEPTH TOO GREAT*"; return false; } # ArrayObject (and maybe ArrayIterator, did not try yet) unsurprisingly consist of mainly dark magic. # What bothers me most, var_dump sees no problem with it, and ArrayObject also uses a custom, # undocumented serialize function, so you can see the properties in internal functions, but # can never iterate some of them if the flags are not STD_PROP_LIST. Fun stuff. if ($variableData->subtype === 'ArrayObject' || is_subclass_of($variable, 'ArrayObject')) { $arrayObjectFlags = $variable->getFlags(); $variable->setFlags(ArrayObject::STD_PROP_LIST); } self::$_objects[$hash] = true; // todo store reflectorObject here for alternatives cache $reflector = new \ReflectionObject($variable); if (Kint::$mode !== 'cli' && Kint::$mode !== 'whitespace' && Kint::$fileLinkFormat && $reflector->isUserDefined()) { list($url) = Kint::shortenPath($reflector->getFileName(), $reflector->getStartLine(), false); $_ = strpos($url, 'http://') === 0 ? 'class="kint-ide-link" ' : ''; $variableData->subtype = "<a {$_}href=\"{$url}\">{$variableData->subtype}</a>"; } $variableData->size = 0; $extendedValue = array(); $encountered = array(); # copy the object as an array as it provides more info than Reflection (depends) foreach ($castedArray as $key => $value) { if (Kint::$keyFilterCallback && call_user_func_array(Kint::$keyFilterCallback, array($key, $value)) === false) { continue; } /* casting object to array: * integer properties are inaccessible; * private variables have the class name prepended to the variable name; * protected variables have a '*' prepended to the variable name. * These prepended values have null bytes on either side. * http://www.php.net/manual/en/language.types.array.php#language.types.array.casting */ if ($key[0] === "") { $access = $key[1] === "*" ? "protected" : "private"; // Remove the access level from the variable name $key = substr($key, strrpos($key, "") + 1); } else { $access = "public"; } $encountered[$key] = true; $output = kintParser::factory($value, self::_escape($key)); $output->access = $access; $output->operator = '->'; $extendedValue[] = $output; $variableData->size++; } foreach ($reflector->getProperties() as $property) { $name = $property->name; if ($property->isStatic() || isset($encountered[$name])) { continue; } if ($property->isProtected()) { $property->setAccessible(true); $access = "protected"; } elseif ($property->isPrivate()) { $property->setAccessible(true); $access = "private"; } else { $access = "public"; } $value = $property->getValue($variable); if (Kint::$keyFilterCallback && call_user_func_array(Kint::$keyFilterCallback, array($name, $value)) === false) { continue; } $output = kintParser::factory($value, self::_escape($name)); $output->access = $access; $output->operator = '->'; $extendedValue[] = $output; $variableData->size++; } if (isset($arrayObjectFlags)) { $variable->setFlags($arrayObjectFlags); } if ($variableData->size) { $variableData->extendedValue = $extendedValue; } }
public static function decorateTrace($traceData) { $output = '<dl class="kint-trace">'; foreach ($traceData as $i => $step) { $class = 'kint-parent'; if (Kint::$expandedByDefault) { $class .= ' kint-show'; } $output .= '<dt class="' . $class . '">' . '<b>' . ($i + 1) . '</b> ' . '<nav></nav>' . '<var>'; if (isset($step['file'])) { $output .= Kint::shortenPath($step['file'], $step['line']); } else { $output .= 'PHP internal call'; } $output .= '</var>'; $output .= $step['function']; if (isset($step['args'])) { $output .= '(' . implode(', ', array_keys($step['args'])) . ')'; } $output .= '</dt><dd>'; $firstTab = ' class="kint-active-tab"'; $output .= '<ul class="kint-tabs">'; if (!empty($step['source'])) { $output .= "<li{$firstTab}>Source</li>"; $firstTab = ''; } if (!empty($step['args'])) { $output .= "<li{$firstTab}>Arguments</li>"; $firstTab = ''; } if (!empty($step['object'])) { kintParser::reset(); $calleeDump = kintParser::factory($step['object']); $output .= "<li{$firstTab}>Callee object [{$calleeDump->subtype}]</li>"; } $output .= '</ul><ul>'; if (!empty($step['source'])) { $output .= "<li><pre class=\"kint-source\">{$step['source']}</pre></li>"; } if (!empty($step['args'])) { $output .= "<li>"; foreach ($step['args'] as $k => $arg) { kintParser::reset(); $output .= self::decorate(kintParser::factory($arg, $k)); } $output .= "</li>"; } if (!empty($step['object'])) { $output .= "<li>" . self::decorate($calleeDump) . "</li>"; } $output .= '</ul></dd>'; } $output .= '</dl>'; return $output; }
protected static function _dump($var, $name = '') { kintParser::reset(); return Kint_Decorators_Rich::decorate(kintParser::factory($var, $name)); }
private static function _parse_object(&$variable, kintVariableData $variableData) { // copy the object as an array $array = (array) $variable; $hash = spl_object_hash($variable); $variableData->type = 'object'; $variableData->subtype = get_class($variable); $variableData->size = count($array); if (isset(self::$_objects[$hash])) { $variableData->value = '*RECURSION*'; return false; } if (self::_checkDepth()) { $variableData->extendedValue = "*DEPTH TOO GREAT*"; return false; } self::$_objects[$hash] = true; if (empty($array)) { return; } $extendedValue = array(); foreach ($array as $key => &$value) { if (Kint::$keyFilterCallback && call_user_func_array(Kint::$keyFilterCallback, array($key, $value)) === false) { continue; } /* casting object to array: * integer properties are inaccessible; * private variables have the class name prepended to the variable name; * protected variables have a '*' prepended to the variable name. * These prepended values have null bytes on either side. * http://www.php.net/manual/en/language.types.array.php#language.types.array.casting */ if ($key[0] === "") { $access = $key[1] === "*" ? "protected" : "private"; // Remove the access level from the variable name $key = substr($key, strrpos($key, "") + 1); } else { $access = "public"; } $key = self::_escape($key); $output = kintParser::factory($value, $key); $output->access = $access; $output->operator = '->'; $extendedValue[] = $output; } $variableData->extendedValue = $extendedValue; }
/** * Dump information about variables, accepts any number of parameters, supports modifiers: * * clean up any output before kint and place the dump at the top of page: * - Kint::dump() * ***** * expand all nodes on display: * ! Kint::dump() * ***** * dump variables disregarding their depth: * + Kint::dump() * ***** * return output instead of displaying it (also disables ajax/cli detection): * @ Kint::dump() * ***** * disable ajax and cli auto-detection and just output as requested (plain/rich): * ~ Kint::dump() * * Modifiers are supported by all dump wrapper functions, including Kint::trace(). Space is optional. * * * You can also use the following shorthand to display debug_backtrace(): * Kint::dump( 1 ); * * Passing the result from debug_backtrace() to kint::dump() as a single parameter will display it as trace too: * $trace = debug_backtrace( true ); * Kint::dump( $trace ); * Or simply: * Kint::dump( debug_backtrace() ); * * * @param mixed $data * * @return void|string */ public static function dump($data = null) { if (!Kint::enabled()) { return ''; } # find caller information list($names, $modifiers, $callee, $previousCaller, $miniTrace) = self::_getPassedNames(defined('DEBUG_BACKTRACE_IGNORE_ARGS') ? debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) : debug_backtrace()); # process modifiers: @, +, !, ~ and - if (strpos($modifiers, '-') !== false) { self::$_firstRun = true; while (ob_get_level()) { ob_end_clean(); } } if (strpos($modifiers, '!') !== false) { $expandedByDefaultOldValue = self::$expandedByDefault; self::$expandedByDefault = true; } if (strpos($modifiers, '+') !== false) { $maxLevelsOldValue = self::$maxLevels; self::$maxLevels = false; } if (strpos($modifiers, '@') !== false) { $firstRunOldValue = self::$_firstRun; self::$_firstRun = true; } # disable mode detection if (strpos($modifiers, '@') !== false || strpos($modifiers, '~') === false) { $modeOldValue = self::$mode; $isAjaxOldValue = self::$_isAjax; if (self::$_detected === 'ajax') { self::$_isAjax = true; } elseif (self::$_detected === 'cli' && self::$cliDetection) { # cli detection is checked here as you can toggle the feature for individual dumps self::$mode = self::$cliColors ? 'cli' : 'whitespace'; } } $decoratorsMap = array('cli' => 'Kint_Decorators_Cli', 'plain' => 'Kint_Decorators_Plain', 'rich' => 'Kint_Decorators_Rich', 'whitespace' => 'Kint_Decorators_Whitespace'); $decorator = $decoratorsMap[self::$mode]; $output = $decorator::wrapStart($callee); $trace = false; if ($names === array(null) && func_num_args() === 1 && $data === 1) { $trace = debug_backtrace(true); # Kint::dump(1) shorthand } elseif (func_num_args() === 1 && is_array($data)) { $trace = $data; # test if the single parameter is result of debug_backtrace() } $trace and $trace = self::_parseTrace($trace); if ($trace) { $output .= $decorator::decorateTrace($trace); } else { $data = func_num_args() === 0 ? array("[[no arguments passed]]") : func_get_args(); foreach ($data as $k => $argument) { kintParser::reset(); $output .= $decorator::decorate(kintParser::factory($argument, $names[$k])); } } $output .= $decorator::wrapEnd($callee, $miniTrace, $previousCaller); if (strpos($modifiers, '~') === false) { self::$mode = $modeOldValue; } if (strpos($modifiers, '!') !== false) { self::$expandedByDefault = $expandedByDefaultOldValue; } if (strpos($modifiers, '+') !== false) { self::$maxLevels = $maxLevelsOldValue; } if (strpos($modifiers, '@') !== false) { self::$_firstRun = $firstRunOldValue; return $output; } if (self::$_isAjax) { $data = rawurlencode($output); $chunks = array(); while (strlen($data) > 4096) { $chunks[] = substr($data, 0, 4096); $data = substr($data, 4096); } $chunks[] = $data; for ($i = 0, $c = count($chunks); $i < $c; $i++) { $index = self::$_headerNo++; $name = 'kint' . ($index > 0 ? "-{$index}" : ''); header("{$name}: {$chunks[$i]}"); } if (strpos($modifiers, '~') === false) { self::$_isAjax = $isAjaxOldValue; } return ''; } echo $output; return ''; }
private static function _drawHeader(kintVariableData $kintVar) { $output = ''; if ($kintVar->access) { $output .= ' ' . $kintVar->access; } if ($kintVar->name !== null && $kintVar->name !== '') { $output .= ' ' . kintParser::escape($kintVar->name); } if ($kintVar->operator) { $output .= ' ' . $kintVar->operator; } $output .= ' ' . self::_colorize($kintVar->type, 'type', false); if ($kintVar->size !== null) { $output .= ' (' . $kintVar->size . ')'; } if ($kintVar->value !== null && $kintVar->value !== '') { $output .= ' ' . self::_colorize($kintVar->value, 'value', false); } return ltrim($output); }
/** * Dump information about variables, accepts any number of parameters, supports modifiers: * * clean up any output before kint and place the dump at the top of page: * - Kint::dump() * ***** * expand all nodes on display: * ! Kint::dump() * ***** * dump variables disregarding their depth: * + Kint::dump() * ***** * return output instead of displaying it: * @ Kint::dump() * ***** * force output as plain text * ~ Kint::dump() * * Modifiers are supported by all dump wrapper functions, including Kint::trace(). Space is optional. * * * You can also use the following shorthand to display debug_backtrace(): * Kint::dump( 1 ); * * Passing the result from debug_backtrace() to kint::dump() as a single parameter will display it as trace too: * $trace = debug_backtrace( true ); * Kint::dump( $trace ); * Or simply: * Kint::dump( debug_backtrace() ); * * * @param mixed $data * * @return void|string */ public static function dump($data = null) { if (!self::enabled()) { return ''; } list($names, $modifiers, $callee, $previousCaller, $miniTrace) = self::_getCalleeInfo(defined('DEBUG_BACKTRACE_IGNORE_ARGS') ? debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) : debug_backtrace()); $modeOldValue = self::enabled(); # process modifiers: @, +, !, ~ and - if (strpos($modifiers, '-') !== false) { self::$_firstRun = true; while (ob_get_level()) { ob_end_clean(); } } if (strpos($modifiers, '!') !== false) { $expandedByDefaultOldValue = self::$expandedByDefault; self::$expandedByDefault = true; } if (strpos($modifiers, '+') !== false) { $maxLevelsOldValue = self::$maxLevels; self::$maxLevels = false; } if (strpos($modifiers, '@') !== false) { $returnOldValue = self::$returnOutput; $firstRunOldValue = self::$_firstRun; self::$returnOutput = true; self::$_firstRun = true; } if (strpos($modifiers, '~') !== false) { self::enabled(self::MODE_WHITESPACE); } # set mode for current run $mode = self::enabled(); if ($mode === true) { $mode = PHP_SAPI === 'cli' ? self::MODE_CLI : self::MODE_RICH; } self::enabled($mode); /** @var Kint_Decorators_Rich|Kint_Decorators_Plain $decorator */ $decorator = self::enabled() === self::MODE_RICH ? 'Kint_Decorators_Rich' : 'Kint_Decorators_Plain'; $output = ''; if (self::$_firstRun) { $output .= $decorator::init(); } $trace = false; if ($names === array(null) && func_num_args() === 1 && $data === 1) { $trace = debug_backtrace(true); # Kint::dump(1) shorthand } elseif (func_num_args() === 1 && is_array($data)) { $trace = $data; # test if the single parameter is result of debug_backtrace() } $trace and $trace = self::_parseTrace($trace); $output .= $decorator::wrapStart(); if ($trace) { $output .= $decorator::decorateTrace($trace); } else { $data = func_num_args() === 0 ? array("[[no arguments passed]]") : func_get_args(); foreach ($data as $k => $argument) { kintParser::reset(); $output .= $decorator::decorate(kintParser::factory($argument, $names[$k])); } } $output .= $decorator::wrapEnd($callee, $miniTrace, $previousCaller); self::enabled($modeOldValue); if (strpos($modifiers, '~') === false) { self::enabled($modeOldValue); } if (strpos($modifiers, '!') !== false) { self::$expandedByDefault = $expandedByDefaultOldValue; } if (strpos($modifiers, '+') !== false) { self::$maxLevels = $maxLevelsOldValue; } if (strpos($modifiers, '@') !== false) { self::$returnOutput = $returnOldValue; self::$_firstRun = $firstRunOldValue; return $output; } if (self::$returnOutput) { return $output; } echo $output; return ''; }
private static function _drawHeader(kintVariableData $kintVar, $verbose = true) { $output = ''; if ($verbose) { if ($kintVar->access !== null) { $output .= "<var>" . $kintVar->access . "</var> "; } if ($kintVar->name !== null && $kintVar->name !== '') { $output .= "<dfn>" . kintParser::escape($kintVar->name) . "</dfn> "; } if ($kintVar->operator !== null) { $output .= $kintVar->operator . " "; } } if ($kintVar->type !== null) { if ($verbose) { $output .= "<var>"; } $output .= $kintVar->type; if ($verbose) { $output .= "</var>"; } else { $output .= " "; } } if ($kintVar->size !== null) { $output .= "(" . $kintVar->size . ") "; } return $output; }
public static function dump($data = null) { if (!self::enabled()) { return ''; } list($names, $modifiers, $callee, $previousCaller, $miniTrace) = self::_getCalleeInfo(defined('DEBUG_BACKTRACE_IGNORE_ARGS') ? debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) : debug_backtrace()); $modeOldValue = self::enabled(); $firstRunOldValue = self::$_firstRun; # process modifiers: @, +, !, ~ and - if (strpos($modifiers, '-') !== false) { self::$_firstRun = true; while (ob_get_level()) { ob_end_clean(); } } if (strpos($modifiers, '!') !== false) { $expandedByDefaultOldValue = self::$expandedByDefault; self::$expandedByDefault = true; } if (strpos($modifiers, '+') !== false) { $maxLevelsOldValue = self::$maxLevels; self::$maxLevels = false; } if (strpos($modifiers, '@') !== false) { $returnOldValue = self::$returnOutput; self::$returnOutput = true; self::$_firstRun = true; } if (strpos($modifiers, '~') !== false) { self::enabled(self::MODE_WHITESPACE); } # set mode for current run $mode = self::enabled(); if ($mode === true) { $mode = PHP_SAPI === 'cli' ? self::MODE_CLI : self::MODE_RICH; } self::enabled($mode); $decorator = self::enabled() === self::MODE_RICH ? 'Kint_Decorators_Rich' : 'Kint_Decorators_Plain'; $output = ''; if (self::$_firstRun) { $output .= call_user_func(array($decorator, 'init')); } $trace = false; if ($names === array(null) && func_num_args() === 1 && $data === 1) { # Kint::dump(1) shorthand $trace = KINT_PHP53 ? debug_backtrace(true) : debug_backtrace(); } elseif (func_num_args() === 1 && is_array($data)) { $trace = $data; # test if the single parameter is result of debug_backtrace() } $trace and $trace = self::_parseTrace($trace); $output .= call_user_func(array($decorator, 'wrapStart')); if ($trace) { $output .= call_user_func(array($decorator, 'decorateTrace'), $trace); } else { $data = func_num_args() === 0 ? array("[[no arguments passed]]") : func_get_args(); foreach ($data as $k => $argument) { kintParser::reset(); # when the dump arguments take long to generate output, user might have changed the file and # Kint might not parse the arguments correctly, so check if names are set and while the # displayed names might be wrong, at least don't throw an error $output .= call_user_func(array($decorator, 'decorate'), kintParser::factory($argument, isset($names[$k]) ? $names[$k] : '')); } } $output .= call_user_func(array($decorator, 'wrapEnd'), $callee, $miniTrace, $previousCaller); self::enabled($modeOldValue); self::$_firstRun = false; if (strpos($modifiers, '~') !== false) { self::$_firstRun = $firstRunOldValue; } else { self::enabled($modeOldValue); } if (strpos($modifiers, '!') !== false) { self::$expandedByDefault = $expandedByDefaultOldValue; } if (strpos($modifiers, '+') !== false) { self::$maxLevels = $maxLevelsOldValue; } if (strpos($modifiers, '@') !== false) { self::$returnOutput = $returnOldValue; self::$_firstRun = $firstRunOldValue; return $output; } if (self::$returnOutput) { return $output; } echo $output; }