Completed
Push — master ( 40c839...4a6871 )
by Flo
05:59
created

LogManager::log()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
c 0
b 0
f 0
rs 9.2
cc 4
eloc 9
nc 4
nop 3
1
<?php
2
3
namespace Faulancer\Log;
4
5
use Faulancer\Exception\LogFileInvalidException;
6
use Faulancer\Exception\LogTypeNotSupportedException;
7
use Faulancer\Service\Config;
8
use Faulancer\Log\Writer\DefaultWriter;
9
use Faulancer\ServiceLocator\ServiceLocator;
10
11
/**
12
 * Class Logger | Logger.php
13
 *
14
 * @package Faulancer\Log
15
 * @author  Florian Knapp <[email protected]>
16
 */
17
class LogManager
18
{
19
20
    const LEVEL_INFO    = 'info';
21
    const LEVEL_DEBUG   = 'debug';
22
    const LEVEL_WARN    = 'warn';
23
    const LEVEL_ERROR   = 'error';
24
25
    /** @var static */
26
    private static $instance;
27
28
    /** @var ServiceLocator */
29
    private static $serviceLocator;
30
31
    /** @var array */
32
    protected static $levels = [
33
        self::LEVEL_INFO,
34
        self::LEVEL_DEBUG,
35
        self::LEVEL_WARN,
36
        self::LEVEL_ERROR
37
    ];
38
39
    /** @var bool */
40
    protected static $fileSystemChecked = false;
41
42
    /** @var array */
43
    protected static $logFiles = [];
44
45
    /**
46
     * @return static
47
     */
48
    public static function instance()
49
    {
50
        if (!self::$instance) {
51
            self::$instance       = new static();
52
            self::$serviceLocator = ServiceLocator::instance();
53
        }
54
55
        return self::$instance;
56
    }
57
58
    /**
59
     * @param string $message
60
     * @param string $level
61
     * @param string $writer
62
     *
63
     * @return bool
64
     */
65
    public static function log(string $message = '', string $level = self::LEVEL_INFO, string $writer = '')
66
    {
67
        if (!self::$fileSystemChecked) {
68
            self::_checkConsistency();
69
        }
70
71
        /** @var Config $config */
72
        $config = self::$serviceLocator->get(Config::class);
73
74
        if (!empty($writer) && class_exists($writer)) {
75
            $writer = new $writer($config, debug_backtrace());
76
        } else {
77
            $writer = new DefaultWriter($config, debug_backtrace());
78
        }
79
80
        return $writer->write(self::$logFiles[$level], $message, $level);
81
    }
82
83
    /**
84
     * Check for filesystem consistency
85
     *
86
     * @return bool
87
     * @throws LogTypeNotSupportedException
88
     */
89
    private static function _checkConsistency()
90
    {
91
        /** @var Config $config */
92
        $config  = self::$serviceLocator->get(Config::class);
93
        $appRoot = realpath($config->get('projectRoot'));
94
        $logDirs = $config->get('log');
95
96
        if ($logDirs === null) {
97
            return true;
98
        }
99
100
        $hasInfoTypeInConf = false;
101
102
        if (in_array('info', array_keys($logDirs))) {
103
            $hasInfoTypeInConf = true;
104
        }
105
106
        foreach ($logDirs as $level => $path) {
107
108
            if (!in_array($level, self::$levels, true)) {
109
110
                throw new LogTypeNotSupportedException(
111
                    'Log type "' . $level . '" is currently not supported.'
112
                    . 'Please use one of the following log types:' . PHP_EOL
113
                    . implode(", ", self::$levels)
114
                );
115
116
            }
117
118
            $lastDirectorySeparator = strrpos($path, '/');
119
120
            if ($lastDirectorySeparator === false) {
121
                throw new LogFileInvalidException(
122
                    'You have to define the logfile path as an absolute path beginning from your project root'
123
                    . ' (i.e. if "/var/www/vhosts/app" is your project root set the logfile path to "/logs/{$level}.log")'
124
                );
125
            }
126
127
            $logDir = substr($path, 0, $lastDirectorySeparator);
128
129
            if (!is_dir($appRoot . $logDir)) {
130
                mkdir($appRoot . $logDir, 0774, true);
131
            }
132
133
            $file     = substr($path, $lastDirectorySeparator, strlen($path));
134
            $fullPath = $appRoot . $logDir . $file;
135
            $fileType = strrpos($fullPath, '.');
136
137
            if ($fileType !== false) {
138
                $fileType = substr($fullPath, $fileType, strlen($fullPath));
139
            }
140
141
            if (!file_exists($fullPath)) {
142
                file_put_contents($fullPath, '');
143
                chmod($fullPath, 0744);
144
            }
145
146
            if (!$hasInfoTypeInConf && !file_exists($appRoot . $logDir . '/info' . $fileType)) {
147
148
                file_put_contents($appRoot . $logDir . '/info' . $fileType, '');
149
                chmod($appRoot . $logDir . '/info' . $fileType, 0744);
150
151
                self::$logFiles[self::LEVEL_INFO] = $appRoot . $logDir . '/info' . $fileType;
152
153
            } else if (!$hasInfoTypeInConf) {
154
155
                self::$logFiles[self::LEVEL_INFO] = $appRoot . $logDir . '/info' . $fileType;
156
157
            }
158
159
            self::$logFiles[$level] = $fullPath;
160
161
        }
162
163
        self::$fileSystemChecked = true;
164
165
        return true;
166
    }
167
168
}