10ecde6ceSAndreas Gohr<?php 20ecde6ceSAndreas Gohr 30ecde6ceSAndreas Gohrnamespace dokuwiki; 40ecde6ceSAndreas Gohr 50ecde6ceSAndreas Gohrclass Logger 60ecde6ceSAndreas Gohr{ 70ecde6ceSAndreas Gohr const LOG_ERROR = 'error'; 80ecde6ceSAndreas Gohr const LOG_DEPRECATED = 'deprecated'; 90ecde6ceSAndreas Gohr const LOG_DEBUG = 'debug'; 100ecde6ceSAndreas Gohr 110ecde6ceSAndreas Gohr /** @var Logger[] */ 120ecde6ceSAndreas Gohr static protected $instances; 130ecde6ceSAndreas Gohr 140ecde6ceSAndreas Gohr /** @var string what kind of log is this */ 150ecde6ceSAndreas Gohr protected $facility; 160ecde6ceSAndreas Gohr 170ecde6ceSAndreas Gohr /** 180ecde6ceSAndreas Gohr * Logger constructor. 190ecde6ceSAndreas Gohr * 200ecde6ceSAndreas Gohr * @param string $facility The type of log 210ecde6ceSAndreas Gohr */ 220ecde6ceSAndreas Gohr protected function __construct($facility) 230ecde6ceSAndreas Gohr { 240ecde6ceSAndreas Gohr $this->facility = $facility; 250ecde6ceSAndreas Gohr } 260ecde6ceSAndreas Gohr 270ecde6ceSAndreas Gohr /** 280ecde6ceSAndreas Gohr * Return a Logger instance for the given facility 290ecde6ceSAndreas Gohr * 300ecde6ceSAndreas Gohr * @param string $facility The type of log 310ecde6ceSAndreas Gohr * @return Logger 320ecde6ceSAndreas Gohr */ 330ecde6ceSAndreas Gohr static public function getInstance($facility = self::LOG_ERROR) 340ecde6ceSAndreas Gohr { 350ecde6ceSAndreas Gohr if (self::$instances[$facility] === null) { 360ecde6ceSAndreas Gohr self::$instances[$facility] = new Logger($facility); 370ecde6ceSAndreas Gohr } 380ecde6ceSAndreas Gohr return self::$instances[$facility]; 390ecde6ceSAndreas Gohr } 400ecde6ceSAndreas Gohr 410ecde6ceSAndreas Gohr /** 42*c2050393SAndreas Gohr * Convenience method to directly log to the error log 43*c2050393SAndreas Gohr * 44*c2050393SAndreas Gohr * @param string $message The log message 45*c2050393SAndreas Gohr * @param mixed $details Any details that should be added to the log entry 46*c2050393SAndreas Gohr * @param string $file A source filename if this is related to a source position 47*c2050393SAndreas Gohr * @param int $line A line number for the above file 48*c2050393SAndreas Gohr * @return bool 49*c2050393SAndreas Gohr */ 50*c2050393SAndreas Gohr static public function error($message, $details = null, $file = '', $line = 0) 51*c2050393SAndreas Gohr { 52*c2050393SAndreas Gohr return self::getInstance(self::LOG_ERROR)->log( 53*c2050393SAndreas Gohr $message, $details, $file, $line 54*c2050393SAndreas Gohr ); 55*c2050393SAndreas Gohr } 56*c2050393SAndreas Gohr 57*c2050393SAndreas Gohr /** 58*c2050393SAndreas Gohr * Convenience method to directly log to the debug log 59*c2050393SAndreas Gohr * 60*c2050393SAndreas Gohr * @param string $message The log message 61*c2050393SAndreas Gohr * @param mixed $details Any details that should be added to the log entry 62*c2050393SAndreas Gohr * @param string $file A source filename if this is related to a source position 63*c2050393SAndreas Gohr * @param int $line A line number for the above file 64*c2050393SAndreas Gohr * @return bool 65*c2050393SAndreas Gohr */ 66*c2050393SAndreas Gohr static public function debug($message, $details = null, $file = '', $line = 0) 67*c2050393SAndreas Gohr { 68*c2050393SAndreas Gohr return self::getInstance(self::LOG_DEBUG)->log( 69*c2050393SAndreas Gohr $message, $details, $file, $line 70*c2050393SAndreas Gohr ); 71*c2050393SAndreas Gohr } 72*c2050393SAndreas Gohr 73*c2050393SAndreas Gohr /** 74*c2050393SAndreas Gohr * Convenience method to directly log to the deprecation log 75*c2050393SAndreas Gohr * 76*c2050393SAndreas Gohr * @param string $message The log message 77*c2050393SAndreas Gohr * @param mixed $details Any details that should be added to the log entry 78*c2050393SAndreas Gohr * @param string $file A source filename if this is related to a source position 79*c2050393SAndreas Gohr * @param int $line A line number for the above file 80*c2050393SAndreas Gohr * @return bool 81*c2050393SAndreas Gohr */ 82*c2050393SAndreas Gohr static public function deprecated($message, $details = null, $file = '', $line = 0) 83*c2050393SAndreas Gohr { 84*c2050393SAndreas Gohr return self::getInstance(self::LOG_DEPRECATED)->log( 85*c2050393SAndreas Gohr $message, $details, $file, $line 86*c2050393SAndreas Gohr ); 87*c2050393SAndreas Gohr } 88*c2050393SAndreas Gohr 89*c2050393SAndreas Gohr /** 900ecde6ceSAndreas Gohr * Log a message to the facility log 910ecde6ceSAndreas Gohr * 920ecde6ceSAndreas Gohr * @param string $message The log message 930ecde6ceSAndreas Gohr * @param mixed $details Any details that should be added to the log entry 940ecde6ceSAndreas Gohr * @param string $file A source filename if this is related to a source position 950ecde6ceSAndreas Gohr * @param int $line A line number for the above file 960ecde6ceSAndreas Gohr * @return bool 970ecde6ceSAndreas Gohr */ 980ecde6ceSAndreas Gohr public function log($message, $details = null, $file = '', $line = 0) 990ecde6ceSAndreas Gohr { 1000ecde6ceSAndreas Gohr // details are logged indented 10170cc2cbfSAndreas Gohr if ($details) { 10270cc2cbfSAndreas Gohr if (!is_string($details)) { 1030ecde6ceSAndreas Gohr $details = json_encode($details, JSON_PRETTY_PRINT); 10470cc2cbfSAndreas Gohr } 1050ecde6ceSAndreas Gohr $details = explode("\n", $details); 1060ecde6ceSAndreas Gohr $loglines = array_map(function ($line) { 1070ecde6ceSAndreas Gohr return ' ' . $line; 1080ecde6ceSAndreas Gohr }, $details); 1090ecde6ceSAndreas Gohr } elseif ($details) { 1100ecde6ceSAndreas Gohr $loglines = [$details]; 1110ecde6ceSAndreas Gohr } else { 1120ecde6ceSAndreas Gohr $loglines = []; 1130ecde6ceSAndreas Gohr } 1140ecde6ceSAndreas Gohr 11570cc2cbfSAndreas Gohr // datetime, fileline, message 11670cc2cbfSAndreas Gohr $logline = gmdate('Y-m-d H:i:s') . "\t"; 1170ecde6ceSAndreas Gohr if ($file) { 11870cc2cbfSAndreas Gohr $logline .= $file; 1190ecde6ceSAndreas Gohr if ($line) $logline .= "($line)"; 1200ecde6ceSAndreas Gohr } 12170cc2cbfSAndreas Gohr $logline .= "\t" . $message; 1220ecde6ceSAndreas Gohr 1230ecde6ceSAndreas Gohr array_unshift($loglines, $logline); 1240ecde6ceSAndreas Gohr return $this->writeLogLines($loglines); 1250ecde6ceSAndreas Gohr } 1260ecde6ceSAndreas Gohr 1270ecde6ceSAndreas Gohr /** 12870cc2cbfSAndreas Gohr * Construct the log file for the given day 12970cc2cbfSAndreas Gohr * 13070cc2cbfSAndreas Gohr * @param false|string|int $date Date to access, false for today 13170cc2cbfSAndreas Gohr * @return string 13270cc2cbfSAndreas Gohr */ 13370cc2cbfSAndreas Gohr public function getLogfile($date = false) 13470cc2cbfSAndreas Gohr { 13570cc2cbfSAndreas Gohr global $conf; 13670cc2cbfSAndreas Gohr 13770cc2cbfSAndreas Gohr if ($date !== null) $date = strtotime($date); 13870cc2cbfSAndreas Gohr if (!$date) $date = time(); 13970cc2cbfSAndreas Gohr 14070cc2cbfSAndreas Gohr return $conf['logdir'] . '/' . $this->facility . '/' . date('Y-m-d', $date) . '.log'; 14170cc2cbfSAndreas Gohr } 14270cc2cbfSAndreas Gohr 14370cc2cbfSAndreas Gohr /** 1440ecde6ceSAndreas Gohr * Write the given lines to today's facility log 1450ecde6ceSAndreas Gohr * 1460ecde6ceSAndreas Gohr * @param string[] $lines the raw lines to append to the log 1470ecde6ceSAndreas Gohr * @return bool true if the log was written 1480ecde6ceSAndreas Gohr */ 1490ecde6ceSAndreas Gohr protected function writeLogLines($lines) 1500ecde6ceSAndreas Gohr { 15170cc2cbfSAndreas Gohr $logfile = $this->getLogfile(); 1520ecde6ceSAndreas Gohr return io_saveFile($logfile, join("\n", $lines) . "\n", true); 1530ecde6ceSAndreas Gohr } 1540ecde6ceSAndreas Gohr} 155