/** * Returns syntax highlighted source code. * @param string * @param int * @param int * @return string */ public static function highlightFile($file, $line, $lines = 15, array $vars = NULL) { $source = @file_get_contents($file); // intentionally @ if ($source) { $source = static::highlightPhp($source, $line, $lines, $vars); if ($editor = Helpers::editorUri($file, $line)) { $source = substr_replace($source, ' data-tracy-href="' . htmlspecialchars($editor, ENT_QUOTES, 'UTF-8') . '"', 4, 0); } return $source; } }
/** * @return mixed */ private static function toJson(&$var, $options, $level = 0) { if (is_bool($var) || is_null($var) || is_int($var)) { return $var; } elseif (is_float($var)) { return is_finite($var) ? strpos($tmp = json_encode($var), '.') ? $var : array('number' => "{$tmp}.0") : array('type' => (string) $var); } elseif (is_string($var)) { return self::encodeString($var, $options[self::TRUNCATE]); } elseif (is_array($var)) { static $marker; if ($marker === NULL) { $marker = uniqid("", TRUE); } if (isset($var[$marker]) || $level >= $options[self::DEPTH]) { return array(NULL); } $res = array(); $var[$marker] = TRUE; foreach ($var as $k => &$v) { if ($k !== $marker) { $k = preg_match('#^\\w{1,50}\\z#', $k) ? $k : '"' . self::encodeString($k, $options[self::TRUNCATE]) . '"'; $res[] = array($k, self::toJson($v, $options, $level + 1)); } } unset($var[$marker]); return $res; } elseif (is_object($var)) { $obj =& self::$liveStorage[spl_object_hash($var)]; if ($obj && $obj['level'] <= $level) { return array('object' => $obj['id']); } if ($options[self::LOCATION] & self::LOCATION_CLASS) { $rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var); $editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine()); } static $counter = 1; $obj = $obj ?: array('id' => self::$livePrefix . '0' . $counter++, 'name' => Helpers::getClass($var), 'editor' => empty($editor) ? NULL : array('file' => $rc->getFileName(), 'line' => $rc->getStartLine(), 'url' => $editor), 'level' => $level, 'object' => $var); if ($level < $options[self::DEPTH] || !$options[self::DEPTH]) { $obj['level'] = $level; $obj['items'] = array(); foreach (self::exportObject($var, $options[self::OBJECT_EXPORTERS]) as $k => $v) { $vis = 0; if (isset($k[0]) && $k[0] === "") { $vis = $k[1] === '*' ? 1 : 2; $k = substr($k, strrpos($k, "") + 1); } $k = preg_match('#^\\w{1,50}\\z#', $k) ? $k : '"' . self::encodeString($k, $options[self::TRUNCATE]) . '"'; $obj['items'][] = array($k, self::toJson($v, $options, $level + 1), $vis); } } return array('object' => $obj['id']); } elseif (is_resource($var)) { $obj =& self::$liveStorage[(string) $var]; if (!$obj) { $type = get_resource_type($var); $obj = array('id' => self::$livePrefix . (int) $var, 'name' => $type . ' resource'); if (isset(self::$resources[$type])) { foreach (call_user_func(self::$resources[$type], $var) as $k => $v) { $obj['items'][] = array($k, self::toJson($v, $options, $level + 1)); } } } return array('resource' => $obj['id']); } else { return array('type' => 'unknown type'); } }
private function renderListeners($ids) { static $addIcon; if (empty($addIcon)) { $addIcon = '<img width="18" height="18" src="data:image/png;base64,' . base64_encode(file_get_contents(__DIR__ . '/add.png')) . '" title="Listener" />'; } $registeredClasses = $this->getClassMap(); $h = 'htmlspecialchars'; $shortFilename = function (Nette\Reflection\GlobalFunction $refl) { $title = '.../' . basename($refl->getFileName()) . ':' . $refl->getStartLine(); if ($editor = Tracy\Helpers::editorUri($refl->getFileName(), $refl->getStartLine())) { return sprintf(' defined at <a href="%s">%s</a>', htmlspecialchars($editor), $title); } return ' defined at ' . $title; }; $s = ''; foreach ($ids as $id) { if (is_callable($id)) { $s .= '<tr><td width=18>' . $addIcon . '</td><td><pre class="nette-dump"><span class="nette-dump-object">' . Callback::toString($id) . ($id instanceof \Closure ? $shortFilename(Callback::toReflection($id)) : '') . '</span></span></th></tr>'; continue; } if (!$this->sl->isCreated($id) && ($class = array_search($id, $registeredClasses, TRUE))) { $s .= '<tr><td width=18>' . $addIcon . '</td><td><pre class="nette-dump"><span class="nette-dump-object">' . $h(Nette\Reflection\ClassType::from($class)->getName()) . '</span></span></th></tr>'; } else { try { $s .= '<tr><td width=18>' . $addIcon . '</td><td>' . self::dumpToHtml($this->sl->getService($id)) . '</th></tr>'; } catch (\Exception $e) { $s .= "<tr><td colspan=2>Service {$id} cannot be loaded because of exception<br><br>\n" . (string) $e . '</td></th>'; } } } return $s; }
private static function dumpObject(& $var, $options, $level) { if ($var instanceof \Closure) { $rc = new \ReflectionFunction($var); $fields = array(); foreach ($rc->getParameters() as $param) { $fields[] = '$' . $param->getName(); } $fields = array( 'file' => $rc->getFileName(), 'line' => $rc->getStartLine(), 'variables' => $rc->getStaticVariables(), 'parameters' => implode(', ', $fields) ); } elseif ($var instanceof \SplFileInfo) { $fields = array('path' => $var->getPathname()); } elseif ($var instanceof \SplObjectStorage) { $fields = array(); foreach (clone $var as $obj) { $fields[] = array('object' => $obj, 'data' => $var[$obj]); } } else { $fields = (array) $var; } static $list = array(); $rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var); $out = '<span class="tracy-dump-object"' . ($options[self::LOCATION] && ($editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine())) ? ' data-tracy-href="' . htmlspecialchars($editor) . '"' : '') . '>' . htmlspecialchars(Helpers::getClass($var)) . '</span> <span class="tracy-dump-hash">#' . substr(md5(spl_object_hash($var)), 0, 4) . '</span>'; if (empty($fields)) { return $out . "\n"; } elseif (in_array($var, $list, TRUE)) { return $out . " { <i>RECURSION</i> }\n"; } elseif (!$options[self::DEPTH] || $level < $options[self::DEPTH] || $var instanceof \Closure) { $collapsed = $level ? count($fields) >= $options[self::COLLAPSE_COUNT] : $options[self::COLLAPSE]; $out = '<span class="tracy-toggle' . ($collapsed ? ' tracy-collapsed' : '') . '">' . $out . "</span>\n<div" . ($collapsed ? ' class="tracy-collapsed"' : '') . '>'; $list[] = $var; foreach ($fields as $k => & $v) { $vis = ''; if ($k[0] === "\x00") { $vis = ' <span class="tracy-dump-visibility">' . ($k[1] === '*' ? 'protected' : 'private') . '</span>'; $k = substr($k, strrpos($k, "\x00") + 1); } $k = preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . htmlspecialchars(self::encodeString($k, $options[self::TRUNCATE]), ENT_NOQUOTES, 'UTF-8') . '"'; $out .= '<span class="tracy-dump-indent"> ' . str_repeat('| ', $level) . '</span>' . '<span class="tracy-dump-key">' . $k . "</span>$vis => " . self::dumpVar($v, $options, $level + 1); } array_pop($list); return $out . '</div>'; } else { return $out . " { ... }\n"; } }