Adding extra charsets for ActionMailer unit tests, if you're looking to parse incomin...
[akelos.git] / lib / AkDevelopmentErrorHandler.php
blob9d56c93822843eab8723f0908234178ca7ea8a56
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4 // +----------------------------------------------------------------------+
5 // | Akelos Framework - http://www.akelos.org |
6 // +----------------------------------------------------------------------+
7 // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez |
8 // | Released under the GNU Lesser General Public License, see LICENSE.txt|
9 // +----------------------------------------------------------------------+
11 /**
12 * @author Cezary Tomczak
13 * @author Bermi Ferrer <bermi a.t akelos c.om>
14 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
15 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
16 * @package ActiveSupport
17 * @subpackage Experimental
20 /**
21 * @todo This is a temporary Debug Library. File highlighting is really dangerous.
22 * Functionality provided by this class is only enabled on "development" environments
26 /**
27 * @version 2.0.1
28 * @license BSD
29 * @copyright (c) 2003,2004 Cezary Tomczak
30 * @link http://gosu.pl/software/mygosulib.html
33 if(defined('AK_DEBUG') && AK_DEBUG){
35 class AkDevelopmentErrorHandler {
37 /**
38 * Constructor
39 * @access public
41 function AkDevelopmentErrorHandler()
43 if(AK_DEBUG == 0){
44 return false;
46 if(isset($_GET['ak_debug_show_source'])){
47 $file = @$_GET['ak_debug_file'];
48 $line = @$_GET['ak_debug_line'];
49 $prev = @$_GET['ak_debug_prev'] ? $_GET['ak_debug_prev'] : 10;
50 $next = @$_GET['ak_debug_next'] ? $_GET['ak_debug_next'] : 10;
51 $this->showSource($file, $line, $prev, $next);
52 exit;
54 ini_set('docref_root', null);
55 ini_set('docref_ext', null);
58 /**
59 * @param int $errNo
60 * @param string $errMsg
61 * @param string $file
62 * @param int $line
63 * @return void
64 * @access public
66 function raiseError($errNo, $errMsg, $file, $line) {
68 if (! ($errNo & error_reporting())) {
69 return;
71 if(AK_DEBUG == 0){
72 return;
74 while (ob_get_level()) {
75 ob_end_clean();
78 $errType = array (
79 1 => "Php Error",
80 2 => "Php Warning",
81 4 => "Parsing Error",
82 8 => "Php Notice",
83 16 => "Core Error",
84 32 => "Core Warning",
85 64 => "Compile Error",
86 128 => "Compile Warning",
87 256 => "Php User Error",
88 512 => "Php User Warning",
89 1024 => "Php User Notice"
92 $info = array();
94 if (($errNo & E_USER_ERROR) && !empty($errMsg) && is_array($arr = @unserialize($errMsg))) {
95 foreach ($arr as $k => $v) {
96 $info[$k] = $v;
100 $trace = array();
102 if (function_exists('debug_backtrace')) {
103 $trace = debug_backtrace();
104 array_shift($trace);
108 $showSourceUri = @$_SERVER['PHP_SELF'].'?ak_debug_show_source=1';
109 $showSourcePrev = 10;
110 $showSourceNext = 10;
113 <script type="text/javascript">
114 function showParam(i) {
115 currentParam = i;
116 document.getElementById('paramHide').style.display = ''
117 document.getElementById('paramSpace').style.display = ''
118 document.getElementById('param').style.display = ''
119 document.getElementById('param').innerHTML = '<pre>' + document.getElementById('param' + i).innerHTML + '</pre>'
121 function hideParam() {
122 currentParam = -1;
123 document.getElementById('paramHide').style.display = 'none'
124 document.getElementById('paramSpace').style.display = 'none'
125 document.getElementById('param').style.display = 'none'
127 function showOrHideParam(i) {
128 if (currentParam == i) {
129 hideParam()
130 } else {
131 showParam(i)
134 function showFile(id) {
135 eval('display = document.getElementById("file' + id + '").style.display')
136 eval('if (display == "none") { document.getElementById("file' + id + '").style.display = "" } else { document.getElementById("file' + id + '").style.display = "none" } ');
138 function showDetails(cnt) {
139 for (i = 0; i < cnt; ++i) {
140 eval('document.getElementById("file' + i + '").style.display = ""')
143 function hideDetails(cnt) {
144 for (i = 0; i < cnt; ++i) {
145 eval('document.getElementById("file' + i + '").style.display = "none"')
148 var currentParam = -1;
149 </script>
151 <pre>
152 <hr />
154 <b>Error type:</b> <?php echo $errType[$errNo]; ?>
156 <?php
158 function fontStart($color) {
159 return '<font color="' . $color . '">';
161 function fontEnd() {
162 return '</font>';
165 $c['default'] = '#000000';
166 $c['keyword'] = '#0000FF';
167 $c['number'] = '#FF0000';
168 $c['string'] = '#FF00FF';
169 $c['comment'] = '#999999';
171 if (count($info)) {
172 foreach ($info as $k => $v) {
173 echo '<b>';
174 echo $k;
175 echo ':</b> ';
176 echo $v;
177 echo "\r\n";
179 } else {
180 echo '<b>Message:</b> ';
181 echo $errMsg;
182 echo "\r\n";
185 echo "\r\n";
187 if (count($trace)) {
189 echo '<span style="font-family: monospaced; font-size: 11px;">Trace: ' . count($trace) . "</span> ";
190 echo '<span style="font-family: monospaced; font-size: 11px; cursor: pointer;" onclick="showDetails('.count($trace).')">[show details]</span> ';
191 echo '<span style="font-family: monospaced; font-size: 11px; cursor: pointer;" onclick="hideDetails('.count($trace).')">[hide details]</span>';
193 echo "\r\n";
194 echo "\r\n";
198 echo '<ul>';
199 $currentParam = -1;
201 foreach ($trace as $k => $v) {
203 $currentParam++;
205 echo '<li style="list-style-type: square;">';
207 if (isset($v['class'])) {
208 echo '<span onmouseover="this.style.color=\'#0000ff\'" onmouseout="this.style.color=\''.$c['keyword'].'\'" style="color: '.$c['keyword'].'; cursor: pointer;" onclick="showFile('.$k.')">';
209 echo $v['class'];
210 echo ".";
211 } else {
212 echo '<span onmouseover="this.style.color=\'#0000ff\'" onmouseout="this.style.color=\''.$c['keyword'].'\'" style="color: '.$c['keyword'].'; cursor: pointer;" onclick="showFile('.$k.')">';
215 echo $v['function'];
216 echo '</span>';
217 echo " (";
219 $sep = '';
220 $v['args'] = (array) @$v['args'];
221 foreach ($v['args'] as $arg) {
223 $currentParam++;
225 echo $sep;
226 $sep = ', ';
227 $color = '#404040';
229 switch (true) {
231 case is_bool($arg):
232 $param = 'TRUE';
233 $string = $param;
234 break;
236 case is_int($arg):
237 case is_float($arg):
238 $param = $arg;
239 $string = $arg;
240 $color = $c['number'];
241 break;
243 case is_null($arg):
244 $param = 'NULL';
245 $string = $param;
246 break;
248 case is_string($arg):
249 $param = $arg;
250 $string = 'string[' . strlen($arg) . ']';
251 break;
253 case is_array($arg):
254 ob_start();
255 print_r($arg);
256 $param = ob_get_contents();
257 ob_end_clean();
258 $string = 'array[' . count($arg) . ']';
259 break;
261 case is_object($arg):
262 ob_start();
263 print_r($arg);
264 $param = ob_get_contents();
265 ob_end_clean();
266 $string = 'object: ' . get_class($arg);
267 break;
269 case is_resource($arg):
270 $param = 'resource: ' . get_resource_type($arg);
271 $string = 'resource';
272 break;
274 default:
275 $param = 'unknown';
276 $string = $param;
277 break;
281 echo '<span style="cursor: pointer; color: '.$color.';" onclick="showOrHideParam('.$currentParam.')" onmouseout="this.style.color=\''.$color.'\'" onmouseover="this.style.color=\'#dd0000\'">';
282 echo $string;
283 echo '</span>';
284 echo '<span id="param'.$currentParam.'" style="display: none;">' . $param . '</span>';
288 echo ")";
289 echo "\r\n";
291 if (!isset($v['file'])) {
292 $v['file'] = 'unknown';
294 if (!isset($v['line'])) {
295 $v['line'] = 'unknown';
298 $v['line'] = @$v['line'];
299 echo '<span id="file'.$k.'" style="display: none; color: gray;">';
300 if ($v['file'] && $v['line']) {
301 echo 'FILE: <a onmouseout="this.style.color=\'#007700\'" onmouseover="this.style.color=\'#FF6600\'" style="color: #007700; text-decoration: none;" target="_blank" href="'.$showSourceUri.'&ak_debug_file='.urlencode($v['file']).'&ak_debug_line='.$v['line'].'&ak_debug_prev='.$showSourcePrev.'&ak_debug_next='.$showSourceNext.'">'.basename($v['file']).'</a>';
302 } else {
303 echo 'FILE: ' . fontStart('#007700') . basename($v['file']) . fontEnd();
305 echo "\r\n";
306 echo 'LINE: ' . fontStart('#007700') . $v['line'] . fontEnd() . "\r\n";
307 echo 'DIR: ' . fontStart('#007700') . dirname($v['file']) . fontEnd();
308 echo '</span>';
310 echo '</li>';
313 echo '</ul>';
315 } else {
316 echo '<b>File:</b> ';
317 echo basename($file);
318 echo ' (' . $line . ') ';
319 echo dirname($file);
324 <?php echo '<span id="paramHide" style="display: none; font-family: monospaced; font-size: 11px; cursor: pointer;" onclick="hideParam()">[hide param]</span>';?>
325 <span id="paramSpace" style="display: none;">
327 </span><div id="param" perm="0" style="background-color: #FFFFE1; padding: 2px; display: none;"></div><hr />
329 Trick: click on a function's argument to see it fully
330 Trick: click on a function to see the file & line
331 Trick: click on the file name to see the source code
333 </pre>
334 <?php
335 exit;
338 function showSource($file, $line, $prev = 10, $next = 10)
340 if(AK_ENVIRONMENT != 'development'){
341 echo Ak::t('Opsss! File highlighting is only available on development mode.');
342 die();
345 // We only allow to show files inside the base path.
346 $file = AK_BASE_DIR.DS.trim(str_replace(array(AK_BASE_DIR,';','..'), array('','',''), $file), DS.'.');
348 if(strstr($file, AK_CONFIG_DIR)){
349 echo Ak::t('Sorry but you can\'t view configuration files.');
350 die();
353 if (!(file_exists($file) && is_file($file))) {
354 echo Ak::t('%file_name is not available for showing its source code', array('%file_name'=> $file));
355 die();
358 ini_set('highlight.default','#000000');
359 ini_set('highlight.keyword','0000FF');
360 ini_set('highlight.number','FF0000');
361 ini_set('highlight.string','#FF00FF');
362 ini_set('highlight.comment','#999999');
365 //read code
366 ob_start();
367 highlight_file($file);
368 $data = ob_get_contents();
369 ob_end_clean();
371 //seperate lines
372 $data = explode('<br />', $data);
373 $count = count($data) - 1;
375 //count which lines to display
376 $start = $line - $prev;
377 if ($start < 1) {
378 $start = 1;
380 $end = $line + $next;
381 if ($end > $count) {
382 $end = $count + 1;
385 //displaying
386 echo '<table cellspacing="0" cellpadding="0"><tr>';
387 echo '<td style="vertical-align: top;"><code style="background-color: #FFFFCC; color: #666666;">';
389 for ($x = $start; $x <= $end; $x++) {
390 echo '<a name="'.$x.'"></a>';
391 echo ($line == $x ? '<font style="background-color: red; color: white;">' : '');
392 echo str_repeat('&nbsp;', (strlen($end) - strlen($x)) + 1);
393 echo $x;
394 echo '&nbsp;';
395 echo ($line == $x ? '</font>' : '');
396 echo '<br />';
398 echo '</code></td><td style="vertical-align: top;"><code>';
399 while ($start <= $end) {
400 echo '&nbsp;' . $data[$start - 1] . '<br />';
401 ++$start;
403 echo '</code></td>';
404 echo '</tr></table>';
406 if ($prev != 10000 || $next != 10000) {
407 echo '<br />';
408 echo '<a style="font-family: tahoma; font-size: 12px;" href="'.@$_SERVER['PHP_SELF'].'?ak_debug_show_source=1&ak_debug_file='.urlencode($file).'&ak_debug_line='.$line.'&ak_debug_prev=10000&ak_debug_next=10000#'.($line - 15).'">View Full Source</a>';