SimpleLogger::getMessages()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Test\Support\Log;
6
7
use Psr\Log\InvalidArgumentException;
8
use Psr\Log\LoggerInterface;
9
use Psr\Log\LoggerTrait;
10
use Psr\Log\LogLevel;
11
use Stringable;
12
13
use function gettype;
14
use function implode;
15
use function is_string;
16
use function preg_replace_callback;
17
use function sprintf;
18
19
final class SimpleLogger implements LoggerInterface
20
{
21
    use LoggerTrait;
22
23
    /**
24
     * The list of log message levels. See {@see LogLevel} constants for valid level names.
25
     */
26
    private const LEVELS = [
27
        LogLevel::EMERGENCY,
28
        LogLevel::ALERT,
29
        LogLevel::CRITICAL,
30
        LogLevel::ERROR,
31
        LogLevel::WARNING,
32
        LogLevel::NOTICE,
33
        LogLevel::INFO,
34
        LogLevel::DEBUG,
35
    ];
36
37
    /**
38
     * @var array[] The log messages.
39
     */
40
    private array $messages = [];
41
42
    /**
43
     * Logs a message in an array {@see $messages}.
44
     *
45
     * To get all the log messages, use the {@see getMessages()} method.
46
     *
47
     * @param mixed $level The log message level.
48
     * @param string|Stringable $message The log message.
49
     * @param array $context The log message context.
50
     */
51 13
    public function log(mixed $level, string|Stringable $message, array $context = []): void
52
    {
53 13
        if (!is_string($level)) {
54 7
            throw new InvalidArgumentException(sprintf(
55 7
                'The log message level must be a string, %s provided.',
56 7
                gettype($level)
57 7
            ));
58
        }
59
60 6
        if (!in_array($level, self::LEVELS, true)) {
61 1
            throw new InvalidArgumentException(sprintf(
62 1
                'Invalid log message level "%s" provided. The following values are supported: "%s".',
63 1
                $level,
64 1
                implode('", "', self::LEVELS)
65 1
            ));
66
        }
67
68 5
        $message = $this->parseMessage((string)$message, $context);
69
70 5
        $this->messages[] = ['level' => $level, 'message' => $message, 'context' => $context];
71
    }
72
73
    /**
74
     * Returns all log messages.
75
     *
76
     * @return array[] All log messages.
77
     */
78 5
    public function getMessages(): array
79
    {
80 5
        return $this->messages;
81
    }
82
83
    /**
84
     * Parses log message resolving placeholders in the form: "{foo}",
85
     * where foo will be replaced by the context data in key "foo".
86
     *
87
     * @param string $message Raw log message.
88
     * @param array $context Message context.
89
     *
90
     * @return string Parsed message.
91
     *
92
     * @psalm-suppress MixedArgumentTypeCoercion
93
     * @psalm-suppress MixedArrayOffset
94
     * @psalm-suppress MixedAssignment
95
     */
96 5
    private function parseMessage(string $message, array $context): string
97
    {
98
        /**
99
         * @var string We use correct regular expression, so we expect that `preg_replace_callback` always returns
100
         * string.
101
         */
102 5
        return preg_replace_callback('/{([\w.]+)}/', static function (array $matches) use ($context) {
103 3
            $placeholderName = $matches[1];
104
105 3
            if (isset($context[$placeholderName])) {
106 1
                return (string) $context[$placeholderName];
107
            }
108
109 2
            return $matches[0];
110 5
        }, $message);
111
    }
112
}
113