1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Diagnostics;
9:
10: use Nette;
11:
12:
13: 14: 15: 16: 17:
18: class BlueScreen extends Nette\Object
19: {
20:
21: private $panels = array();
22:
23:
24: public $collapsePaths = array();
25:
26:
27: 28: 29: 30: 31:
32: public function addPanel($panel)
33: {
34: if (!in_array($panel, $this->panels, TRUE)) {
35: $this->panels[] = $panel;
36: }
37: return $this;
38: }
39:
40:
41: 42: 43: 44: 45:
46: public function render($exception)
47: {
48: $panels = $this->panels;
49: require __DIR__ . '/templates/bluescreen.phtml';
50: }
51:
52:
53: 54: 55: 56: 57: 58: 59:
60: public static function highlightFile($file, $line, $lines = 15, $vars = array())
61: {
62: $source = @file_get_contents($file);
63: if ($source) {
64: return substr_replace(
65: static::highlightPhp($source, $line, $lines, $vars),
66: ' data-nette-href="' . htmlspecialchars(strtr(Debugger::$editor, array('%file' => rawurlencode($file), '%line' => $line))) . '"',
67: 4, 0
68: );
69: }
70: }
71:
72:
73: 74: 75: 76: 77: 78: 79:
80: public static function highlightPhp($source, $line, $lines = 15, $vars = array())
81: {
82: if (function_exists('ini_set')) {
83: ini_set('highlight.comment', '#998; font-style: italic');
84: ini_set('highlight.default', '#000');
85: ini_set('highlight.html', '#06B');
86: ini_set('highlight.keyword', '#D24; font-weight: bold');
87: ini_set('highlight.string', '#080');
88: }
89:
90: $source = str_replace(array("\r\n", "\r"), "\n", $source);
91: $source = explode("\n", highlight_string($source, TRUE));
92: $out = $source[0];
93: $source = str_replace('<br />', "\n", $source[1]);
94: $out .= static::highlightLine($source, $line, $lines);
95:
96: if ($vars) {
97: $out = preg_replace_callback('#">\$(\w+)( )?</span>#', function ($m) use ($vars) {
98: return array_key_exists($m[1], $vars)
99: ? '" title="' . str_replace('"', '"', trim(strip_tags(Dumper::toHtml($vars[$m[1]])))) . $m[0]
100: : $m[0];
101: }, $out);
102: }
103:
104: return "<pre class='php'><div>$out</div></pre>";
105: }
106:
107:
108:
109: 110: 111: 112:
113: public static function highlightLine($html, $line, $lines = 15)
114: {
115: $source = explode("\n", "\n" . str_replace("\r\n", "\n", $html));
116: $out = '';
117: $spans = 1;
118: $start = $i = max(1, $line - floor($lines * 2/3));
119: while (--$i >= 1) {
120: if (preg_match('#.*(</?span[^>]*>)#', $source[$i], $m)) {
121: if ($m[1] !== '</span>') {
122: $spans++;
123: $out .= $m[1];
124: }
125: break;
126: }
127: }
128:
129: $source = array_slice($source, $start, $lines, TRUE);
130: end($source);
131: $numWidth = strlen((string) key($source));
132:
133: foreach ($source as $n => $s) {
134: $spans += substr_count($s, '<span') - substr_count($s, '</span');
135: $s = str_replace(array("\r", "\n"), array('', ''), $s);
136: preg_match_all('#<[^>]+>#', $s, $tags);
137: if ($n == $line) {
138: $out .= sprintf(
139: "<span class='highlight'>%{$numWidth}s: %s\n</span>%s",
140: $n,
141: strip_tags($s),
142: implode('', $tags[0])
143: );
144: } else {
145: $out .= sprintf("<span class='line'>%{$numWidth}s:</span> %s\n", $n, $s);
146: }
147: }
148: $out .= str_repeat('</span>', $spans) . '</code>';
149: return $out;
150: }
151:
152:
153: 154: 155: 156: 157:
158: public function isCollapsed($file)
159: {
160: foreach ($this->collapsePaths as $path) {
161: if (strpos(strtr($file, '\\', '/'), strtr("$path/", '\\', '/')) === 0) {
162: return TRUE;
163: }
164: }
165: return FALSE;
166: }
167:
168: }
169: