Code

< 40 %
40-60 %
> 60 %
1
<?php
2
3
namespace WebStream\Log;
4
5
use WebStream\Container\Container;
6
use WebStream\Exception\Extend\LoggerException;
7
use WebStream\IO\File;
8
use WebStream\IO\Writer\SimpleFileWriter;
9
10
/**
11
 * LoggerConfigurationManager
12
 * @author Ryuichi Tanaka
13
 * @since 2016/01/29
14
 * @version 0.7
15
 */
16
class LoggerConfigurationManager
17
{
18
    use LoggerUtils;
19
20
    /**
21
     * @var Container ログ設定コンテナ
22
     */
23
    private Container $logContainer;
24
25
    /**
26
     * @var Container IOコンテナ
27
     */
28
    private Container $ioContainer;
29
30
    /**
31
     * @var array<string> ログ設定情報
32
     */
33
    private $configMap;
34
35
    /**
36
     * Constructor
37 141
     * @param mixed $config ログ設定
38
     * @throws LoggerException
39 141
     */
40
    public function __construct($config)
41
    {
42 141
        if (is_array($config)) {
43 141
            $configMap = $config;
44
        } else {
45
            $configMap = parse_ini_file($config);
46
            if ($configMap === null) {
47
                throw new LoggerException("Log config file does not exist: " . $config);
48 141
            }
49 141
        }
50
51 141
        $this->logContainer = new Container(false);
52 141
        $this->ioContainer = new Container();
53
54
        $this->ioContainer->file = function () use ($configMap) {
55 141
            if (!array_key_exists("path", $configMap)) {
56
                throw new LoggerException("Log path must be defined.");
57 9
            }
58 9
            return new File($configMap["path"]);
59
        };
60
        $this->ioContainer->fileWriter = function () use ($configMap) {
61 141
            return new SimpleFileWriter($configMap["path"]);
62 141
        };
63
64
        $this->configMap = $configMap;
65
    }
66
67
    /**
68 141
     * 設定を読み込む
69
     * @throws LoggerException
70 141
     */
71 141
    public function load()
72 141
    {
73 141
        $this->loadLogLevel()
74 141
             ->loadLogFilePath()
75 141
             ->loadRotateCycle()
76 141
             ->loadRotateSize()
77
             ->loadApplicationName()
78
             ->loadFormat();
79
    }
80
81
    /**
82 141
     * ログ設定を返却する
83
     * @return Container ログ設定
84 141
     */
85
    public function getConfig()
86
    {
87
        return $this->logContainer;
88
    }
89
90
    /**
91 141
     * ログレベルを読み込む
92
     * @throws LoggerException
93 141
     */
94
    private function loadLogLevel()
95
    {
96
        if (!array_key_exists("level", $this->configMap)) {
97 141
            throw new LoggerException("Log level must be defined.");
98 141
        }
99
100 141
        $logLevel = $this->toLogLevelValue($this->configMap["level"]);
101
        $this->logContainer->logLevel = $logLevel;
102
103
        return $this;
104
    }
105
106
    /**
107 141
     * ログ保存先パスを読み込む
108
     * @throws LoggerException
109 141
     */
110 141
    private function loadLogFilePath()
111 9
    {
112
        $file = $this->ioContainer->file;
113
        if (!($file->exists() && $file->isFile())) {
114 141
            $this->ioContainer->fileWriter->write("");
115 141
        }
116 141
117 141
        $this->logContainer->logPath = $file->getAbsoluteFilePath();
118
        $this->logContainer->statusPath = preg_replace_callback('/(.*)\..+/', function ($matches) {
119 141
            return "$matches[1].status";
120
        }, $this->logContainer->logPath);
121
122
        return $this;
123
    }
124
125
    /**
126 141
     * ログローテートサイクルを読み込む
127
     * @throws LoggerException
128 141
     */
129 14
    private function loadRotateCycle()
130
    {
131
        if (array_key_exists("rotate_cycle", $this->configMap)) {
132 141
            $this->logContainer->rotateCycle = $this->cycle2value($this->configMap["rotate_cycle"]);
133
        }
134
135
        return $this;
136
    }
137
138
    /**
139 141
     * ログローテートサイズを読み込む
140
     * @throws LoggerException
141 141
     */
142
    private function loadRotateSize()
143
    {
144
        if (array_key_exists("rotate_size", $this->configMap)) {
145
            $rotateSize = intval($this->configMap["rotate_size"]);
146
            // ローテートサイズが不正の場合(正の整数以外の値が設定された場合)
147
            if ($rotateSize <= 0) {
148
                throw new LoggerException("Invalid log rotate size: " . $this->configMap["rotate_size"]);
149
            }
150 141
            $this->logContainer->rotateSize = $rotateSize;
151
        }
152
153
        return $this;
154
    }
155
156 141
    /**
157
     * アプリケーション名を読み込む
158 141
     */
159 115
    private function loadApplicationName()
160
    {
161
        if (array_key_exists("application_name", $this->configMap) && !empty($this->configMap["application_name"])) {
162 141
            $this->logContainer->applicationName = $this->configMap["application_name"];
163
        }
164
165
        return $this;
166
    }
167
168 141
    /**
169
     * ロガーフォーマットを読み込む
170 141
     */
171 141
    private function loadFormat()
172
    {
173
        if (array_key_exists("format", $this->configMap)) {
174
            $this->logContainer->format = $this->configMap["format"];
175
        } else {
176 141
            $this->logContainer->format = $this->defaultLoggerFormatter();
177
        }
178
179
        return $this;
180
    }
181
182
    /**
183
     * ログローテートサイクルを時間に変換
184
     * @param string ローテートサイクル
185 14
     * @return int ローテート時間
186
     * @throws LoggerException
187 14
     */
188 14
    private function cycle2value($cycle)
189 14
    {
190 14
        $day_to_h = 24;
191
        $week_to_h = $day_to_h * 7;
192 14
        $month_to_h = $day_to_h * intval(date("t", time()));
193 14
        $year_to_h = $day_to_h * 365;
194
195
        $year = date("Y");
196
        if (($year % 4 === 0 && $year % 100 !== 0) || $year % 400 === 0) {
197 14
            $year_to_h = $day_to_h * 366;
198 14
        }
199 4
200 10
        switch (strtolower($cycle)) {
201 4
            case 'day':
202 6
                return $day_to_h;
203 3
            case 'week':
204 3
                return $week_to_h;
205 3
            case 'month':
206
                return $month_to_h;
207
            case 'year':
208
                return $year_to_h;
209
            default:
210
                throw new LoggerException("Invalid log rotate cycle: " . $cycle);
211
        }
212
    }
213
214
    /**
215
     * ログレベルを数値に変換
216
     * ログレベルはWebStream独自、PSR-3両方対応
217
     * @param string ログレベル文字列
218 141
     * @throws LoggerException
219
     * @return int ログレベル数値
220 141
     */
221 141
    private function toLogLevelValue(string $level)
222 42
    {
223 99
        switch (strtolower($level)) {
224 11
            case 'debug':
225 88
                return 1;
226 11
            case 'info':
227 77
                return 2;
228 55
            case 'notice':    // PSR-3
229 22
                return 3;
230 55
            case 'warn':
231 11
            case 'warning':   // PSR-3
232 44
                return 4;
233 11
            case 'error':
234 33
                return 5;
235 11
            case 'critical':  // PSR-3
236 22
                return 6;
237 11
            case 'alert':     // PSR-3
238 11
                return 7;
239 11
            case 'emergency': // PSR-3
240
                return 8;
241
            case 'fatal':
242
                return 9;
243
            default:
244
                throw new LoggerException("Undefined log level: $level");
245
        }
246
    }
247
}
248