StandardFormatter::getTimestampFromImmutable()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
ccs 1
cts 1
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Moon\Logger\Formatter;
6
7
use Exception;
8
9
class StandardFormatter implements FormatterInterface
10
{
11
    /**
12
     * The string to return is composed by some placeholders
13
     * {date} timestamp of the log
14
     * {name} logger name
15
     * {level} log level
16
     * {message} message to log (can contains placeholder too)
17
     * {context} un-replaced variables
18
     * {exception} exception trace.
19
     *
20
     * @var string
21
     */
22
    private $format = '[{date}] {name}.{level}: {message} [{context}] [{exception}]';
23
24
    /**
25
     * @var string dateFormat
26
     */
27
    private $dateFormat;
28
29
    public function __construct($dateFormat = 'Y-m-d H:i:s')
30
    {
31
        $this->dateFormat = $dateFormat;
32
    }
33
34 2
    public function interpolate(string $name, string $level, string $message, array $context = []): string
35
    {
36 2
        foreach ($context as $key => $value) {
37 2
            // If in the context array there's a key with an \Exception as value
38
            if ('exception' === $key && $value instanceof Exception) {
39
                // Get the full error trace as string
40
                $exceptionTrace = '';
41
                while ($previous ?? true) {
42 4
                    // Create the trace string
43
                    $exceptionTrace .= '( '.\get_class($value).": (code:  {$value->getCode()} ):  {$value->getMessage()}  at  {$value->getFile()} : {$value->getLine()}),";
44 4
                    // If there's no previous exception, stop the loop
45
                    if (!$value = $value->getPrevious()) {
46
                        $previous = false;
47 3
                    }
48
                }
49 1
                // Trim the last comma and remove all the break lines
50 1
                $exceptionTrace = \str_replace(PHP_EOL, ' ', \rtrim($exceptionTrace, ','));
51
                // Remove from the context and continue
52 1
                unset($context[$key]);
53
                continue;
54 1
            }
55 1
56
            // If the value isn't an array and is an object with a toString method
57
            if ((!\is_array($value) || (\is_object($value) && \method_exists($value, '__toString'))) && false !== \mb_strpos($message, '{'.$key.'}')) {
58
                // If in the message there's a placeholder (represented as {key}) replace it with the value,
59 1
                // remove from the context and continue
60
                $message = \str_replace('{'.$key.'}', "$value", $message);
61 1
                unset($context[$key]);
62 1
            }
63
        }
64
65
        // Handle the string to replace (empty if is not set)
66 2
        $context = \count($context) > 0 ? \json_encode($context) : '';
67
        $exceptionTrace = $exceptionTrace ?? '';
68
69 1
        // Replace and return the log line
70 1
        $data = \str_replace(
71
            ['{date}', '{name}', '{level}', '{context}', '{exception}', '{message}'],
72
            [$this->getTimestampFromImmutable(), $name, $level, $context, $exceptionTrace, $message],
73
            $this->format
74
        );
75 4
76 4
        return $data;
77
    }
78
79 4
    /**
80 4
     * Return a timestamp for logger
81 4
     * (Is a specific method for a better testability).
82 4
     */
83
    protected function getTimestampFromImmutable(): string
84
    {
85 4
        $date = new \DateTimeImmutable('now', new \DateTimeZone('utc'));
86
87
        return $date->format($this->dateFormat);
88
    }
89
}
90