Passed
Push — master ( 8ff3c7...b0cf05 )
by Damiano
02:24
created

StandardFormatter::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
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 $format
21
     */
22
    private $format = '[{date}] {name}.{level}: {message} [{context}] [{exception}]';
23
24
    /**
25
     * @var string dateFormat
26
     */
27
    private $dateFormat;
28
29
    /**
30
     * StandardFormatter constructor.
31
     *
32
     * @param string $dateFormat
33
     */
34 2
    public function __construct($dateFormat = 'Y-m-d H:i:s')
35
    {
36 2
        $this->dateFormat = $dateFormat;
37 2
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42 4
    public function interpolate(string $name, string $level, string $message, array $context = []): string
43
    {
44 4
        foreach ($context as $key => $value) {
45
46
            // If in the context array there's a key with an \Exception as value
47 3
            if ($key === 'exception' && $value instanceof Exception) {
48
                // Get the full error trace as string
49 1
                $exceptionTrace = '';
50 1
                while ($previous??true) {
51
                    // Create the trace string
52 1
                    $exceptionTrace .= "( " . get_class($value) . ": (code:  {$value->getCode()} ):  {$value->getMessage()}  at  {$value->getFile()} : {$value->getLine()}),";
53
                    // If there's no previous exception, stop the loop
54 1
                    if (!$value = $value->getPrevious()) {
55 1
                        $previous = false;
56
                    }
57
                }
58
                // Trim the last comma and remove all the break lines
59 1
                $exceptionTrace = str_replace(PHP_EOL, ' ', rtrim($exceptionTrace, ','));
60
                // Remove from the context and continue
61 1
                unset($context[$key]);
62 1
                continue;
63
            }
64
65
            // If the value isn't an array and is an object with a toString method
66 2
            if (!is_array($value) || (is_object($value) && method_exists($value, '__toString'))) {
67
                // If in the message there's a placeholder (represented as {key}) replace it with the value,
68
                // remove from the context and continue
69 2
                if (strpos($message, '{' . $key . '}') !== false) {
70 1
                    $message = str_replace('{' . $key . '}', "$value", $message);
71 1
                    unset($context[$key]);
72
                }
73
            }
74
        }
75
76
        // Handle the string to replace (empty if is not set)
77 4
        $context = count($context) > 0 ? json_encode($context) : '';
78 4
        $exceptionTrace = $exceptionTrace ?? '';
79
80
        // Replace and return the log line
81 4
        $data = str_replace(
82 4
            ['{date}', '{name}', '{level}', '{context}', '{exception}', '{message}'],
83 4
            [$this->getTimestampFromImmutable(), $name, $level, $context, $exceptionTrace, $message],
84 4
            $this->format
85
        );
86
87 4
        return $data;
88
    }
89
90
    /**
91
     * Return a timestamp for logger
92
     * (Is a specific method for a better testability)
93
     *
94
     * @return string
95
     */
96 1
    protected function getTimestampFromImmutable(): string
97
    {
98 1
        $date = new \DateTimeImmutable('now', new \DateTimeZone('utc'));
99
100 1
        return $date->format($this->dateFormat);
101
    }
102
}