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

FileWriter::write()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 25
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 9
nop 5
dl 0
loc 25
rs 8.439
c 0
b 0
f 0
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\Writer;
9
10
use Garden\Cli\Logger\Formatter\FormatterInterface;
11
12
/**
13
 * Log writer to append output to a file.
14
 */
15
class FileWriter implements WriterInterface {
16
17
    /**
18
     * @var resource The file handle resource.
19
     */
20
    protected $handle;
21
22
    /**
23
     * @var FormatterInterface[] An array of formatters.
24
     */
25
    protected $formatters = [];
26
27
    /**
28
     * @var bool Whether or not to show durations for tasks.
29
     */
30
    protected $showDurations = true;
31
32
    /**
33
     * FileWriter constructor.
34
     *
35
     * @param string $filePath The path of the file to append to.
36
     * @param string $mode The type of access to the file.
37
     * @param bool $useIncludePath Whether to search the include path for the file.
38
     *
39
     * @throws \Exception
40
     */
41
    public function __construct(string $filePath, string $mode = 'a', bool $useIncludePath = false) {
42
        $this->handle = fopen($filePath, $mode, $useIncludePath);
0 ignored issues
show
Documentation Bug introduced by
It seems like fopen($filePath, $mode, $useIncludePath) can also be of type false. However, the property $handle is declared as type resource. 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...
43
44
        // ensure the file opened
45
        if ($this->handle === false) {
46
            throw new \Exception('The "'.$filePath.'" could not be opened/created');
47
        }
48
    }
49
50
    /**
51
     * FileWriter destructor.
52
     */
53
    public function __destruct() {
54
        // ensure the file we have opened gets closed
55
        fclose($this->handle);
56
    }
57
58
    /**
59
     * Set the showDurations.
60
     *
61
     * @param boolean $showDurations Flag to indicate if durations should be displayed.
62
     *
63
     * @return $this
64
     */
65
    public function setShowDurations(bool $showDurations) {
66
        $this->showDurations = $showDurations;
67
68
        return $this;
69
    }
70
71
    /**
72
     * Get the showDurations.
73
     *
74
     * @return boolean Returns the showDurations.
75
     */
76
    public function getShowDurations() {
77
        return $this->showDurations;
78
    }
79
80
    /**
81
     * Add a formatter to be used by the writer.
82
     *
83
     * @param FormatterInterface $formatter A formatter to use for the writer.
84
     *
85
     * @return $this
86
     */
87
    public function addFormatter(FormatterInterface $formatter) {
88
        array_push($this->formatters, $formatter);
89
90
        return $this;
91
    }
92
93
    /**
94
     * Write the stream.
95
     *
96
     * @param int $timestamp The unix timestamp of the log.
97
     * @param string $logLevel The level of the message (e.g. INFO, SUCCESS, WARNING, ERROR).
98
     * @param string $message The message.
99
     * @param int $indentLevel The nesting level of the message.
100
     * @param float|null $duration The duration to add to the message.
101
     */
102
    public function write(int $timestamp, string $logLevel, string $message, int $indentLevel = 0, $duration = null) {
103
        // ensure our stream hasn't died
104
        if (feof($this->handle)) {
105
            // @codeCoverageIgnoreStart
106
            trigger_error('Called '.__CLASS__.'::write() but file handle was closed.', E_USER_WARNING);
107
            return;
108
            // @codeCoverageIgnoreEnd
109
        }
110
111
        // apply each of the formatters we've attached to this writer
112
        foreach($this->formatters as $formatter) {
113
            list($timestamp, $logLevel, $message, $indentLevel, $duration) = $formatter->format($timestamp, $logLevel, $indentLevel, $message, $duration);
114
        }
115
116
        // convert the indent levels to a visual representation
117
        $indentation = $indentLevel ? str_repeat('  ', $indentLevel).'- ' : '';
118
119
        // build the log entry we'll write to the stream
120
        $logEntry = $timestamp . ' ' . $indentation . ' ' .$message;
121
        if ($this->showDurations) {
122
            $logEntry .= ' '.$duration;
123
        }
124
125
        // write the message
126
        fwrite($this->handle, trim($logEntry).PHP_EOL);
127
    }
128
}
129