Test Setup Failed
Push — master ( aa9039...94c501 )
by Derek
03:32
created

File::initialize()   B

Complexity

Conditions 6
Paths 14

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 36
rs 8.439
cc 6
eloc 20
nc 14
nop 0
1
<?php
2
3
namespace Subreality\Dilmun\Nabu\LoggerHandler;
4
5
/**
6
 * Log file object implementing a standard HandlerInterface for log entry handlers.
7
 *
8
 * @author derek
9
 *
10
 * @todo Create methods that set Class properties from actual file properties.
11
 * @todo Implement log rotation mechanism based on the size of an existing log file specified for writing.
12
 */
13
class File implements HandlerInterface
14
{
15
    private $file_name;
16
    private $file_path;
17
18
    private $display_init_failure = true;
19
20
    private $init_failure_email_address = false;
21
22
    /**
23
     * @var \SplFileObject
24
     */
25
    private $file_pointer;
26
27
    /**
28
     * Sets up the file name and path if optional parameters provided.
29
     *
30
     * @param string $file_name [optional] The name of the file used for logging; file_path is not required if file_name
31
     *                          is fully-qualified.
32
     * @param string $file_path [optional] The path of the file used for logging without the trailing directory
33
     *                          separator
34
     */
35
    public function __construct($file_name = null, $file_path = null)
36
    {
37
        $this->file_name = $file_name;
38
39
        //Trim any trailing directory separators from the path.
40
        if (isset($file_path)) {
41
            $this->file_path = rtrim($file_path, '\/');
42
        }
43
    }
44
45
    /**
46
     * Clean-up
47
     */
48
    public function __destruct()
49
    {
50
        $this->close();
51
    }
52
53
    /**
54
     * @return null|string  The file_name set for the File instance
55
     */
56
    public function getFileName()
57
    {
58
        return $this->file_name;
59
    }
60
61
    /**
62
     * @return null|string  The file_path set for the File instance
63
     */
64
    public function getFilePath()
65
    {
66
        return $this->file_path;
67
    }
68
69
    /**
70
     * Sets the name of the file to be used for logging; setting file_path is not required if the specified file name
71
     * is fully-qualified.
72
     *
73
     * @param string $file_name The name of the file to be used for logging
74
     *
75
     * @todo Perform some sort of validation against the file name string
76
     */
77
    public function setFileName($file_name)
78
    {
79
        $this->file_name = $file_name;
80
    }
81
82
    /**
83
     * Sets the path of the file to be used for logging; file path should not be set if the File's file name is
84
     * fully-qualified.
85
     *
86
     * @see File::setFileName()
87
     *
88
     * @param string $file_path The path of the file to be used for logging
89
     *
90
     * @todo Perform some sort of validation against the file path string, maybe considering file_name contents
91
     */
92
    public function setFilePath($file_path)
93
    {
94
        //Trip any trailing directory separators from the path.
95
        $this->file_path = rtrim($file_path, '\/');
96
    }
97
98
    /**
99
     * Prevents the initialization function from outputting an exception/failure message when initialization fails;
100
     * reversed by displayInitFailureMessage. If message is suppressed, a message is instead written to the PHP error
101
     * log via error_log.
102
     *
103
     * @see error_log()
104
     * @see File::displayInitFailureMessage()
105
     * @see File::initialize()
106
     */
107
    public function suppressInitFailureMessage()
108
    {
109
        $this->display_init_failure = false;
110
    }
111
112
    /**
113
     * Enables the initialization function to output an exception/failure message when initialization fails; reversed
114
     * by suppressInitFailureMessage.
115
     *
116
     * @see File::initialize()
117
     * @see File::suppressInitFailureMessage()
118
     */
119
    public function displayInitFailureMessage()
120
    {
121
        $this->display_init_failure = true;
122
    }
123
124
    /**
125
     * Sets the email address to send a failure notification if File initialization fails. Note that setting the email
126
     * address enables sending an email notification via PHP's error_log.
127
     *
128
     * @see File::initialize()
129
     * @see error_log()
130
     *
131
     * @param string $email_address
132
     */
133
    public function sendInitFailureEmailAddress($email_address)
134
    {
135
        $this->init_failure_email_address = $email_address;
0 ignored issues
show
Documentation Bug introduced by
The property $init_failure_email_address was declared of type boolean, but $email_address is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
136
    }
137
138
    /**
139
     * Truncates the File to zero bytes, effectively clearing the file's contents. Does not delete the file.
140
     *
141
     * @return bool Returns true if truncate succeeded; returns false on failure.
142
     */
143
    public function clearFile()
144
    {
145
        if (isset($this->file_pointer)) {
146
            $this->file_pointer->ftruncate(0);
147
148
            return true;
149
        } else {
150
            return false;
151
        }
152
    }
153
154
    /**
155
     * Sets the File's file_pointer to null to clean up resource.
156
     */
157
    public function close()
158
    {
159
        $this->file_pointer = null;
160
    }
161
162
    /**
163
     * Initializes the File for writing via append. Initialization attempts to create an SplFileObject pointer using
164
     * the File's name and path properties. On failure, initialization may output the full file path with an Exception
165
     * message depending on File properties. By default, File::initialize() writes output to the standard output
166
     * buffer and does not send email.
167
     *
168
     * @see \SplFileObject
169
     *
170
     * @return bool Returns true on successful file pointer creation; returns false on failure.
171
     *
172
     * @todo Detect whether file_path has trailing directory separator; add both cases to FileTest.
173
     */
174
    public function initialize()
175
    {
176
        $full_file = "";
177
178
        if (isset($this->file_path)) {
179
            $full_file = $this->file_path . DIRECTORY_SEPARATOR;
180
        }
181
182
        $full_file .= $this->file_name;
183
184
        try {
185
            $this->file_pointer = new \SplFileObject($full_file, "a");
186
187
            return true;
188
        } catch (\Exception $e) {
189
            $file_error_message = "Cannot open specified log file for writing: {$full_file}: {$e->getMessage()}\n";
190
191
            if ($this->init_failure_email_address) {
192
                $email_success = error_log($file_error_message, 1, $this->init_failure_email_address);
193
194
                //Write to PHP log if sending email fails
195
                if (!$email_success) {
196
                    error_log("Sending email to {$this->init_failure_email_address}
197
                               failed! Message: {$file_error_message}");
198
                }
199
            }
200
201
            if ($this->display_init_failure) {
202
                echo $file_error_message;
203
            } else {
204
                error_log($file_error_message);
205
            }
206
207
            return false;
208
        }
209
    }
210
211
    /**
212
     * Writes the specified message to the File pointer. Requires initialization via File::initialize().
213
     *
214
     * @see File::initialize()
215
     *
216
     * @param string $message   Message to be written to the file.
217
     *
218
     * @return bool Returns true on successful write; returns false on failure.
219
     *
220
     * @todo Refactor to return what was written to the file rather than true on success.
221
     */
222
    public function write($message)
223
    {
224
        if (isset($this->file_pointer)) {
225
            $locked = $this->file_pointer->flock(LOCK_EX);
226
        } else {
227
            $locked = false;
228
        }
229
230
        if ($locked) {
231
            $now = date('Y-m-d H:i:s');
232
            $this->file_pointer->fwrite("$now : $message" . "\r\n");
233
            $this->file_pointer->flock(LOCK_UN);
234
235
            return true;
236
        } else {
237
            return false;
238
        }
239
    }
240
}
241