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 $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:
95: $out .= static::highlightLine($source, $line, $lines);
96: $out = preg_replace_callback('#">\$(\w+)( )?</span>#', function($m) use ($vars) {
97: return isset($vars[$m[1]])
98: ? '" title="' . str_replace('"', '"', strip_tags(Dumper::toHtml($vars[$m[1]]))) . $m[0]
99: : $m[0];
100: }, $out);
101:
102: return "<pre class='php'><div>$out</div></pre>";
103: }
104:
105:
106:
107: 108: 109: 110:
111: public static function highlightLine($html, $line, $lines = 15)
112: {
113: $source = explode("\n", "\n" . str_replace("\r\n", "\n", $html));
114: $out = '';
115: $spans = 1;
116: $start = $i = max(1, $line - floor($lines * 2/3));
117: while (--$i >= 1) {
118: if (preg_match('#.*(</?span[^>]*>)#', $source[$i], $m)) {
119: if ($m[1] !== '</span>') {
120: $spans++;
121: $out .= $m[1];
122: }
123: break;
124: }
125: }
126:
127: $source = array_slice($source, $start, $lines, TRUE);
128: end($source);
129: $numWidth = strlen((string) key($source));
130:
131: foreach ($source as $n => $s) {
132: $spans += substr_count($s, '<span') - substr_count($s, '</span');
133: $s = str_replace(array("\r", "\n"), array('', ''), $s);
134: preg_match_all('#<[^>]+>#', $s, $tags);
135: if ($n == $line) {
136: $out .= sprintf(
137: "<span class='highlight'>%{$numWidth}s: %s\n</span>%s",
138: $n,
139: strip_tags($s),
140: implode('', $tags[0])
141: );
142: } else {
143: $out .= sprintf("<span class='line'>%{$numWidth}s:</span> %s\n", $n, $s);
144: }
145: }
146: $out .= str_repeat('</span>', $spans) . '</code>';
147: return $out;
148: }
149:
150:
151: 152: 153: 154: 155:
156: public function isCollapsed($file)
157: {
158: foreach ($this->collapsePaths as $path) {
159: if (strpos(strtr($file, '\\', '/'), strtr("$path/", '\\', '/')) === 0) {
160: return TRUE;
161: }
162: }
163: return FALSE;
164: }
165:
166: }
167: