LoggerConfigurationManager::loadLogFilePath()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 13
ccs 7
cts 7
cp 1
rs 10
cc 3
nc 2
nop 0
crap 3
1
<?php
2
3
namespace WebStream\Log;
4
5
use WebStream\Container\Container;
0 ignored issues
show
Bug introduced by
The type WebStream\Container\Container was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use WebStream\Exception\Extend\LoggerException;
0 ignored issues
show
Bug introduced by
The type WebStream\Exception\Extend\LoggerException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use WebStream\IO\File;
0 ignored issues
show
Bug introduced by
The type WebStream\IO\File was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use WebStream\IO\Writer\SimpleFileWriter;
0 ignored issues
show
Bug introduced by
The type WebStream\IO\Writer\SimpleFileWriter was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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)) {
0 ignored issues
show
Bug introduced by
It seems like $configMap can also be of type false; however, parameter $search of array_key_exists() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

55
            if (!array_key_exists("path", /** @scrutinizer ignore-type */ $configMap)) {
Loading history...
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;
0 ignored issues
show
Documentation Bug introduced by
It seems like $configMap can also be of type false. However, the property $configMap is declared as type string[]. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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 ローテートサイクル
0 ignored issues
show
Documentation Bug introduced by
The doc comment ローテートサイクル at position 0 could not be parsed: Unknown type name 'ローテートサイクル' at position 0 in ローテートサイクル.
Loading history...
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 ログレベル文字列
0 ignored issues
show
Documentation Bug introduced by
The doc comment ログレベル文字列 at position 0 could not be parsed: Unknown type name 'ログレベル文字列' at position 0 in ログレベル文字列.
Loading history...
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