FileLogger   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 170
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 17
eloc 60
c 1
b 0
f 0
dl 0
loc 170
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A serializeContext() 0 3 1
A getTimestamp() 0 3 1
A flush() 0 7 2
A log() 0 16 4
A close() 0 5 2
A formatMessage() 0 12 1
A __construct() 0 40 6
1
<?php
2
3
/**
4
 * PHP version 5.4 and 8
5
 *
6
 * @category  Logger
7
 * @package   Payever\Core
8
 * @author    payever GmbH <[email protected]>
9
 * @author    Hennadii.Shymanskyi <[email protected]>
10
 * @copyright 2017-2021 payever GmbH
11
 * @license   MIT <https://opensource.org/licenses/MIT>
12
 * @link      https://docs.payever.org/shopsystems/api/getting-started
13
 */
14
15
namespace Payever\ExternalIntegration\Core\Logger;
16
17
use Psr\Log\AbstractLogger;
18
use Psr\Log\LogLevel;
19
20
/**
21
 * Class FileLogger
22
 *
23
 * Simple PSR-3 compatible Logger class.
24
 * Recommended for use when there's no advanced logger (e.g. Monolog) provided in user's system.
25
 *
26
 * @SuppressWarnings(PHPMD.MissingImport)
27
 */
28
class FileLogger extends AbstractLogger
29
{
30
    /** @var string */
31
    protected $logFilePath;
32
33
    /** @var resource  */
34
    protected $logFileHandle;
35
36
    /** @var string */
37
    protected $channelName;
38
39
    /** @var int */
40
    protected $logLevelInt;
41
42
    /** @var int */
43
    protected $bufferSize;
44
45
    /** @var array */
46
    protected $buffer = [];
47
48
    /** @var bool */
49
    protected $shutdownRegistered = false;
50
51
    /**
52
     * Log Levels
53
     * @var array
54
     */
55
    protected $logLevels = [
56
        LogLevel::EMERGENCY => 0,
57
        LogLevel::ALERT     => 1,
58
        LogLevel::CRITICAL  => 2,
59
        LogLevel::ERROR     => 3,
60
        LogLevel::WARNING   => 4,
61
        LogLevel::NOTICE    => 5,
62
        LogLevel::INFO      => 6,
63
        LogLevel::DEBUG     => 7
64
    ];
65
66
    /**
67
     * @param string $logFilePath
68
     * @param string $logLevel
69
     * @param string $channelName
70
     * @param int    $bufferSize
71
     */
72
    public function __construct($logFilePath, $logLevel, $channelName = 'payever', $bufferSize = 50)
73
    {
74
        if (!isset($this->logLevels[$logLevel])) {
75
            throw new \InvalidArgumentException(
76
                sprintf("Log level must be one of Psr\Log\LogLevel constants, %s given", $logLevel)
77
            );
78
        }
79
80
        if (!is_readable(dirname($logFilePath))) {
81
            // @codeCoverageIgnoreStart
82
            throw new \UnexpectedValueException(
83
                sprintf("The directory of log file is not readable: %s", $logFilePath)
84
            );
85
            // @codeCoverageIgnoreEnd
86
        }
87
88
        $bufferSize = (int) $bufferSize;
89
90
        if ($bufferSize < 1) {
91
            throw new \InvalidArgumentException(sprintf('Buffer size must be > 0, %d given', $bufferSize));
92
        }
93
94
        if (!file_exists($logFilePath)) {
95
            // @codeCoverageIgnoreStart
96
            touch($logFilePath);
97
            // @codeCoverageIgnoreEnd
98
        }
99
        $this->logFileHandle = fopen($logFilePath, 'a');
100
        if (!$this->logFileHandle) {
101
            // @codeCoverageIgnoreStart
102
            throw new \UnexpectedValueException(
103
                sprintf("Can't open file for writing: %s", $logFilePath)
104
            );
105
            // @codeCoverageIgnoreEnd
106
        }
107
108
        $this->logFilePath = $logFilePath;
109
        $this->logLevelInt = $this->logLevels[$logLevel];
110
        $this->channelName = $channelName;
111
        $this->bufferSize = $bufferSize;
112
    }
113
114
    /**
115
     * @param string $level
116
     * @param string $message
117
     * @param array  $context
118
     */
119
    public function log($level, $message, array $context = [])
120
    {
121
        if ($this->logLevels[$level] > $this->logLevelInt) {
122
            return;
123
        }
124
125
        if (!$this->shutdownRegistered) {
126
            $this->shutdownRegistered = true;
127
            /** __destruct doesn't get called on fatal errors */
128
            register_shutdown_function([$this, 'close']);
129
        }
130
131
        $this->buffer[] = $this->formatMessage($level, $message, $context);
132
133
        if (count($this->buffer) === $this->bufferSize) {
134
            $this->flush();
135
        }
136
    }
137
138
    /**
139
     * register_shutdown_function handler
140
     */
141
    public function close()
142
    {
143
        $this->flush();
144
145
        is_resource($this->logFileHandle) && fclose($this->logFileHandle);
146
    }
147
148
    /**
149
     * Actually writes collected messages into file
150
     */
151
    protected function flush()
152
    {
153
        foreach ($this->buffer as $message) {
154
            fwrite($this->logFileHandle, $message);
155
        }
156
157
        $this->buffer = [];
158
    }
159
160
    /**
161
     * @param string $level
162
     * @param string $message
163
     * @param array  $context
164
     *
165
     * @return string
166
     */
167
    protected function formatMessage($level, $message, array $context)
168
    {
169
        $level = strtoupper($level);
170
171
        return sprintf(
172
            '[%s] %s.%s: %s %s%s',
173
            $this->getTimestamp(),
174
            $this->channelName,
175
            $level,
176
            $message,
177
            $this->serializeContext($context),
178
            PHP_EOL
179
        );
180
    }
181
182
    /**
183
     * @param array $context
184
     *
185
     * @return string
186
     */
187
    protected function serializeContext(array $context)
188
    {
189
        return json_encode($context, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
190
    }
191
192
    /**
193
     * @return string
194
     */
195
    protected function getTimestamp()
196
    {
197
        return date('Y-m-d H:i:s');
198
    }
199
}
200