PageRenderTime 57ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/Nette/Diagnostics/Helpers.php

http://github.com/nette/nette
PHP | 221 lines | 168 code | 25 blank | 28 comment | 26 complexity | 57e8a4856bafe55a0d30d4cd3ed87f4d MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * This file is part of the Nette Framework (http://nette.org)
  4. *
  5. * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  6. *
  7. * For the full copyright and license information, please view
  8. * the file license.txt that was distributed with this source code.
  9. */
  10. namespace Nette\Diagnostics;
  11. use Nette;
  12. /**
  13. * Rendering helpers for Debugger.
  14. *
  15. * @author David Grudl
  16. */
  17. final class Helpers
  18. {
  19. /**
  20. * Returns link to editor.
  21. * @return Nette\Utils\Html
  22. */
  23. public static function editorLink($file, $line)
  24. {
  25. if (Debugger::$editor && is_file($file)) {
  26. $dir = dirname(strtr($file, '/', DIRECTORY_SEPARATOR));
  27. $base = isset($_SERVER['SCRIPT_FILENAME']) ? dirname(dirname(strtr($_SERVER['SCRIPT_FILENAME'], '/', DIRECTORY_SEPARATOR))) : dirname($dir);
  28. if (substr($dir, 0, strlen($base)) === $base) {
  29. $dir = '...' . substr($dir, strlen($base));
  30. }
  31. return Nette\Utils\Html::el('a')
  32. ->href(strtr(Debugger::$editor, array('%file' => rawurlencode($file), '%line' => $line)))
  33. ->title("$file:$line")
  34. ->setHtml(htmlSpecialChars(rtrim($dir, DIRECTORY_SEPARATOR)) . DIRECTORY_SEPARATOR . '<b>' . htmlSpecialChars(basename($file)) . '</b>');
  35. } else {
  36. return Nette\Utils\Html::el('span')->setText($file);
  37. }
  38. }
  39. /**
  40. * Internal dump() implementation.
  41. * @param mixed variable to dump
  42. * @param int current recursion level
  43. * @return string
  44. */
  45. public static function htmlDump(&$var, $level = 0)
  46. {
  47. static $tableUtf, $tableBin, $reBinary = '#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u';
  48. if ($tableUtf === NULL) {
  49. foreach (range("\x00", "\xFF") as $ch) {
  50. if (ord($ch) < 32 && strpos("\r\n\t", $ch) === FALSE) {
  51. $tableUtf[$ch] = $tableBin[$ch] = '\\x' . str_pad(dechex(ord($ch)), 2, '0', STR_PAD_LEFT);
  52. } elseif (ord($ch) < 127) {
  53. $tableUtf[$ch] = $tableBin[$ch] = $ch;
  54. } else {
  55. $tableUtf[$ch] = $ch; $tableBin[$ch] = '\\x' . dechex(ord($ch));
  56. }
  57. }
  58. $tableBin["\\"] = '\\\\';
  59. $tableBin["\r"] = '\\r';
  60. $tableBin["\n"] = '\\n';
  61. $tableBin["\t"] = '\\t';
  62. $tableUtf['\\x'] = $tableBin['\\x'] = '\\\\x';
  63. }
  64. if (is_bool($var)) {
  65. return '<span class="php-bool">' . ($var ? 'TRUE' : 'FALSE') . "</span>\n";
  66. } elseif ($var === NULL) {
  67. return "<span class=\"php-null\">NULL</span>\n";
  68. } elseif (is_int($var)) {
  69. return "<span class=\"php-int\">$var</span>\n";
  70. } elseif (is_float($var)) {
  71. $var = var_export($var, TRUE);
  72. if (strpos($var, '.') === FALSE) {
  73. $var .= '.0';
  74. }
  75. return "<span class=\"php-float\">$var</span>\n";
  76. } elseif (is_string($var)) {
  77. if (Debugger::$maxLen && strlen($var) > Debugger::$maxLen) {
  78. $s = htmlSpecialChars(substr($var, 0, Debugger::$maxLen), ENT_NOQUOTES, 'ISO-8859-1') . ' ... ';
  79. } else {
  80. $s = htmlSpecialChars($var, ENT_NOQUOTES, 'ISO-8859-1');
  81. }
  82. $s = strtr($s, preg_match($reBinary, $s) || preg_last_error() ? $tableBin : $tableUtf);
  83. $len = strlen($var);
  84. return "<span class=\"php-string\">\"$s\"</span>" . ($len > 1 ? " ($len)" : "") . "\n";
  85. } elseif (is_array($var)) {
  86. $s = '<span class="php-array">array</span>(' . count($var) . ") ";
  87. $space = str_repeat($space1 = ' ', $level);
  88. $brackets = range(0, count($var) - 1) === array_keys($var) ? "[]" : "{}";
  89. static $marker;
  90. if ($marker === NULL) {
  91. $marker = uniqid("\x00", TRUE);
  92. }
  93. if (empty($var)) {
  94. } elseif (isset($var[$marker])) {
  95. $brackets = $var[$marker];
  96. $s .= "$brackets[0] *RECURSION* $brackets[1]";
  97. } elseif ($level < Debugger::$maxDepth || !Debugger::$maxDepth) {
  98. $s .= "<code>$brackets[0]\n";
  99. $var[$marker] = $brackets;
  100. foreach ($var as $k => &$v) {
  101. if ($k === $marker) {
  102. continue;
  103. }
  104. $k = strtr($k, preg_match($reBinary, $k) || preg_last_error() ? $tableBin : $tableUtf);
  105. $k = htmlSpecialChars(preg_match('#^\w+$#', $k) ? $k : "\"$k\"");
  106. $s .= "$space$space1<span class=\"php-key\">$k</span> => " . self::htmlDump($v, $level + 1);
  107. }
  108. unset($var[$marker]);
  109. $s .= "$space$brackets[1]</code>";
  110. } else {
  111. $s .= "$brackets[0] ... $brackets[1]";
  112. }
  113. return $s . "\n";
  114. } elseif (is_object($var)) {
  115. if ($var instanceof \Closure) {
  116. $rc = new \ReflectionFunction($var);
  117. $arr = array();
  118. foreach ($rc->getParameters() as $param) {
  119. $arr[] = '$' . $param->getName();
  120. }
  121. $arr = array('file' => $rc->getFileName(), 'line' => $rc->getStartLine(), 'parameters' => implode(', ', $arr));
  122. } else {
  123. $arr = (array) $var;
  124. }
  125. $s = '<span class="php-object">' . get_class($var) . "</span>(" . count($arr) . ") ";
  126. $space = str_repeat($space1 = ' ', $level);
  127. static $list = array();
  128. if (empty($arr)) {
  129. } elseif (in_array($var, $list, TRUE)) {
  130. $s .= "{ *RECURSION* }";
  131. } elseif ($level < Debugger::$maxDepth || !Debugger::$maxDepth || $var instanceof \Closure) {
  132. $s .= "<code>{\n";
  133. $list[] = $var;
  134. foreach ($arr as $k => &$v) {
  135. $m = '';
  136. if ($k[0] === "\x00") {
  137. $m = ' <span class="php-visibility">' . ($k[1] === '*' ? 'protected' : 'private') . '</span>';
  138. $k = substr($k, strrpos($k, "\x00") + 1);
  139. }
  140. $k = strtr($k, preg_match($reBinary, $k) || preg_last_error() ? $tableBin : $tableUtf);
  141. $k = htmlSpecialChars(preg_match('#^\w+$#', $k) ? $k : "\"$k\"");
  142. $s .= "$space$space1<span class=\"php-key\">$k</span>$m => " . self::htmlDump($v, $level + 1);
  143. }
  144. array_pop($list);
  145. $s .= "$space}</code>";
  146. } else {
  147. $s .= "{ ... }";
  148. }
  149. return $s . "\n";
  150. } elseif (is_resource($var)) {
  151. return '<span class="php-resource">' . htmlSpecialChars(get_resource_type($var)) . " resource</span>\n";
  152. } else {
  153. return "<span>unknown type</span>\n";
  154. }
  155. }
  156. /**
  157. * Dumps variable.
  158. * @param string
  159. * @return string
  160. */
  161. public static function clickableDump($dump, $collapsed = FALSE)
  162. {
  163. return '<pre class="nette-dump">' . preg_replace_callback(
  164. '#^( *)((?>[^(\r\n]{1,200}))\((\d+)\) <code>#m',
  165. function ($m) use ($collapsed) {
  166. return "$m[1]<a href='#' rel='next'>$m[2]($m[3]) "
  167. . (($m[1] || !$collapsed) && ($m[3] < 7)
  168. ? '<abbr>&#x25bc;</abbr> </a><code>'
  169. : '<abbr>&#x25ba;</abbr> </a><code class="nette-collapsed">');
  170. },
  171. self::htmlDump($dump)
  172. ) . '</pre>';
  173. }
  174. public static function findTrace(array $trace, $method, & $index = NULL)
  175. {
  176. $m = explode('::', $method);
  177. foreach ($trace as $i => $item) {
  178. if (isset($item['function']) && $item['function'] === end($m)
  179. && isset($item['class']) === isset($m[1])
  180. && (!isset($item['class']) || $item['class'] === $m[0] || is_subclass_of($item['class'], $m[0])))
  181. {
  182. $index = $i;
  183. return $item;
  184. }
  185. }
  186. }
  187. }