Passed
Push — develop ( 899798...74e1f6 )
by nguereza
02:00
created

Logger::setFormatter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Platine Logger
5
 *
6
 * Platine Logger is the implementation of PSR 3
7
 *
8
 * This content is released under the MIT License (MIT)
9
 *
10
 * Copyright (c) 2020 Platine Logger
11
 *
12
 * Permission is hereby granted, free of charge, to any person obtaining a copy
13
 * of this software and associated documentation files (the "Software"), to deal
14
 * in the Software without restriction, including without limitation the rights
15
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
 * copies of the Software, and to permit persons to whom the Software is
17
 * furnished to do so, subject to the following conditions:
18
 *
19
 * The above copyright notice and this permission notice shall be included in all
20
 * copies or substantial portions of the Software.
21
 *
22
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
 * SOFTWARE.
29
 */
30
31
/**
32
 *  @file Logger.php
33
 *
34
 *  The Logger class is the main class to use to handle application log.
35
 *
36
 *  @package    Platine\Logger
37
 *  @author Platine Developers Team
38
 *  @copyright  Copyright (c) 2020
39
 *  @license    http://opensource.org/licenses/MIT  MIT License
40
 *  @link   http://www.iacademy.cf
41
 *  @version 1.0.0
42
 *  @filesource
43
 */
44
45
declare(strict_types=1);
46
47
namespace Platine\Logger;
48
49
use Exception;
50
use Platine\Logger\Formatter\DefaultFormatter;
51
use Platine\Logger\Handler\NullHandler;
52
53
/**
54
 * Class Logger
55
 * @package Platine\Logger
56
 */
57
class Logger implements LoggerInterface
58
{
59
    /**
60
     * Special minimum log level which will not log any log levels.
61
     */
62
    public const LOG_LEVEL_NONE = 'none';
63
64
    /**
65
     * The list of logger handler
66
     * @var array<string, LoggerHandlerInterface>
67
     */
68
    protected array $handlers = [];
69
70
    /**
71
     * Log level hierarchy
72
     * @var array<string, int>
73
     */
74
    protected array $levels = [
75
        self::LOG_LEVEL_NONE => 999,
76
        LogLevel::DEBUG => 0,
77
        LogLevel::INFO => 1,
78
        LogLevel::NOTICE => 2,
79
        LogLevel::WARNING => 3,
80
        LogLevel::ERROR => 4,
81
        LogLevel::CRITICAL => 5,
82
        LogLevel::ALERT => 6,
83
        LogLevel::EMERGENCY => 7,
84
    ];
85
86
    /**
87
     * Lowest log level to log.
88
     * @var int
89
     */
90
    protected int $logLevel;
91
92
    /**
93
     * Channel used to identify each log message
94
     * @var string
95
     */
96
    protected string $channel = 'MAIN';
97
98
    /**
99
     * The configuration to use
100
     * @var Configuration
101
     */
102
    protected Configuration $config;
103
104
    /**
105
     * Logger formatter to be used
106
     * @var LoggerFormatterInterface
107
     */
108
    protected LoggerFormatterInterface $formatter;
109
110
    /**
111
     * Create new logger instance
112
     *
113
     * @param Configuration|null $config the configuration to use
114
     * @param LoggerFormatterInterface|null $formatter the formatter to use
115
     */
116
    public function __construct(
117
        ?Configuration $config = null,
118
        ?LoggerFormatterInterface $formatter = null
119
    ) {
120
        $this->config = $config ?? new Configuration([]);
121
122
        $this->formatter = $formatter ?? new DefaultFormatter();
123
        $level = $this->config->has('level')
124
                ? $this->config->get('level')
125
                : LogLevel::DEBUG;
126
127
        $this->setLevel($level);
0 ignored issues
show
Bug introduced by
It seems like $level can also be of type null; however, parameter $logLevel of Platine\Logger\Logger::setLevel() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

127
        $this->setLevel(/** @scrutinizer ignore-type */ $level);
Loading history...
128
    }
129
130
    /**
131
     * Return the logger formatter
132
     * @return LoggerFormatterInterface
133
     */
134
    public function getFormatter(): LoggerFormatterInterface
135
    {
136
        return $this->formatter;
137
    }
138
139
    /**
140
     * Set logger formatter for future use
141
     * @param LoggerFormatterInterface $formatter
142
     * @return $this
143
     */
144
    public function setFormatter(LoggerFormatterInterface $formatter): self
145
    {
146
        $this->formatter = $formatter;
147
148
        return $this;
149
    }
150
151
152
    /**
153
     * Add logger handler
154
     * @param string $name
155
     * @param LoggerHandlerInterface $handler
156
     * @return $this
157
     */
158
    public function addHandler(string $name, LoggerHandlerInterface $handler): self
159
    {
160
        $this->handlers[$name] = $handler;
161
162
        return $this;
163
    }
164
165
    /**
166
     * Return the list of handlers instance
167
     * @return array<string, LoggerHandlerInterface>
168
     */
169
    public function getHandlers(): array
170
    {
171
        return $this->handlers;
172
    }
173
174
    /**
175
     * Set the minimum log level
176
     *
177
     * @param string $logLevel
178
     *
179
     * @throws Exception
180
     *
181
     * @return $this
182
     */
183
    public function setLevel(string $logLevel): self
184
    {
185
        if (!array_key_exists($logLevel, $this->levels)) {
186
            throw new Exception(sprintf(
187
                'Log level [%s] is not a valid log level. '
188
                . 'Must be one of (%s)',
189
                $logLevel,
190
                implode(', ', array_keys($this->levels))
191
            ));
192
        }
193
        $this->logLevel = $this->levels[$logLevel];
194
195
        return $this;
196
    }
197
198
    /**
199
     * Set log channel
200
     *
201
     * @param string $channel
202
     *
203
     * @return self
204
     */
205
    public function setChannel(string $channel): self
206
    {
207
        $this->channel = $channel;
208
209
        return $this;
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215
    public function emergency(string $message, array $context = []): void
216
    {
217
        $this->log(LogLevel::EMERGENCY, $message, $context);
218
    }
219
220
    /**
221
     * {@inheritdoc}
222
     */
223
    public function alert(string $message, array $context = []): void
224
    {
225
        $this->log(LogLevel::ALERT, $message, $context);
226
    }
227
228
    /**
229
     * {@inheritdoc}
230
     */
231
    public function critical(string $message, array $context = []): void
232
    {
233
        $this->log(LogLevel::CRITICAL, $message, $context);
234
    }
235
236
    /**
237
     * {@inheritdoc}
238
     */
239
    public function error(string $message, array $context = []): void
240
    {
241
        $this->log(LogLevel::ERROR, $message, $context);
242
    }
243
244
    /**
245
     * {@inheritdoc}
246
     */
247
    public function warning(string $message, array $context = []): void
248
    {
249
        $this->log(LogLevel::WARNING, $message, $context);
250
    }
251
252
    /**
253
     * {@inheritdoc}
254
     */
255
    public function notice(string $message, array $context = []): void
256
    {
257
        $this->log(LogLevel::NOTICE, $message, $context);
258
    }
259
260
    /**
261
     * {@inheritdoc}
262
     */
263
    public function info(string $message, array $context = []): void
264
    {
265
        $this->log(LogLevel::INFO, $message, $context);
266
    }
267
268
    /**
269
     * {@inheritdoc}
270
     */
271
    public function debug(string $message, array $context = []): void
272
    {
273
        $this->log(LogLevel::DEBUG, $message, $context);
274
    }
275
276
    /**
277
     * {@inheritdoc}
278
     */
279
    public function log(string $level, string $message, array $context = []): void
280
    {
281
        $msg = $this->formatter->format(
282
            $level,
283
            $message,
284
            $context,
285
            $this->channel
286
        );
287
288
        foreach ($this->handlers as $name => $handler) {
289
            if ($this->handlerCanLog($name, $level)) {
290
                $handler->log($msg);
291
            }
292
        }
293
    }
294
295
    /**
296
     * Whether the given handler can log
297
     * @param string $name
298
     * @param string $level
299
     * @return bool
300
     */
301
    protected function handlerCanLog(string $name, string $level): bool
302
    {
303
        $key = 'handlers.' . $name;
304
        $currentLevel = $this->logLevel;
305
        $logLevel = $this->levels[$level];
306
307
        if ($this->config->has($key)) {
308
            $handler = $this->config->get($key);
309
            $handlerLevel = $handler['level'] ?? $this->config->get('level');
310
311
            $currentLevel = $this->levels[$handlerLevel];
312
        }
313
314
        return $logLevel >= $currentLevel;
315
    }
316
}
317