[ Index ] |
PHP Cross Reference of BackPress |
[Summary view] [Print] [Text view]
1 <?php 2 3 4 /** 5 * BackPress logging level constants 6 */ 7 define('BP_LOG_NONE', 0); 8 define('BP_LOG_FAIL', 1); 9 define('BP_LOG_ERROR', 2); 10 define('BP_LOG_WARNING', 4); 11 define('BP_LOG_NOTICE', 8); 12 define('BP_LOG_DEBUG', 16); 13 14 /** 15 * Combination of all errors (excluding none and debug) 16 */ 17 define('BP_LOG_ALL', BP_LOG_FAIL + BP_LOG_ERROR + BP_LOG_WARNING + BP_LOG_NOTICE); 18 19 20 21 /** 22 * Provides easy and abstracted logging facilities 23 * 24 * @package BackPress 25 */ 26 class BP_Log 27 { 28 /** 29 * The logging level 30 * 31 * @var integer 32 */ 33 var $level = BP_LOG_NONE; 34 35 /** 36 * The type of logging 37 * 38 * @var string 39 */ 40 var $type = 'php'; 41 42 /** 43 * The types of logging available 44 * 45 * @var array 46 */ 47 var $types = array('php', 'file', 'display', 'console'); 48 49 /** 50 * The filename of the file to log messages to when type is "file" 51 * 52 * @var string 53 */ 54 var $filename = ''; 55 56 /** 57 * Whether or not the javascript functions are available 58 * 59 * @var boolean 60 **/ 61 var $console_javascript_loaded = false; 62 63 /** 64 * Console log messages which are queued up to be displayed on page load 65 * 66 * @var array 67 **/ 68 var $console_javascript_onloads = array(); 69 70 /** 71 * Initialises the logging 72 * 73 * @return void 74 */ 75 function __construct($level = false, $type = false, $filename = false) 76 { 77 $this->set_level($level); 78 $this->set_type($type); 79 $this->set_filename($filename); 80 } 81 82 function BP_log($level = false, $type = false, $filename = false) { 83 self::__construct($level, $type, $filename); 84 } 85 /** 86 * Sets the logging level 87 * 88 * @return integer|boolean The old level on success or false 89 * @uses BP_LOG_LEVEL 90 */ 91 function set_level($level) 92 { 93 $old_level = $this->level; 94 95 if (is_integer($level)) { 96 $this->level = $level; 97 } elseif (defined('BP_LOG_LEVEL') && is_integer(BP_LOG_LEVEL)) { 98 $this->level = BP_LOG_LEVEL; 99 } else { 100 return false; 101 } 102 103 return $old_level; 104 } 105 106 /** 107 * Sets the logging type 108 * 109 * @return string|false The old type on success or false 110 * @uses BP_LOG_TYPE 111 */ 112 function set_type($type) 113 { 114 $old_type = $this->type; 115 $type = strtolower($type); 116 117 if (in_array($type, $this->types)) { 118 $this->type = $type; 119 } elseif (defined('BP_LOG_TYPE') && in_array(BP_LOG_TYPE, $this->types)) { 120 $this->type = BP_LOG_TYPE; 121 } else { 122 return false; 123 } 124 125 return $old_type; 126 } 127 128 /** 129 * Sets the logging filename 130 * 131 * @return string|boolean The old filename on success or false 132 * @uses BP_LOG_FILENAME 133 */ 134 function set_filename($filename) 135 { 136 $old_filename = $this->filename; 137 138 if (is_string($filename)) { 139 $_filename = $filename; 140 } elseif (defined('BP_LOG_FILENAME') && is_string(BP_LOG_FILENAME)) { 141 $_filename = BP_LOG_FILENAME; 142 } else { 143 return false; 144 } 145 146 if (isset($_filename) && file_exists($_filename) && is_file($_filename) && is_writable($_filename)) { 147 $this->filename = $_filename; 148 } else { 149 return false; 150 } 151 152 return $old_filename; 153 } 154 155 /** 156 * Sends a message to the log 157 * 158 * @return boolean True on success, false on failure 159 */ 160 function send($message = '', $level = BP_LOG_DEBUG, $type = false, $prefix = false) 161 { 162 // Make sure the level of this message is set to be logged 163 if (($level & $this->level) === 0) { 164 return; 165 } 166 167 // Format the message into an array of lines to be logged 168 $lines = $this->format_message($message, $level, $prefix); 169 170 // Do some validation on the type 171 if ($type && in_array($type, $this->types)) { 172 $_type = $type; 173 } else { 174 $_type = $this->type; 175 } 176 177 // Get a name for the level 178 if ($level) { 179 $_level = $this->get_level_from_integer($level); 180 } 181 182 // Setup strings to prepend to some of the types 183 $prepend = $_level . ': '; 184 if ($prefix) { 185 $prepend .= $prefix . ': '; 186 } 187 $pad = str_repeat(' ', strlen($prepend) - 2) . '| '; 188 189 // Switch over the four types 190 switch ($_type) { 191 case 'php': 192 $php_fail = false; 193 194 // Check that the error_log() function is available 195 if (function_exists('error_log') && is_callable('error_log')) { 196 foreach ($lines as $key => $line) { 197 if ($key === 0) { 198 $_prepend = $prepend; 199 } else { 200 $_prepend = $pad; 201 } 202 if (!error_log($_prepend . $line, 0)) { 203 $php_fail = true; 204 break; 205 } 206 } 207 } else { 208 $php_fail = true; 209 } 210 211 if ($php_fail) { 212 // The PHP error log process failed, path of least resistance is to write to display 213 $this->send($message, $level, 'display', $prefix); 214 return; 215 } 216 break; 217 218 case 'file': 219 $file_fail = false; 220 221 // We've already done the prerequisite checks on the file by now so just write to it 222 if (!$file_handle = fopen($this->filename, 'a')) { 223 $file_fail = true; 224 } else { 225 // Prepare a string to write 226 $_lines = array( 227 '[' . date('c') . ']', 228 '[client ' . $_SERVER['REMOTE_ADDR'] . ']', 229 $prepend, 230 join("\n", $lines) 231 ); 232 } 233 if (fwrite($file_handle, join(' ', $_lines) . "\n") === false) { 234 $file_fail = true; 235 } 236 if ($file_handle) { 237 fclose($file_handle); 238 } 239 if ($file_fail) { 240 // Writing to file failed, output to display 241 $this->send($message, $level, 'display', $prefix); 242 return; 243 } 244 break; 245 246 case 'display': 247 $_lines = array(); 248 foreach ($lines as $key => $line) { 249 if ($key === 0) { 250 $_lines[] = $prepend . $line; 251 } else { 252 $_lines[] = $pad . $line; 253 } 254 } 255 echo '<div class="bplog_message bplog_level_' . strtolower($_level) . '"><pre>' . join("\n", $_lines) . '</pre></div>' . "\n"; 256 break; 257 258 case 'console': 259 $_lines = array(); 260 foreach ($lines as $key => $line) { 261 if ($key === 0 && $prefix) { 262 $_lines[] = $prefix . ': ' . $line; 263 } else { 264 $_lines[] = $line; 265 } 266 } 267 268 $_lines = $ident . $_level . ' ~\n' . str_replace('\'', '\\\'', join('\n', $_lines)); 269 270 if (!$this->console_javascript_loaded) { 271 // Queue it for logging onload 272 $this->console_javascript_onloads[] = array('message' => $_lines, 'level' => $level, 'time' => date('c')); 273 } else { 274 // Log it now 275 echo '<script type="text/javascript" charset="utf-8">bp_log_add(\'' . $this->_esc_js_log( $_lines ) . '\', ' . $this->_esc_js_log( $level ) . ', \'' . $this->_esc_js_log( date('c') ) . '\');</script>' . "\n"; 276 } 277 break; 278 } 279 280 return true; 281 } 282 283 /** 284 * Gets the name of the log level from an integer 285 * 286 * @return string The logging level 287 */ 288 function get_level_from_integer($integer) 289 { 290 switch ($integer) { 291 case BP_LOG_NONE: 292 return 'BP_LOG_NONE'; 293 break; 294 case BP_LOG_FAIL: 295 return 'BP_LOG_FAIL'; 296 break; 297 case BP_LOG_ERROR: 298 return 'BP_LOG_ERROR'; 299 break; 300 case BP_LOG_WARNING: 301 return 'BP_LOG_WARNING'; 302 break; 303 case BP_LOG_NOTICE: 304 return 'BP_LOG_NOTICE'; 305 break; 306 case BP_LOG_DEBUG: 307 return 'BP_LOG_DEBUG'; 308 break; 309 default: 310 return 'BP_LOG_UNDEFINED'; 311 break; 312 } 313 } 314 315 /** 316 * Formats a message for output to a log file 317 * 318 * @return boolean True on success, false on failure 319 */ 320 function format_message($message, $level = BP_LOG_DEBUG, $prefix = false, $tabs = 0) 321 { 322 $lines = array(); 323 324 if (is_null($message)) { 325 $lines[] = 'null (' . var_export($message, true) . ')'; 326 return $lines; 327 } 328 329 if (is_bool($message)) { 330 $lines[] = 'bool (' . var_export($message, true) . ')'; 331 return $lines; 332 } 333 334 if (is_string($message)) { 335 if ($level === BP_LOG_DEBUG || $message === '') { 336 $lines[] = 'string(' . strlen($message) . ') ("' . $message . '")'; 337 } else { 338 $lines[] = $message; 339 } 340 return $lines; 341 } 342 343 if (is_array($message) || is_object($message)) { 344 if (is_array($message)) { 345 $lines[] = 'array(' . count($message) . ') ('; 346 } else { 347 $lines[] = 'object(' . get_class($message) . ') ('; 348 } 349 $tabs++; 350 foreach ($message as $key => $value) { 351 $array = $this->format_message($value, $level, false, $tabs); 352 if (is_array($array)) { 353 $array[0] = str_repeat(' ', $tabs) . $key . ' => ' . $array[0]; 354 $lines = array_merge($lines, $array); 355 } else { 356 $lines[] = str_repeat(' ', $tabs) . $key . ' => ' . $array; 357 } 358 } 359 $tabs--; 360 $lines[] = str_repeat(' ', $tabs) . ')'; 361 return $lines; 362 } 363 364 if (is_int($message)) { 365 $lines[] = 'int (' . $message . ')'; 366 return $lines; 367 } 368 369 if (is_float($message)) { 370 $lines[] = 'float (' . $message . ')'; 371 return $lines; 372 } 373 374 if (is_resource($message)) { 375 $lines[] = 'resource (' . get_resource_type($message) . ')'; 376 return $lines; 377 } 378 379 $lines[] = 'unknown (' . $message . ')'; 380 return $lines; 381 } 382 383 /** 384 * Send a debug message 385 * 386 * @return boolean True on success, false on failure 387 */ 388 function debug($message, $prefix = false) 389 { 390 $this->send($message, BP_LOG_DEBUG, false, $prefix); 391 } 392 393 /** 394 * Send a notice message 395 * 396 * If the message is an array, then it sends each index as a separate message 397 * 398 * @return boolean True on success, false on failure 399 */ 400 function notice($message) 401 { 402 if (is_array($message)) { 403 foreach ($message as $value) { 404 $this->send($value, BP_LOG_NOTICE); 405 } 406 } else { 407 $this->send($message, BP_LOG_NOTICE); 408 } 409 } 410 411 /** 412 * Send a warning message 413 * 414 * If the message is an array, then it sends each index as a separate message 415 * 416 * @return boolean True on success, false on failure 417 */ 418 function warning($message) 419 { 420 if (is_array($message)) { 421 foreach ($message as $value) { 422 $this->send($value, BP_LOG_WARNING); 423 } 424 } else { 425 $this->send($message, BP_LOG_WARNING); 426 } 427 } 428 429 /** 430 * Send an error message 431 * 432 * If the message is an array, then it sends each index as a separate message 433 * 434 * @return boolean True on success, false on failure 435 */ 436 function error($message) 437 { 438 if (is_array($message)) { 439 foreach ($message as $value) { 440 $this->send($value, BP_LOG_ERROR); 441 } 442 } else { 443 $this->send($message, BP_LOG_ERROR); 444 } 445 } 446 447 /** 448 * Send an error message and die 449 * 450 * If the message is an array, then it sends each index as a separate message 451 * 452 * @return boolean True on success, false on failure 453 */ 454 function fail($message) 455 { 456 if (is_array($message)) { 457 foreach ($message as $value) { 458 $this->send($value, BP_LOG_FAIL); 459 } 460 } else { 461 $this->send($message, BP_LOG_FAIL); 462 } 463 464 die(); 465 } 466 467 /** 468 * Outputs javascript functions for the head of the html document 469 * 470 * Must be included in the head of the debug document somehow when using 'console' type. 471 * 472 * @return void 473 **/ 474 function console_javascript() 475 { 476 if ($this->type !== 'console') { 477 return; 478 } 479 480 $this->console_javascript_loaded = true; 481 ?> 482 483 <script type="text/javascript" charset="utf-8"> 484 var BP_LOG_NONE = 0; 485 var BP_LOG_FAIL = 1; 486 var BP_LOG_ERROR = 2; 487 var BP_LOG_WARNING = 4; 488 var BP_LOG_NOTICE = 8; 489 var BP_LOG_DEBUG = 16; 490 491 function bp_log_send(message, level, time) { 492 if (window.console) { 493 // Works in later Safari and Firefox with Firebug 494 switch (level) { 495 case BP_LOG_NONE: 496 // This shouldn't happen really 497 break; 498 case BP_LOG_FAIL: 499 case BP_LOG_ERROR: 500 window.console.error("[" + time + "] " + message); 501 break; 502 case BP_LOG_WARNING: 503 window.console.warn("[" + time + "] " + message); 504 break; 505 case BP_LOG_NOTICE: 506 window.console.info("[" + time + "] " + message); 507 break; 508 case BP_LOG_DEBUG: 509 window.console.log("[" + time + "] " + message); 510 break; 511 default: 512 break; 513 } 514 } 515 } 516 517 var bp_log_queue = new Array(); 518 519 function bp_log_add(message, level, time) { 520 bp_log_queue.push(new Array(message, level, time)); 521 } 522 523 function bp_log_process() { 524 while (item = bp_log_queue.shift()) { 525 bp_log_send(item[0], item[1], item[2]); 526 } 527 } 528 529 function bp_log_onload() { 530 <?php 531 foreach ($this->console_javascript_onloads as $onload) { 532 echo "\t\t\t" . 'bp_log_send(\'' . $this->_esc_js_log( $onload['message'] ) . '\', ' . $this->_esc_js_log( $onload['level'] ) . ', \'' . $this->_esc_js_log( $onload['time'] ) . '\');' . "\n"; 533 } 534 ?> 535 bp_log_process(); 536 } 537 538 window.onload = bp_log_onload; 539 </script> 540 541 <?php 542 } 543 544 function _esc_js_log( $message ) 545 { 546 return str_replace( 547 array( '\'', "\n" ), 548 array( '\\\'', '\n' ), 549 $message 550 ); 551 } 552 553 } // END class BP_Log
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Oct 9 01:00:57 2024 | Cross-referenced by PHPXref 0.7.1 |