ILIAS  Release_4_1_x_branch Revision 61804
 All Data Structures Namespaces Files Functions Variables Groups Pages
Log.php
Go to the documentation of this file.
1 <?php
10 define('PEAR_LOG_EMERG', 0); /* System is unusable */
11 define('PEAR_LOG_ALERT', 1); /* Immediate action required */
12 define('PEAR_LOG_CRIT', 2); /* Critical conditions */
13 define('PEAR_LOG_ERR', 3); /* Error conditions */
14 define('PEAR_LOG_WARNING', 4); /* Warning conditions */
15 define('PEAR_LOG_NOTICE', 5); /* Normal but significant */
16 define('PEAR_LOG_INFO', 6); /* Informational */
17 define('PEAR_LOG_DEBUG', 7); /* Debug-level messages */
18 
19 define('PEAR_LOG_ALL', 0xffffffff); /* All messages */
20 define('PEAR_LOG_NONE', 0x00000000); /* No message */
21 
22 /* Log types for PHP's native error_log() function. */
23 define('PEAR_LOG_TYPE_SYSTEM', 0); /* Use PHP's system logger */
24 define('PEAR_LOG_TYPE_MAIL', 1); /* Use PHP's mail() function */
25 define('PEAR_LOG_TYPE_DEBUG', 2); /* Use PHP's debugging connection */
26 define('PEAR_LOG_TYPE_FILE', 3); /* Append to a file */
27 
37 class Log
38 {
45  var $_opened = false;
46 
53  var $_id = 0;
54 
61  var $_ident = '';
62 
70 
78 
85  var $_listeners = array();
86 
94  var $_formatMap = array('%{timestamp}' => '%1$s',
95  '%{ident}' => '%2$s',
96  '%{priority}' => '%3$s',
97  '%{message}' => '%4$s',
98  '%{file}' => '%5$s',
99  '%{line}' => '%6$s',
100  '%{function}' => '%7$s',
101  '%{class}' => '%8$s',
102  '%\{' => '%%{');
103 
117  function _classExists($class)
118  {
119  if (version_compare(PHP_VERSION, '5.0.0', 'ge')) {
120  return class_exists($class, false);
121  }
122 
123  return class_exists($class);
124  }
125 
151  function &factory($handler, $name = '', $ident = '', $conf = array(),
152  $level = PEAR_LOG_DEBUG)
153  {
154  $handler = strtolower($handler);
155  $class = 'Log_' . $handler;
156  $classfile = 'Log/' . $handler . '.php';
157 
158  /*
159  * Attempt to include our version of the named class, but don't treat
160  * a failure as fatal. The caller may have already included their own
161  * version of the named class.
162  */
163  if (!Log::_classExists($class)) {
164  include_once $classfile;
165  }
166 
167  /* If the class exists, return a new instance of it. */
168  if (Log::_classExists($class)) {
169  $obj = new $class($name, $ident, $conf, $level);
170  return $obj;
171  }
172 
173  $null = null;
174  return $null;
175  }
176 
213  function &singleton($handler, $name = '', $ident = '', $conf = array(),
214  $level = PEAR_LOG_DEBUG)
215  {
216  static $instances;
217  if (!isset($instances)) $instances = array();
218 
219  $signature = serialize(array($handler, $name, $ident, $conf, $level));
220  if (!isset($instances[$signature])) {
221  $instances[$signature] = &Log::factory($handler, $name, $ident,
222  $conf, $level);
223  }
224 
225  return $instances[$signature];
226  }
227 
232  function open()
233  {
234  return false;
235  }
236 
241  function close()
242  {
243  return false;
244  }
245 
250  function flush()
251  {
252  return false;
253  }
254 
259  function log($message, $priority = null)
260  {
261  return false;
262  }
263 
276  function emerg($message)
277  {
278  return $this->log($message, PEAR_LOG_EMERG);
279  }
280 
293  function alert($message)
294  {
295  return $this->log($message, PEAR_LOG_ALERT);
296  }
297 
310  function crit($message)
311  {
312  return $this->log($message, PEAR_LOG_CRIT);
313  }
314 
327  function err($message)
328  {
329  return $this->log($message, PEAR_LOG_ERR);
330  }
331 
344  function warning($message)
345  {
346  return $this->log($message, PEAR_LOG_WARNING);
347  }
348 
361  function notice($message)
362  {
363  return $this->log($message, PEAR_LOG_NOTICE);
364  }
365 
378  function info($message)
379  {
380  return $this->log($message, PEAR_LOG_INFO);
381  }
382 
395  function debug($message)
396  {
397  return $this->log($message, PEAR_LOG_DEBUG);
398  }
399 
417  function _extractMessage($message)
418  {
419  /*
420  * If we've been given an object, attempt to extract the message using
421  * a known method. If we can't find such a method, default to the
422  * "human-readable" version of the object.
423  *
424  * We also use the human-readable format for arrays.
425  */
426  if (is_object($message)) {
427  if (method_exists($message, 'getmessage')) {
428  $message = $message->getMessage();
429  } else if (method_exists($message, 'tostring')) {
430  $message = $message->toString();
431  } else if (method_exists($message, '__tostring')) {
432  if (version_compare(PHP_VERSION, '5.0.0', 'ge')) {
433  $message = (string)$message;
434  } else {
435  $message = $message->__toString();
436  }
437  } else {
438  $message = var_export($message, true);
439  }
440  } else if (is_array($message)) {
441  if (isset($message['message'])) {
442  if (is_scalar($message['message'])) {
443  $message = $message['message'];
444  } else {
445  $message = var_export($message['message'], true);
446  }
447  } else {
448  $message = var_export($message, true);
449  }
450  } else if (is_bool($message) || $message === NULL) {
451  $message = var_export($message, true);
452  }
453 
454  /* Otherwise, we assume the message is a string. */
455  return $message;
456  }
457 
472  function _getBacktraceVars($depth)
473  {
474  /* Start by generating a backtrace from the current call (here). */
475  $bt = debug_backtrace();
476 
477  /*
478  * If we were ultimately invoked by the composite handler, we need to
479  * increase our depth one additional level to compensate.
480  */
481  $class = isset($bt[$depth+1]['class']) ? $bt[$depth+1]['class'] : null;
482  if ($class !== null && strcasecmp($class, 'Log_composite') == 0) {
483  $depth++;
484  $class = isset($bt[$depth + 1]) ? $bt[$depth + 1]['class'] : null;
485  }
486 
487  /*
488  * We're interested in the frame which invoked the log() function, so
489  * we need to walk back some number of frames into the backtrace. The
490  * $depth parameter tells us where to start looking. We go one step
491  * further back to find the name of the encapsulating function from
492  * which log() was called.
493  */
494  $file = isset($bt[$depth]) ? $bt[$depth]['file'] : null;
495  $line = isset($bt[$depth]) ? $bt[$depth]['line'] : 0;
496  $func = isset($bt[$depth + 1]) ? $bt[$depth + 1]['function'] : null;
497 
498  /*
499  * However, if log() was called from one of our "shortcut" functions,
500  * we're going to need to go back an additional step.
501  */
502  if (in_array($func, array('emerg', 'alert', 'crit', 'err', 'warning',
503  'notice', 'info', 'debug'))) {
504  $file = isset($bt[$depth + 1]) ? $bt[$depth + 1]['file'] : null;
505  $line = isset($bt[$depth + 1]) ? $bt[$depth + 1]['line'] : 0;
506  $func = isset($bt[$depth + 2]) ? $bt[$depth + 2]['function'] : null;
507  }
508 
509  /*
510  * If we couldn't extract a function name (perhaps because we were
511  * executed from the "main" context), provide a default value.
512  */
513  if (is_null($func)) {
514  $func = '(none)';
515  }
516 
517  /* Return a 4-tuple containing (file, line, function, class). */
518  return array($file, $line, $func, $class);
519  }
520 
530  function _format($format, $timestamp, $priority, $message)
531  {
532  /*
533  * If the format string references any of the backtrace-driven
534  * variables (%5 %6,%7,%8), generate the backtrace and fetch them.
535  */
536  if (preg_match('/%[5678]/', $format)) {
537  list($file, $line, $func, $class) = $this->_getBacktraceVars(2);
538  }
539 
540  /*
541  * Build the formatted string. We use the sprintf() function's
542  * "argument swapping" capability to dynamically select and position
543  * the variables which will ultimately appear in the log string.
544  */
545  return sprintf($format,
546  $timestamp,
547  $this->_ident,
548  $this->priorityToString($priority),
549  $message,
550  isset($file) ? $file : '',
551  isset($line) ? $line : '',
552  isset($func) ? $func : '',
553  isset($class) ? $class : '');
554  }
555 
566  function priorityToString($priority)
567  {
568  $levels = array(
569  PEAR_LOG_EMERG => 'emergency',
570  PEAR_LOG_ALERT => 'alert',
571  PEAR_LOG_CRIT => 'critical',
572  PEAR_LOG_ERR => 'error',
573  PEAR_LOG_WARNING => 'warning',
574  PEAR_LOG_NOTICE => 'notice',
575  PEAR_LOG_INFO => 'info',
576  PEAR_LOG_DEBUG => 'debug'
577  );
578 
579  return $levels[$priority];
580  }
581 
595  function stringToPriority($name)
596  {
597  $levels = array(
598  'emergency' => PEAR_LOG_EMERG,
599  'alert' => PEAR_LOG_ALERT,
600  'critical' => PEAR_LOG_CRIT,
601  'error' => PEAR_LOG_ERR,
602  'warning' => PEAR_LOG_WARNING,
603  'notice' => PEAR_LOG_NOTICE,
604  'info' => PEAR_LOG_INFO,
605  'debug' => PEAR_LOG_DEBUG
606  );
607 
608  return $levels[strtolower($name)];
609  }
610 
623  function MASK($priority)
624  {
625  return (1 << $priority);
626  }
627 
642  function UPTO($priority)
643  {
644  return Log::MAX($priority);
645  }
646 
661  function MIN($priority)
662  {
663  return PEAR_LOG_ALL ^ ((1 << $priority) - 1);
664  }
665 
680  function MAX($priority)
681  {
682  return ((1 << ($priority + 1)) - 1);
683  }
684 
695  function setMask($mask)
696  {
697  $this->_mask = $mask;
698 
699  return $this->_mask;
700  }
701 
710  function getMask()
711  {
712  return $this->_mask;
713  }
714 
726  function _isMasked($priority)
727  {
728  return (Log::MASK($priority) & $this->_mask);
729  }
730 
739  function getPriority()
740  {
741  return $this->_priority;
742  }
743 
752  function setPriority($priority)
753  {
754  $this->_priority = $priority;
755  }
756 
769  function attach(&$observer)
770  {
771  if (!is_a($observer, 'Log_observer')) {
772  return false;
773  }
774 
775  $this->_listeners[$observer->_id] = &$observer;
776 
777  return true;
778  }
779 
791  function detach($observer)
792  {
793  if (!is_a($observer, 'Log_observer') ||
794  !isset($this->_listeners[$observer->_id])) {
795  return false;
796  }
797 
798  unset($this->_listeners[$observer->_id]);
799 
800  return true;
801  }
802 
811  function _announce($event)
812  {
813  foreach ($this->_listeners as $id => $listener) {
814  if ($event['priority'] <= $this->_listeners[$id]->_priority) {
815  $this->_listeners[$id]->notify($event);
816  }
817  }
818  }
819 
828  function isComposite()
829  {
830  return false;
831  }
832 
841  function setIdent($ident)
842  {
843  $this->_ident = $ident;
844  }
845 
854  function getIdent()
855  {
856  return $this->_ident;
857  }
858 }