LoggerConfigurationManager::loadLogFilePath()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 2
nop 0
dl 0
loc 13
rs 10
c 0
b 0
f 0
1
<?php
2
namespace WebStream\Log;
3
4
use WebStream\IO\File;
5
use WebStream\IO\Writer\SimpleFileWriter;
6
use WebStream\Container\Container;
7
use WebStream\Exception\Extend\LoggerException;
8
9
/**
10
 * LoggerConfigurationManager
11
 * @author Ryuichi Tanaka
12
 * @since 2016/01/29
13
 * @version 0.7
14
 */
15
class LoggerConfigurationManager
16
{
17
    /**
18
     * @var Container ログ設定コンテナ
19
     */
20
    private $logContainer;
21
22
    /**
23
     * @var Container IOコンテナ
24
     */
25
    private $ioContainer;
26
27
    /**
28
     * @var array<string> ログ設定情報
29
     */
30
    private $configMap;
31
32
    /**
33
     * Constructor
34
     * @param mixed $config ログ設定
35
     * @throws LoggerException
36
     */
37
    public function __construct($config)
38
    {
39
        if (is_array($config)) {
40
            $configMap = $config;
41
        } else {
42
            $configMap = parse_ini_file($config);
43
            if ($configMap === null) {
44
                throw new LoggerException("Log config file does not exist: " . $config);
45
            }
46
        }
47
48
        $this->logContainer = new Container(false);
49
        $this->ioContainer = new Container();
50
51
        $this->ioContainer->file = function () use ($configMap) {
0 ignored issues
show
Bug Best Practice introduced by
The property file does not exist on WebStream\Container\Container. Since you implemented __set, consider adding a @property annotation.
Loading history...
52
            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

52
            if (!array_key_exists("path", /** @scrutinizer ignore-type */ $configMap)) {
Loading history...
53
                throw new LoggerException("Log path must be defined.");
54
            }
55
            return new File($configMap["path"]);
56
        };
57
        $this->ioContainer->fileWriter = function () use ($configMap) {
0 ignored issues
show
Bug Best Practice introduced by
The property fileWriter does not exist on WebStream\Container\Container. Since you implemented __set, consider adding a @property annotation.
Loading history...
58
            return new SimpleFileWriter($configMap["path"]);
59
        };
60
61
        $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...
62
    }
63
64
    /**
65
     * 設定を読み込む
66
     * @throws LoggerException
67
     */
68
    public function load()
69
    {
70
        $this->loadLogLevel()
71
             ->loadLogFilePath()
72
             ->loadRotateCycle()
73
             ->loadRotateSize()
74
             ->loadApplicationName()
75
             ->loadFormat();
76
    }
77
78
    /**
79
     * ログ設定を返却する
80
     * @return Container ログ設定
81
     */
82
    public function getConfig()
83
    {
84
        return $this->logContainer;
85
    }
86
87
    /**
88
     * ログレベルを読み込む
89
     * @throws LoggerException
90
     */
91
    private function loadLogLevel()
92
    {
93
        if (!array_key_exists("level", $this->configMap)) {
94
            throw new LoggerException("Log level must be defined.");
95
        }
96
97
        $logLevel = $this->toLogLevelValue($this->configMap["level"]);
98
        $this->logContainer->logLevel = $logLevel;
0 ignored issues
show
Bug Best Practice introduced by
The property logLevel does not exist on WebStream\Container\Container. Since you implemented __set, consider adding a @property annotation.
Loading history...
99
100
        return $this;
101
    }
102
103
    /**
104
     * ログ保存先パスを読み込む
105
     * @throws LoggerException
106
     */
107
    private function loadLogFilePath()
108
    {
109
        $file = $this->ioContainer->file;
0 ignored issues
show
Bug Best Practice introduced by
The property file does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
110
        if (!($file->exists() && $file->isFile())) {
0 ignored issues
show
Bug introduced by
The method exists() does not exist on null. ( Ignorable by Annotation )

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

110
        if (!($file->/** @scrutinizer ignore-call */ exists() && $file->isFile())) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
111
            $this->ioContainer->fileWriter->write("");
0 ignored issues
show
Bug introduced by
The method write() does not exist on null. ( Ignorable by Annotation )

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

111
            $this->ioContainer->fileWriter->/** @scrutinizer ignore-call */ 
112
                                            write("");

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug Best Practice introduced by
The property fileWriter does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
112
        }
113
114
        $this->logContainer->logPath = $file->getAbsoluteFilePath();
0 ignored issues
show
Bug Best Practice introduced by
The property logPath does not exist on WebStream\Container\Container. Since you implemented __set, consider adding a @property annotation.
Loading history...
115
        $this->logContainer->statusPath = preg_replace_callback('/(.*)\..+/', function ($matches) {
0 ignored issues
show
Bug Best Practice introduced by
The property statusPath does not exist on WebStream\Container\Container. Since you implemented __set, consider adding a @property annotation.
Loading history...
116
            return "$matches[1].status";
117
        }, $this->logContainer->logPath);
0 ignored issues
show
Bug Best Practice introduced by
The property logPath does not exist on WebStream\Container\Container. Since you implemented __get, consider adding a @property annotation.
Loading history...
118
119
        return $this;
120
    }
121
122
    /**
123
     * ログローテートサイクルを読み込む
124
     * @throws LoggerException
125
     */
126
    private function loadRotateCycle()
127
    {
128
        if (array_key_exists("rotate_cycle", $this->configMap)) {
129
            $this->logContainer->rotateCycle = $this->cycle2value($this->configMap["rotate_cycle"]);
0 ignored issues
show
Bug Best Practice introduced by
The property rotateCycle does not exist on WebStream\Container\Container. Since you implemented __set, consider adding a @property annotation.
Loading history...
130
        }
131
132
        return $this;
133
    }
134
135
    /**
136
     * ログローテートサイズを読み込む
137
     * @throws LoggerException
138
     */
139
    private function loadRotateSize()
140
    {
141
        if (array_key_exists("rotate_size", $this->configMap)) {
142
            $rotateSize = intval($this->configMap["rotate_size"]);
143
            // ローテートサイズが不正の場合(正の整数以外の値が設定された場合)
144
            if ($rotateSize <= 0) {
145
                throw new LoggerException("Invalid log rotate size: " . $this->configMap["rotate_size"]);
146
            }
147
            $this->logContainer->rotateSize = $rotateSize;
0 ignored issues
show
Bug Best Practice introduced by
The property rotateSize does not exist on WebStream\Container\Container. Since you implemented __set, consider adding a @property annotation.
Loading history...
148
        }
149
150
        return $this;
151
    }
152
153
    /**
154
     * アプリケーション名を読み込む
155
     */
156
    private function loadApplicationName()
157
    {
158
        if (array_key_exists("application_name", $this->configMap) && !empty($this->configMap["application_name"])) {
159
            $this->logContainer->applicationName = $this->configMap["application_name"];
0 ignored issues
show
Bug Best Practice introduced by
The property applicationName does not exist on WebStream\Container\Container. Since you implemented __set, consider adding a @property annotation.
Loading history...
160
        }
161
162
        return $this;
163
    }
164
165
    /**
166
     * ロガーフォーマットを読み込む
167
     */
168
    private function loadFormat()
169
    {
170
        if (array_key_exists("format", $this->configMap)) {
171
            $this->logContainer->format = $this->configMap["format"];
0 ignored issues
show
Bug Best Practice introduced by
The property format does not exist on WebStream\Container\Container. Since you implemented __set, consider adding a @property annotation.
Loading history...
172
        } else {
173
            $this->logContainer->format = $this->defaultLoggerFormatter();
0 ignored issues
show
Bug introduced by
The method defaultLoggerFormatter() does not exist on WebStream\Log\LoggerConfigurationManager. ( Ignorable by Annotation )

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

173
            /** @scrutinizer ignore-call */ 
174
            $this->logContainer->format = $this->defaultLoggerFormatter();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
174
        }
175
176
        return $this;
177
    }
178
179
    /**
180
     * ログローテートサイクルを時間に変換
181
     * @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...
182
     * @return int ローテート時間
183
     * @throws LoggerException
184
     */
185
    private function cycle2value($cycle)
186
    {
187
        $day_to_h = 24;
188
        $week_to_h = $day_to_h * 7;
189
        $month_to_h = $day_to_h * intval(date("t", time()));
190
        $year_to_h = $day_to_h * 365;
191
192
        $year = date("Y");
193
        if (($year % 4 === 0 && $year % 100 !== 0) || $year % 400 === 0) {
194
            $year_to_h = $day_to_h * 366;
195
        }
196
197
        switch (strtolower($cycle)) {
198
            case 'day':
199
                return $day_to_h;
200
            case 'week':
201
                return $week_to_h;
202
            case 'month':
203
                return $month_to_h;
204
            case 'year':
205
                return $year_to_h;
206
            default:
207
                throw new LoggerException("Invalid log rotate cycle: " . $cycle);
208
        }
209
    }
210
211
    /**
212
     * ログレベルを数値に変換
213
     * ログレベルはWebStream独自、PSR-3両方対応
214
     * @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...
215
     * @throws LoggerException
216
     * @return int ログレベル数値
217
     */
218
    private function toLogLevelValue(string $level)
219
    {
220
        switch (strtolower($level)) {
221
            case 'debug':
222
                return 1;
223
            case 'info':
224
                return 2;
225
            case 'notice':    // PSR-3
226
                return 3;
227
            case 'warn':
228
            case 'warning':   // PSR-3
229
                return 4;
230
            case 'error':
231
                return 5;
232
            case 'critical':  // PSR-3
233
                return 6;
234
            case 'alert':     // PSR-3
235
                return 7;
236
            case 'emergency': // PSR-3
237
                return 8;
238
            case 'fatal':
239
                return 9;
240
            default:
241
                throw new LoggerException("Undefined log level: $level");
242
        }
243
    }
244
}
245