Changeset 1535892
- Timestamp:
- 11/17/2016 09:00:00 PM (9 years ago)
- Location:
- dbug/trunk
- Files:
-
- 28 added
- 5 deleted
- 2 edited
-
_plugin.php (added)
-
admin.php (added)
-
admin_log_viewer.php (deleted)
-
admin_settings.php (deleted)
-
bug.png (deleted)
-
composer.json (added)
-
dbug-admin.php (deleted)
-
dbug.css (deleted)
-
dbug.php (modified) (1 diff)
-
functions.php (added)
-
index.php (added)
-
lib (added)
-
lib/WP_Dbug (added)
-
lib/WP_Dbug/Dbug.php (added)
-
public (added)
-
public/bug.png (added)
-
public/dbug.css (added)
-
readme.txt (modified) (2 diffs)
-
theme.php (added)
-
vendor (added)
-
vendor/autoload.php (added)
-
vendor/composer (added)
-
vendor/composer/ClassLoader.php (added)
-
vendor/composer/LICENSE (added)
-
vendor/composer/autoload_classmap.php (added)
-
vendor/composer/autoload_namespaces.php (added)
-
vendor/composer/autoload_psr4.php (added)
-
vendor/composer/autoload_real.php (added)
-
vendor/composer/autoload_static.php (added)
-
vendor/composer/installed.json (added)
-
views (added)
-
views/admin (added)
-
views/admin/log_viewer.php (added)
-
views/admin/options-general.php (added)
-
views/dbug.php (added)
Legend:
- Unmodified
- Added
- Removed
-
dbug/trunk/dbug.php
r769784 r1535892 1 1 <?php 2 /*3 Plugin Name: dbug4 Plugin URI: https://wordpress.org/extend/plugins/dbug/5 Description: Helps with Dev'n6 Author: Eric Eaglstun7 Version: 1.98 Author URI: http://ericeaglstun.com9 */10 2 11 if( !function_exists('dbug') && !class_exists('Dbug') ){ 12 13 /* 14 * output debug information to screen 15 * @param mixed 16 * @param string optional 17 * @param int optional 18 * @param int optional 19 */ 20 function dbug( $v = null, $k = null, $trace = 1 ){ 21 // dont use DEBUG for integer 0 22 if( is_null($k) ){ 23 $k = 'DEBUG'; 24 } 25 26 Dbug::debug( $v, $k, $trace ); 27 return; 28 } 29 30 /* 31 * write debug information to log 32 * @param mixed 33 * @param string optional 34 * @param string optional 35 */ 36 function dlog( $v = null, $k = null, $file = 'dlog' ){ 37 // dont use DEBUG for integer 0 38 if( is_null($k) ){ 39 $k = 'DEBUG'; 40 } 41 42 Dbug::delog( $v, $k, $file ); 43 return; 44 } 45 46 /* 47 * dbug and die 48 * @param mixed 49 * @param string optional 50 * @param int optional number of lines to backtrace 51 * ends script 52 */ 53 function ddbug( $v = null, $k = null, $trace = 1 ){ 54 // dont call dbug() from here because it screws up backtrace 55 // dont use DEBUG for integer 0 56 if( is_null($k) ){ 57 $k = 'DEBUG'; 58 } 59 60 Dbug::debug( $v, $k, $trace ); 61 die(); 62 } 63 64 /* 65 * dlog and die 66 * @param mixed 67 * @param string optional 68 * @param int optional number of lines to backtrace 69 * ends script 70 */ 71 function ddlog( $v = null, $k = null, $file = 'dlog' ){ 72 // dont call dbug() from here because it screws up backtrace 73 // dont use DEBUG for integer 0 74 if( is_null($k) ){ 75 $k = 'DEBUG'; 76 } 77 78 Dbug::delog( $v, $k, $file ); 79 die(); 80 } 81 82 class Dbug{ 83 84 private static $error_handler = 'screen'; // or 'log' 85 private static $html = ''; // html echoed for `screen` logging 86 private static $is_mu = FALSE; // is multi-user install 87 88 private static $LOG_PATH = ''; // absolute path to logs on server 89 private static $LOG_FILESIZE = 1048576; // in bytes 1048576 = 1 megabyte 90 91 /* 92 * sets up log path, error handling, admin screens 93 * @return NULL 94 */ 95 public static function setup(){ 96 // set whether we are on MU or not 97 if( function_exists('delete_blog_option') ) 98 self::$is_mu = TRUE; 99 100 // set path to logs 101 self::$LOG_PATH = self::getLogPath(); 102 103 // set default error handling to screen to logs 104 Dbug::set_error_handler(); 105 106 // only admin stuff below 107 if( !is_admin() ) 108 return; 109 110 require_once 'dbug-admin.php'; 111 DbugAdmin::setup(); 112 } 113 114 /* 115 * output debug info to screen 116 * @param mixed 117 * @param string|int 118 * @param int 119 * @param int 120 * @return NULL 121 */ 122 public static function debug( $v, $k, $t = 1 ){ 123 // dont show 124 if( self::$error_handler == 'log' ) 125 return self::delog( $v, $k, 'dbug' ); 126 127 self::$html = '<div class="dbug">'; 128 129 self::debug_value_html( $k, $v, 0 ); 130 131 if( $t ){ 132 $bt = self::get_backtrace( $t ); 133 134 self::$html .= '<span class="backtrace"><strong>backtrace:</strong></span><br/>'; 135 136 foreach( $bt as $debug ){ 137 self::$html .= '<span class="backtrace"> 138 '. 139 $debug['file'].' line '.$debug['line'].' 140 </span><br/>'."\r\n"; 141 } 142 } 143 144 self::$html .= "</div>\n\n"; 145 146 echo self::$html; 147 self::$html = ''; 148 } 149 150 /* 151 * 152 * TODO: if we can not write to the log directory, handle the failure in a way that lets the site admin know 153 * @param 154 * @param 155 * @param string 156 * @return 157 */ 158 public static function delog( $v, $k = 'DEBUG', $file ){ 159 $now = time(); 160 161 self::debug_value_html( $k, $v, 0 ); 162 163 $log = $_SERVER['REQUEST_URI']."\n"; 164 $log .= date( 'M jS Y h:i:s a', $now )." ( $now ) \n"; 165 $log .= strip_tags( str_replace(' ', ' ', self::$html)). "\n\n"; 166 167 $log = html_entity_decode( $log ); 168 $log = utf8_decode( $log ); 169 170 if( !file_exists(self::$LOG_PATH.$file) ) 171 touch( self::$LOG_PATH.$file ); 172 173 file_put_contents( self::$LOG_PATH.$file, $log, FILE_APPEND ); 174 self::$html = ''; 175 176 $m = filesize( self::$LOG_PATH.$file ); 177 $path = self::$LOG_PATH; 178 179 if( $m >= self::$LOG_FILESIZE ){ 180 $i = 1; 181 while( file_exists($path.$file."_".$i) ){ 182 $i++; 183 } 184 185 copy( $path.$file, $path.$file."_".$i ); 186 unlink( $path.$file ); 187 } 188 } 189 190 /* 191 * removes the `dbug` elements from backtrace 192 * 193 * @param int 194 * @return array 195 */ 196 public static function get_backtrace( $levels = 1 ){ 197 $bt = debug_backtrace(); 198 $bt = array_map( 'Dbug::_get_backtrace', $bt ); 199 $bt = array_filter( $bt ); 200 201 if( $bt > 0 ) 202 $bt = array_slice( $bt, 2, $levels ); 203 204 return $bt; 205 } 206 207 /* 208 * array_map callback 209 */ 210 public static function _get_backtrace( $e ){ 211 if( isset($e['file']) ) 212 return $e; 213 } 214 215 /* 216 * 217 * @param 218 * @param 219 * @param 220 * @param 221 * @bool 222 */ 223 public static function debug_value_html( $k, $v, $indent, $hack = FALSE ){ 224 if( $indent > 100 ){ 225 return; 226 } 227 228 // dont display arrays/objects as key 229 if( is_int($k) ) 230 $k = strval( $k ); 231 elseif( is_float($k) ) 232 $k = strval( $k ); 233 elseif( !is_string($k) ) 234 $k = '?'; 235 236 $k = urlencode( (string) $k ); 237 $k = str_replace( '%00%2A%00_', '', $k ); 238 $k = urldecode( $k ); 239 240 self::debug_indent_html( $indent ); 241 242 if( is_null($v) ){ 243 self::$html .= ( htmlentities($k) . " = <strong>Null</strong><br/>\n" ); 244 } else if( is_bool($v) ){ 245 self::$html .= ( htmlentities($k) . " = <strong>Bool:</strong> [ " . ( $v == TRUE ? 'TRUE' : 'FALSE') . " ]<br/>\n" ); 246 } else if( is_int($v) ){ 247 self::$html .= ( htmlentities($k) . " = <strong>Int:</strong> [ $v ]<br/>\n" ); 248 } else if( is_float($v) ){ 249 self::$html .= ( htmlentities($k) . " = <strong>Float:</strong> [ $v ]<br/>\n" ); 250 } else if( is_string($v) ){ 251 self::$html .= $hack ? 252 htmlentities($k) ." = [ ". htmlentities($v) ." ]<br/>\n" : 253 htmlentities($k) ." = <strong>String:</strong> [ ". htmlentities($v) ." ]<br/>\n"; 254 } else if( is_array($v) ){ 255 self::$html .= $hack ? 256 htmlentities($k) ."<br/>\n" : 257 htmlentities($k) ." = <strong>Array</strong> containing ". count($v) ." elements:<br/>\n"; 258 259 foreach( $v as $k1 => $v1 ){ 260 $hack ? 261 self::debug_value_html( $k1, $v1, ( $indent + 5), TRUE ) : 262 self::debug_value_html( $k1, $v1, ( $indent + 5) ); 263 } 264 265 } else if( ($v_class = get_class($v)) && ($v_class != 'stdClass') ){ 266 // TODO: figure out a way to make this work. 267 // there is a problem with get_class on certain objects... 268 self::$html .= ( $k . " = <strong>Class</strong> $v_class:<br/>\n" ); 269 270 $RC = new ReflectionClass( $v ); 271 272 $properties = $RC->getProperties(); 273 self::$html .= count($properties) ." properties:<br/>\n"; 274 foreach( $properties as $k1 => $v1 ){ 275 $type = self::getType($v1); 276 277 $property_mockup = array(); 278 279 if( $v_class != $v1->class ){ 280 $property_mockup['Class:'] = $v1->class; 281 } 282 283 // TODO: find better way to not use small tags 284 self::debug_value_html( "$".$v1->name." <small>( $type )</small>", $property_mockup, ($indent + 5), TRUE ); 285 } 286 287 $methods = $RC->getMethods(); 288 self::$html .= count($methods) ." methods:<br/>\n"; 289 foreach( $methods as $k1 => $v1 ){ 290 $type = self::getType($v1); 291 292 $params = $v1->getParameters(); 293 $params = implode( ', ', $params ); 294 295 $method_mockup = array( 296 'Parameters' => $params 297 ); 298 299 if( $v_class != $v1->class ){ 300 $method_mockup['Class:'] = $v1->class; 301 } 302 303 self::debug_value_html( $v1->name." <small>( $type )</small> ", $method_mockup , ($indent + 5), TRUE ); 304 } 305 306 } else if( is_object($v) ){ 307 $vars = (array) $v; 308 $count = count( $vars ); 309 310 self::$html .= ( $k . " = <strong>Object</strong> with $count elements:<br/>\n" ); 311 312 foreach( $vars as $k1 => $v1 ){ 313 self::debug_value_html( $k1, $v1, ($indent + 5) ); 314 } 315 } 316 } 317 318 /* 319 * add any number of non breaking spaces (&npsp;) to html 320 * @param int 321 * @return 322 */ 323 private static function debug_indent_html( $indent ){ 324 if( $indent > 0 ){ 325 for( $x=0; $x<$indent; $x++ ){ 326 self::$html .= ' '; 327 } 328 } 329 } 330 331 /* 332 * gets the max filesize of logs in bytes 333 * @return int 334 */ 335 protected static function getLogFilesize(){ 336 $dbug_log_filesize = (int) self::get_option( 'dbug_log_filesize' ); 337 $dbug_log_filesize = $dbug_log_filesize < 1024 ? 1048576 : $dbug_log_filesize; 338 339 return $dbug_log_filesize; 340 } 341 342 /* 343 * gets the saved path to log files and creates if doesnt exist 344 * @return string absolute path to directory or FALSE 345 */ 346 protected static function getLogPath(){ 347 $path = self::get_option( 'dbug_log_path' ); 348 349 return self::checkLogDirectory( $path ); 350 } 351 352 /* 353 * get the type of method or property. is there a better way to do this? 354 * @param ReflectionMethod|ReflectionProperty 355 * @return string 356 */ 357 private static function getType( $r ){ 358 if( $r->isPublic() ) 359 $type = 'public'; 360 elseif( $r->isPrivate() ) 361 $type = 'private'; 362 elseif( $r->isProtected() ) 363 $type = 'protected'; 364 365 if( $r instanceof ReflectionProperty ) 366 return $type; 367 368 // ReflectionMethod only below 369 370 if( $r->isStatic() ) 371 $type = "static $type"; 372 373 if( $r->isAbstract() ) 374 $type = "abstract $type"; 375 376 if( $r->isFinal() ) 377 $type = "final $type"; 378 379 return $type; 380 } 381 382 /* 383 * catch all php errors with dbug 384 * write to a log file if we are on production, screen otherwise. 385 * @return 386 */ 387 private static function set_error_handler(){ 388 // set max filesize of logs 389 self::$LOG_FILESIZE = self::getLogFilesize(); 390 391 // get the saved error level and calculate val 392 $error_level = 0; 393 $error_levels = get_option( 'dbug_error_level' ); 394 395 if( is_array($error_levels) ) 396 foreach( $error_levels as $e_level ){ 397 //echo "$error_level | $e_level<br/>\n"; 398 $error_level = $error_level | $e_level; 399 } 400 401 //die('$error_level: '.$error_level); 402 //error_reporting( $error_level ); 403 404 // whether to output errors or log to file 405 $logging = self::get_option( 'dbug_logging' ); 406 switch($logging){ 407 case 'log': 408 set_error_handler( 'Dbug::handle_error_log', $error_level ); 409 self::$error_handler = 'log'; 410 return; 411 break; 412 case 'screen': 413 default: 414 add_action( 'init', 'Dbug::register_styles' ); 415 set_error_handler( 'Dbug::handle_error_screen', $error_level ); 416 self::$error_handler = 'screen'; 417 return; 418 break; 419 } 420 } 421 422 /* 423 * catch all php errors to screen rather than log file 424 * usually only enabled on development 425 * @param 426 * @param 427 * @param 428 * @param 429 * @return bool 430 */ 431 public static function handle_error_screen( $err_no, $err_str, $err_file, $err_line ){ 432 dbug( $err_str, // php error 433 "PHP ERROR ($err_no) ", 2, 1 ); 434 return TRUE; 435 } 436 437 /* 438 * catch all php errors to log file rather than screen 439 * usually only enabled on production 440 * @param 441 * @param 442 * @param 443 * @param 444 * @return bool 445 */ 446 public static function handle_error_log( $err_no, $err_str, $err_file, $err_line ){ 447 dlog( $err_str, // php error 448 "PHP ERROR ($err_no) $err_file $err_line", // file name, line 449 'php_errors' ); 450 return TRUE; 451 } 452 453 /* 454 * create the log directory if it does not exist 455 * default to /logs/ in wordpress root 456 * @TODO find a better way to make sure the path is writeable and valid 457 * @TODO fix error when log path is not on same server. 458 * @TODO set up htaccess to copy from current directory ( mu compat ) 459 * @param string 460 * @return string absolute path to directory or FALSE 461 */ 462 protected static function checkLogDirectory( $dir ){ 463 if( !is_dir($dir) ) 464 $dir = ABSPATH.'logs/'; 465 466 $pathinfo = pathinfo( $dir ); 467 $dirname = isset( $pathinfo['dirname'] ) ? $pathinfo['dirname'] : NULL; 468 if( !is_dir($dirname) ) 469 return FALSE; 470 471 // force trailing slash! 472 if( strrpos($dir, '/') != (strlen($dir)-1) ) 473 $dir .= '/'; 474 475 // make directory if it doesnt exist 476 if( !is_dir($dir) ) 477 @mkdir( $dir, 0755 ); 478 479 // change permissions if we cant write to it 480 if( !is_writable($dir) ) 481 @chmod( $dir, 0755 ); 482 483 // test and make sure we can write to it 484 if( !is_dir($dir) || !is_writable($dir) ) 485 return FALSE; 486 487 // make sure htaccess is in place to protect log files 488 if( !file_exists($dir.'.htaccess') && file_exists(__DIR__.'/_htaccess.php') ) 489 copy( __DIR__.'/_htaccess.php', 490 $dir.'.htaccess' ); 491 492 return $dir; 493 } 494 495 /* 496 * register fancy styles for screen 497 * attached to `init` action 498 */ 499 public static function register_styles(){ 500 wp_register_style( 'dbugStyle', plugins_url('dbug/dbug.css', dirname(__FILE__)) ); 501 wp_enqueue_style( 'dbugStyle' ); 502 } 503 504 /* 505 * render a page into wherever 506 * @param string 507 * @param object|array 508 */ 509 protected static function render( $filename, $vars = array() ){ 510 extract( (array) $vars, EXTR_SKIP ); 511 512 include $filename; 513 } 514 515 /* 516 * wrapper for single/mu delete_option/delete_blog_option 517 * deletes options for all blogs in blog #1 for mu 518 * @param string 519 */ 520 protected static function delete_option( $key ){ 521 return self::$is_mu ? delete_blog_option( 1, $key ) : delete_option( $key ); 522 } 523 524 /* 525 * wrapper for single/mu get_option/get_blog_option 526 * gets options for all blogs in blog #1 for mu 527 * @param string 528 */ 529 protected static function get_option( $key ){ 530 return self::$is_mu ? get_blog_option( 1, $key ) : get_option( $key ); 531 } 532 533 /* 534 * wrapper for single/mu update_option/update_blog_option 535 * updates options for all blogs in blog #1 for mu 536 * @param string 537 * @param mixed 538 */ 539 protected static function update_option( $key, $val ){ 540 return self::$is_mu ? update_blog_option( 1, $key, $val ) : update_option( $key, $val ); 541 } 542 } 543 544 // init 545 Dbug::setup(); 546 } 547 548 // end of file 549 // dbug/dbug.php 3 // keep this file around for a while for bc 4 require_once __DIR__.'/_plugin.php'; -
dbug/trunk/readme.txt
r769784 r1535892 3 3 Donate link: http://www.heifer.org/ 4 4 Tags: debug, error log 5 Requires at least: 3.26 Tested up to: 3.65 Requires at least: 4.0 6 Tested up to: 4.6.1 7 7 Stable tag: trunk 8 8 … … 23 23 24 24 == Changelog == 25 26 = 1.9.2 = 27 Add composer info, autoload 25 28 26 29 = 1.9 =
Note: See TracChangeset
for help on using the changeset viewer.