Completed
Pull Request — master (#24)
by
unknown
07:25 queued 03:43
created

Logger::end()   B

Complexity

Conditions 8
Paths 4

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 11
nc 4
nop 3
dl 0
loc 20
rs 7.7777
c 0
b 0
f 0
ccs 11
cts 11
cp 1
crap 8
1
<?php
2
/**
3
 * @author Chris dePage <[email protected]>
4
 * @copyright 2009-2018 Vanilla Forums Inc.
5
 * @license MIT
6
 */
7
8
namespace Garden\Cli\Logger;
9
10
use Garden\Cli\Logger\Writer\WriterInterface;
11
12
/**
13
 * Garden logger that accepts multiple writers.
14
 */
15
class Logger implements LoggerInterface {
16
17
    /**
18
     * @var LoggerInterface[] An array of writers.
19
     */
20
    protected $writers = [];
21
22
    /**
23
     * @var int The max indent level to send to the writers.
24
     */
25
    protected $maxLevel = 2;
26
27
    /**
28
     * @var array An array of currently running tasks.
29
     */
30
    protected $taskStack = [];
31
32
    /**
33
     * Add a writer.
34
     *
35
     * @param WriterInterface $writer A writer to use.
36
     *
37
     * @return $this
38
     */
39 17
    public function addWriter(WriterInterface $writer) {
40 17
        array_push($this->writers, $writer);
41
42 17
        return $this;
43
    }
44
45
    /**
46
     * Set the maximum indent level to send to the writers.
47
     *
48
     * @param int $maxLevel The maximum indent level
49
     *
50
     * @return $this
51
     */
52 2
    public function setMaxLevel(int $maxLevel) {
53 2
        if ($maxLevel < 0) {
54 1
            throw new \InvalidArgumentException("The max level must be greater than zero.", 416);
55
        }
56
57 1
        $this->maxLevel = $maxLevel;
58
59 1
        return $this;
60
    }
61
62
    /**
63
     * Get the max indent level to send to the writers.
64
     *
65
     * @return int Returns the maxLevel.
66
     */
67 12
    public function getMaxLevel() {
68 12
        return $this->maxLevel;
69
    }
70
71
    /**
72
     * Log a message that designates the beginning of a task.
73
     *
74
     * @param string $str The message to output.
75
     * @return $this
76
     */
77 10
    public function begin(string $str) {
78 10
        $indentLevel = count($this->taskStack) + 1;
79 10
        $task = [$str, microtime(true), $indentLevel];
80
81 10
        array_push($this->taskStack, $task);
82
83
        // if the current indent level is less than the max, we trigger the logging behaviour
84 10
        if ($indentLevel <= $this->getMaxLevel()) {
85 10
            $this->write(time(), LogLevels::INFO, $str, $indentLevel);
86
        }
87
88 10
        return $this;
89
    }
90
91
    /**
92
     * Log an error message.
93
     *
94
     * @param string $str The message to output.
95
     *
96
     * @return $this
97
     */
98 1
    public function error(string $str) {
99 1
        $indentLevel = count($this->taskStack);
100 1
        $this->write(time(), LogLevels::ERROR, $str, $indentLevel);
101
102 1
        return $this;
103
    }
104
105
    /**
106
     * Log a success message.
107
     *
108
     * @param string $str The message to output.
109
     *
110
     * @return $this
111
     */
112 1
    public function success(string $str) {
113 1
        $indentLevel = count($this->taskStack);
114 1
        $this->write(time(), LogLevels::SUCCESS, $str, $indentLevel);
115
116 1
        return $this;
117
    }
118
119
    /**
120
     * Log a warning message.
121
     *
122
     * @param string $str The message to output.
123
     *
124
     * @return $this
125
     */
126 3
    public function warn(string $str) {
127 3
        $indentLevel = count($this->taskStack);
128 3
        $this->write(time(), LogLevels::WARNING, $str, $indentLevel);
129
130 3
        return $this;
131
    }
132
133
    /**
134
     * Log an info message.
135
     *
136
     * @param string $str The message to output.
137
     * @param bool $force Whether or not to force output of the message even if it's past the max depth.
138
     *
139
     * @return $this
140
     */
141 3
    public function message(string $str, bool $force = false) {
142 3
        $indentLevel = count($this->taskStack);
143
144 3
        if ($indentLevel > $this->getMaxLevel()) {
145
146
            // if not forced we drop the message
147 2
            if (!$force) {
148 2
                return $this;
149
            }
150
151
            // output everything that hasn't been output so far
152 1
            foreach ($this->taskStack as $task) {
153 1
                list($taskStr, $taskTimestamp, $taskIndentLevel) = $task;
154 1
                if ($taskIndentLevel > $this->getMaxLevel()) {
155 1
                  $this->write($taskTimestamp, LogLevels::INFO, $taskStr, $taskIndentLevel);
156
                }
157
            }
158
        }
159
160 3
        $this->write(time(), LogLevels::INFO, $str, $indentLevel);
161
162 3
        return $this;
163
    }
164
165
    /**
166
     * Log a message that represents a task being completed in success.
167
     *
168
     * @param string $str The message to output.
169
     * @param bool $force Whether or not to force a message past the max level to be output.
170
     *
171
     * @return $this
172
     */
173 2
    public function endSuccess(string $str, bool $force = false) {
174 2
        return $this->end($str, $force, LogLevels::SUCCESS);
175
    }
176
177
    /**
178
     * Log a message that represents a task being completed in an error.
179
     *
180
     * When formatting is turned on, error messages are output in red. Error messages are always output even if they are
181
     * past the maximum depth.
182
     *
183
     * @param string $str The message to output.
184
     *
185
     * @return $this
186
     */
187 2
    public function endError(string $str) {
188 2
        return $this->end($str, true, LogLevels::ERROR);
189
    }
190
191
    /**
192
     * Log a message that designates a task being completed.
193
     *
194
     * @param string $str The message to output.
195
     * @param bool $force Whether or not to always output the message even if the task is past the max depth.
196
     * @param string $logLevel The level/type of log to write.
197
     *
198
     * @return $this
199
     */
200 9
    public function end(string $str = '', bool $force =  false, $logLevel = LogLevels::INFO) {
201
        // get the task we are finishing (there has to be one)
202 9
        $task = array_pop($this->taskStack);
203 9
        if (is_null($task)) {
204 1
            trigger_error('Called Logger::end() without calling Logger::begin()', E_USER_NOTICE);
205
        } else {
206 8
            list($taskStr, $taskTimestamp, $indentLevel) = $task;
207 8
            $duration = microtime(true) - $taskTimestamp;
208
209 8
            if (count($this->taskStack) >= $this->getMaxLevel()) {
210 2
                if (!$force || !isset($taskStr) || $indentLevel >= $this->getMaxLevel()) {
211 2
                    return $this;
212
                }
213
            }
214
215
            // update the $str so we prepend the original task $str to it
216 8
            $str = trim($taskStr.' '.$str);
217
        }
218
219 9
        return $this->write(time(), $logLevel, $str, $indentLevel || 0, $duration || null);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $indentLevel does not seem to be defined for all execution paths leading up to this point.
Loading history...
Bug introduced by
$indentLevel || 0 of type boolean is incompatible with the type integer expected by parameter $indentLevel of Garden\Cli\Logger\Logger::write(). ( Ignorable by Annotation )

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

219
        return $this->write(time(), $logLevel, $str, /** @scrutinizer ignore-type */ $indentLevel || 0, $duration || null);
Loading history...
Comprehensibility Best Practice introduced by
The variable $duration does not seem to be defined for all execution paths leading up to this point.
Loading history...
Bug introduced by
$duration || null of type boolean is incompatible with the type null|double expected by parameter $duration of Garden\Cli\Logger\Logger::write(). ( Ignorable by Annotation )

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

219
        return $this->write(time(), $logLevel, $str, $indentLevel || 0, /** @scrutinizer ignore-type */ $duration || null);
Loading history...
220
    }
221
222
    /**
223
     * Log a message that ends a task with an HTTP status code.
224
     *
225
     * @param int $httpStatus The HTTP status code that represents the completion of a task.
226
     * @param bool $force Whether or not to force message output.
227
     *
228
     * @return $this
229
     *
230
     * @see LogFormatter::endSuccess(), LogFormatter::endError().
231
     */
232 3
    public function endHttpStatus(int $httpStatus, bool $force = false) {
233 3
        $statusStr = sprintf('%03d', $httpStatus);
234
235 3
        if ($httpStatus == 0 || $httpStatus >= 400) {
236 1
            $this->endError($statusStr);
237 2
        } elseif ($httpStatus >= 200 && $httpStatus < 300) {
238 1
            $this->endSuccess($statusStr, $force);
239
        } else {
240 1
            $this->end($statusStr, $force);
241
        }
242
243 3
        return $this;
244
    }
245
246
    /**
247
     * Write the stream.
248
     *
249
     * @param int $timestamp The unix timestamp of the log.
250
     * @param string $logLevel The level of the message (e.g. SUCCESS, WARNING, ERROR).
251
     * @param int $indentLevel The nesting level of the message.
252
     * @param string $message The message.
253
     * @param float|null $duration The duration to add to the message.
254
     *
255
     * @return $this
256
     */
257 15
    public function write(int $timestamp, string $logLevel, string $message, $indentLevel = 0, $duration = null) {
258 15
        foreach($this->writers as $writer) {
259 15
            $writer->write($timestamp, $logLevel, $message, $indentLevel, $duration);
0 ignored issues
show
Bug introduced by
The method write() does not exist on Garden\Cli\Logger\LoggerInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Garden\Cli\Logger\LoggerInterface. ( Ignorable by Annotation )

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

259
            $writer->/** @scrutinizer ignore-call */ 
260
                     write($timestamp, $logLevel, $message, $indentLevel, $duration);
Loading history...
260
        }
261
262 15
        return $this;
263
    }
264
}
265