xref: /dokuwiki/inc/Logger.php (revision 31667ec67823633de149106f2f0de3f1dbc5fd1e)
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