1<?php 2 3namespace dokuwiki; 4 5class Logger 6{ 7 const LOG_ERROR = 'error'; 8 const LOG_DEPRECATED = 'deprecated'; 9 const LOG_DEBUG = 'debug'; 10 11 /** @var Logger[] */ 12 static protected $instances; 13 14 /** @var string what kind of log is this */ 15 protected $facility; 16 17 /** 18 * Logger constructor. 19 * 20 * @param string $facility The type of log 21 */ 22 protected function __construct($facility) 23 { 24 $this->facility = $facility; 25 } 26 27 /** 28 * Return a Logger instance for the given facility 29 * 30 * @param string $facility The type of log 31 * @return Logger 32 */ 33 static public function getInstance($facility = self::LOG_ERROR) 34 { 35 if (self::$instances[$facility] === null) { 36 self::$instances[$facility] = new Logger($facility); 37 } 38 return self::$instances[$facility]; 39 } 40 41 /** 42 * Convenience method to directly log to the error log 43 * 44 * @param string $message The log message 45 * @param mixed $details Any details that should be added to the log entry 46 * @param string $file A source filename if this is related to a source position 47 * @param int $line A line number for the above file 48 * @return bool 49 */ 50 static public function error($message, $details = null, $file = '', $line = 0) 51 { 52 return self::getInstance(self::LOG_ERROR)->log( 53 $message, $details, $file, $line 54 ); 55 } 56 57 /** 58 * Convenience method to directly log to the debug log 59 * 60 * @param string $message The log message 61 * @param mixed $details Any details that should be added to the log entry 62 * @param string $file A source filename if this is related to a source position 63 * @param int $line A line number for the above file 64 * @return bool 65 */ 66 static public function debug($message, $details = null, $file = '', $line = 0) 67 { 68 return self::getInstance(self::LOG_DEBUG)->log( 69 $message, $details, $file, $line 70 ); 71 } 72 73 /** 74 * Convenience method to directly log to the deprecation log 75 * 76 * @param string $message The log message 77 * @param mixed $details Any details that should be added to the log entry 78 * @param string $file A source filename if this is related to a source position 79 * @param int $line A line number for the above file 80 * @return bool 81 */ 82 static public function deprecated($message, $details = null, $file = '', $line = 0) 83 { 84 return self::getInstance(self::LOG_DEPRECATED)->log( 85 $message, $details, $file, $line 86 ); 87 } 88 89 /** 90 * Log a message to the facility log 91 * 92 * @param string $message The log message 93 * @param mixed $details Any details that should be added to the log entry 94 * @param string $file A source filename if this is related to a source position 95 * @param int $line A line number for the above file 96 * @return bool 97 */ 98 public function log($message, $details = null, $file = '', $line = 0) 99 { 100 // details are logged indented 101 if ($details) { 102 if (!is_string($details)) { 103 $details = json_encode($details, JSON_PRETTY_PRINT); 104 } 105 $details = explode("\n", $details); 106 $loglines = array_map(function ($line) { 107 return ' ' . $line; 108 }, $details); 109 } elseif ($details) { 110 $loglines = [$details]; 111 } else { 112 $loglines = []; 113 } 114 115 // datetime, fileline, message 116 $logline = gmdate('Y-m-d H:i:s') . "\t"; 117 if ($file) { 118 $logline .= $file; 119 if ($line) $logline .= "($line)"; 120 } 121 $logline .= "\t" . $message; 122 123 array_unshift($loglines, $logline); 124 return $this->writeLogLines($loglines); 125 } 126 127 /** 128 * Construct the log file for the given day 129 * 130 * @param false|string|int $date Date to access, false for today 131 * @return string 132 */ 133 public function getLogfile($date = false) 134 { 135 global $conf; 136 137 if ($date !== null) $date = strtotime($date); 138 if (!$date) $date = time(); 139 140 return $conf['logdir'] . '/' . $this->facility . '/' . date('Y-m-d', $date) . '.log'; 141 } 142 143 /** 144 * Write the given lines to today's facility log 145 * 146 * @param string[] $lines the raw lines to append to the log 147 * @return bool true if the log was written 148 */ 149 protected function writeLogLines($lines) 150 { 151 $logfile = $this->getLogfile(); 152 return io_saveFile($logfile, join("\n", $lines) . "\n", true); 153 } 154} 155