Logger::start()   B
last analyzed

Complexity

Conditions 11
Paths 11

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
nc 11
nop 0
dl 0
loc 33
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Asymptix\tools\logging;
4
5
use Asymptix\core\OutputStream;
6
7
/**
8
 * Universal Logging functionality. Supports browser output, file and database
9
 * logging.
10
 *
11
 * @category Asymptix PHP Framework
12
 * @author Dmytro Zarezenko <[email protected]>
13
 * @copyright (c) 2016, Dmytro Zarezenko
14
 * @license http://opensource.org/licenses/MIT
15
 */
16
class Logger {
17
18
    /**
19
     * Log messages types constants.
20
     */
21
    const LOG_INFO    = "info";
22
    const LOG_DEBUG   = "debug";
23
    const LOG_SUCCESS = "success";
24
    const LOG_WARNING = "warning";
25
    const LOG_ERROR   = "error";
26
27
    /**
28
     * Log messages output directions constants.
29
     */
30
    const TO_OUTPUT_STREAM = 0;
31
    const TO_FILE = 1;
32
    const TO_DB = 2;
33
34
    /**
35
     * Log messages output direction.
36
     *
37
     * @var int
38
     */
39
    private $direction = null;
40
41
    /**
42
     * Log file name.
43
     *
44
     * @var string
45
     */
46
    private $fileName = null;
47
48
    /**
49
     * Log DB object. Object must have log() method for logging functionality
50
     * support.
51
     *
52
     * @var \Asymptix\db\DBObject
53
     */
54
    private $dbObject = null;
55
56
    /**
57
     * Initiates Logger setting and starts logging.
58
     *
59
     * @param int $direction Output direction.
60
     * @param mixed $output Output file name or DB object.
61
     *
62
     * @throws LoggerException
63
     */
64
    public function __construct($direction = null, $output = null) {
65
        switch ($direction) {
66
            case (null):
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $direction of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
67
            case (self::TO_OUTPUT_STREAM):
68
                $this->direction = self::TO_OUTPUT_STREAM;
69
                break;
70
            case (self::TO_FILE):
71
                $this->direction = self::TO_FILE;
72
                $this->fileName = $output;
73
                break;
74
            case (self::TO_DB):
75
                $this->direction = self::TO_DB;
76
                $this->dbObject = $output;
77
                break;
78
            default:
79
                throw new LoggerException("Invalid logging output direction type");
80
        }
81
        $this->start();
82
    }
83
84
    /**
85
     * Performs preparation to the logging process.
86
     *
87
     * @throws LoggerException
88
     */
89
    public function start() {
90
        switch ($this->direction) {
91
            case (self::TO_OUTPUT_STREAM):
92
                OutputStream::start();
93
94
                return;
95
            case (self::TO_FILE):
96
                if (empty($this->fileName)) {
97
                    throw new LoggerException("Log file name is invalid");
98
                }
99
                if (file_exists($this->fileName)) {
100
                    if (!is_file($this->fileName)) {
101
                        throw new LoggerException("Log file name is invalid");
102
                    }
103
                }
104
                if (file_put_contents($this->fileName, "", FILE_APPEND) === false) {
105
                    throw new LoggerException("Can't write to a file");
106
                }
107
108
                return;
109
            case (self::TO_DB):
110
                if (empty($this->dbObject) || !is_object($this->dbObject)) {
111
                    throw new LoggerException("Invalid LogDBObject object");
112
                }
113
                if (!method_exists($this->dbObject, "log")) {
114
                    throw new LoggerException("No log() method in the LogDBObject object");
115
                }
116
117
                return;
118
            default:
119
                throw new LoggerException("Invalid logging output direction type");
120
        }
121
    }
122
123
    /**
124
     * Main logging method, performs log writing.
125
     *
126
     * @param int $type Log message type.
127
     * @param string $message Message text.
128
     * @param string $format Time label format.
129
     * @param int $time Timestamp.
130
     *
131
     * @throws LoggerException
132
     */
133
    public function log($type, $message, $format = "\[Y-m-d H:i:s\]", $time = null) {
134
        $msgType = null;
0 ignored issues
show
Unused Code introduced by
$msgType is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
135
        switch ($type) {
136
            case (self::LOG_INFO):
137
                $msgType = OutputStream::MSG_INFO;
138
                break;
139
            case (self::LOG_DEBUG):
140
                $msgType = OutputStream::MSG_DEBUG;
141
                break;
142
            case (self::LOG_SUCCESS):
143
                $msgType = OutputStream::MSG_SUCCESS;
144
                break;
145
            case (self::LOG_WARNING):
146
                $msgType = OutputStream::MSG_WARNING;
147
                break;
148
            case (self::LOG_ERROR):
149
                $msgType = OutputStream::MSG_ERROR;
150
                break;
151
            default:
152
                throw new LoggerException("Invalid message type");
153
        }
154
155
        switch ($this->direction) {
156
            case (self::TO_OUTPUT_STREAM):
157
                OutputStream::msg($msgType, $message, $format, $time);
158
159
                return;
160
            case (self::TO_FILE):
161
                $message = "({$type}) " . $message;
162
163
                if (strpos($message, "{{time}}") === false) {
164
                    $message = "{{time}} " . $message;
165
                }
166
                if (is_null($time)) {
167
                    $time = time();
168
                }
169
                $message = str_replace("{{time}}", date($format, $time), $message);
170
171
                file_put_contents($this->fileName, "{$message}\n", FILE_APPEND);
172
173
                return;
174
            case (self::TO_DB):
175
                $this->dbObject->log($type, $message, $time = null);
0 ignored issues
show
Documentation Bug introduced by
The method log does not exist on object<Asymptix\db\DBObject>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
176
177
                return;
178
            default:
179
                throw new LoggerException("Invalid logging output direction type");
180
        }
181
    }
182
183
    /**
184
     * Terminal logging method, performs log to the terminal (CLI).
185
     *
186
     * @param string $message Log message text.
187
     * @param string $timeFormat Time label format.
188
     * @param int $time Timestamp.
189
     */
190
    public static function terminal($message, $timeFormat = "\[Y-m-d H:i:s\]", $time = null) {
191
        if (strpos($message, "{{time}}") === false) {
192
            $message = "{{time}} " . $message;
193
        }
194
195
        if (is_null($time)) {
196
            $time = time();
197
        }
198
199
        print(str_replace("{{time}}", date($timeFormat, $time), $message) . "\n");
200
    }
201
202
    /**
203
     * Closes Logger session.
204
     *
205
     * @throws LoggerException
206
     */
207
    public function close() {
208
        switch ($this->direction) {
209
            case (self::TO_OUTPUT_STREAM):
210
                OutputStream::close();
211
212
                return;
213
            case (self::TO_FILE):
214
                // nothing to do
215
                return;
216
            case (self::TO_DB):
217
                // nothing to do
218
                return;
219
            default:
220
                throw new LoggerException("Invalid logging output direction type");
221
        }
222
    }
223
224
}
225
226
class LoggerException extends \Exception {}
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
227