PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / 2.0.2
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More v2.0.2
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 47 releases
content-control / vendor-prefixed / trustedlogin / client / src / Logger.php

Logger.php in Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More 2.0.2, at vendor-prefixed/trustedlogin/client/src/Logger.php

477 lines 13.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @license GPL-2.0-or-later
4 *
5 * Modified by code-atlantic on 18-September-2023 using Strauss.
6 * @see https://github.com/BrianHenryIE/strauss
7 */
8 namespace ContentControl\Vendor\TrustedLogin;
9 use DateTime;
10 use RuntimeException;
11
12 /**
13 * Copied from https://github.com/katzgrau/KLogger/blob/3c19e350232e5fee0c3e96e3eff1e7be5f37d617/src/Logger.php
14 * See: https://github.com/trustedlogin/client/issues/105
15 *
16 * A light, permissions-checking logging class.
17 *
18 * Originally written for use with wpSearch
19 *
20 * Usage:
21 * $log = new Katzgrau\KLogger\Logger('/var/log/', Psr\Log\LogLevel::INFO);
22 * $log->info('Returned a million search results'); //Prints to the log file
23 * $log->error('Oh dear.'); //Prints to the log file
24 * $log->debug('x = 5'); //Prints nothing due to current severity threshhold
25 *
26 * @author Kenny Katzgrau <katzgrau@gmail.com>
27 * @since July 26, 2008
28 * @link https://github.com/katzgrau/KLogger
29 * @version 1.0.0
30 */
31
32 class Logger
33 {
34 const EMERGENCY = 'emergency';
35 const ALERT = 'alert';
36 const CRITICAL = 'critical';
37 const ERROR = 'error';
38 const WARNING = 'warning';
39 const NOTICE = 'notice';
40 const INFO = 'info';
41 const DEBUG = 'debug';
42
43 /**
44 * KLogger options
45 * Anything options not considered 'core' to the logging library should be
46 * settable view the third parameter in the constructor
47 *
48 * Core options include the log file path and the log threshold
49 *
50 * @var array
51 */
52 protected $options = array (
53 'extension' => 'txt',
54 'dateFormat' => 'Y-m-d G:i:s.u',
55 'filename' => false,
56 'flushFrequency' => false,
57 'prefix' => 'log_',
58 'logFormat' => false,
59 'appendContext' => true,
60 );
61
62 /**
63 * Path to the log file
64 * @var string
65 */
66 private $logFilePath;
67
68 /**
69 * Current minimum logging threshold
70 * @var integer
71 */
72 protected $logLevelThreshold = self::DEBUG;
73
74 /**
75 * The number of lines logged in this instance's lifetime
76 * @var int
77 */
78 private $logLineCount = 0;
79
80 /**
81 * Log Levels
82 * @var array
83 */
84 protected $logLevels = array(
85 self::EMERGENCY => 0,
86 self::ALERT => 1,
87 self::CRITICAL => 2,
88 self::ERROR => 3,
89 self::WARNING => 4,
90 self::NOTICE => 5,
91 self::INFO => 6,
92 self::DEBUG => 7
93 );
94
95 /**
96 * This holds the file handle for this instance's log file
97 * @var resource
98 */
99 private $fileHandle;
100
101 /**
102 * This holds the last line logged to the logger
103 * Used for unit tests
104 * @var string
105 */
106 private $lastLine = '';
107
108 /**
109 * Octal notation for default permissions of the log file
110 * @var integer
111 */
112 private $defaultPermissions = 0777;
113
114 /**
115 * Class constructor
116 *
117 * @param string $logDirectory File path to the logging directory
118 * @param string $logLevelThreshold The LogLevel Threshold
119 * @param array $options
120 *
121 * @internal param string $logFilePrefix The prefix for the log file name
122 * @internal param string $logFileExt The extension for the log file
123 */
124 public function __construct($logDirectory, $logLevelThreshold = self::DEBUG, array $options = array())
125 {
126 $this->logLevelThreshold = $logLevelThreshold;
127 $this->options = array_merge($this->options, $options);
128
129 $logDirectory = rtrim($logDirectory, DIRECTORY_SEPARATOR);
130 if ( ! file_exists($logDirectory)) {
131 mkdir($logDirectory, $this->defaultPermissions, true);
132 }
133
134 if(strpos($logDirectory, 'php://') === 0) {
135 $this->setLogToStdOut($logDirectory);
136 $this->setFileHandle('w+');
137 } else {
138 $this->setLogFilePath($logDirectory);
139 if(file_exists($this->logFilePath) && !is_writable($this->logFilePath)) {
140 throw new RuntimeException('The file could not be written to. Check that appropriate permissions have been set.');
141 }
142 $this->setFileHandle('a');
143 }
144
145 if ( ! $this->fileHandle) {
146 throw new RuntimeException('The file could not be opened. Check permissions.');
147 }
148 }
149
150 /**
151 * @param string $stdOutPath
152 */
153 public function setLogToStdOut($stdOutPath) {
154 $this->logFilePath = $stdOutPath;
155 }
156
157 /**
158 * @param string $logDirectory
159 */
160 public function setLogFilePath($logDirectory) {
161 if ($this->options['filename']) {
162 if (strpos($this->options['filename'], '.log') !== false || strpos($this->options['filename'], '.txt') !== false) {
163 $this->logFilePath = $logDirectory.DIRECTORY_SEPARATOR.$this->options['filename'];
164 }
165 else {
166 $this->logFilePath = $logDirectory.DIRECTORY_SEPARATOR.$this->options['filename'].'.'.$this->options['extension'];
167 }
168 } else {
169 $this->logFilePath = $logDirectory.DIRECTORY_SEPARATOR.$this->options['prefix'].date('Y-m-d').'.'.$this->options['extension'];
170 }
171 }
172
173 /**
174 * @param $writeMode
175 *
176 * @internal param resource $fileHandle
177 */
178 public function setFileHandle($writeMode) {
179 $this->fileHandle = fopen($this->logFilePath, $writeMode);
180 }
181
182
183 /**
184 * Class destructor
185 */
186 public function __destruct()
187 {
188 if ($this->fileHandle) {
189 fclose($this->fileHandle);
190 }
191 }
192
193 /**
194 * Sets the date format used by all instances of KLogger
195 *
196 * @param string $dateFormat Valid format string for date()
197 */
198 public function setDateFormat($dateFormat)
199 {
200 $this->options['dateFormat'] = $dateFormat;
201 }
202
203 /**
204 * Sets the Log Level Threshold
205 *
206 * @param string $logLevelThreshold The log level threshold
207 */
208 public function setLogLevelThreshold($logLevelThreshold)
209 {
210 $this->logLevelThreshold = $logLevelThreshold;
211 }
212
213 /**
214 * Logs with an arbitrary level.
215 *
216 * @param mixed $level
217 * @param string $message
218 * @param array $context
219 * @return null
220 */
221 public function log($level, $message, array $context = array())
222 {
223 if ($this->logLevels[$this->logLevelThreshold] < $this->logLevels[$level]) {
224 return;
225 }
226 $message = $this->formatMessage($level, $message, $context);
227 $this->write($message);
228 }
229
230 /**
231 * Writes a line to the log without prepending a status or timestamp
232 *
233 * @param string $message Line to write to the log
234 * @return void
235 */
236 public function write($message)
237 {
238 if (null !== $this->fileHandle) {
239 if (fwrite($this->fileHandle, $message) === false) {
240 throw new RuntimeException('The file could not be written to. Check that appropriate permissions have been set.');
241 } else {
242 $this->lastLine = trim($message);
243 $this->logLineCount++;
244
245 if ($this->options['flushFrequency'] && $this->logLineCount % $this->options['flushFrequency'] === 0) {
246 fflush($this->fileHandle);
247 }
248 }
249 }
250 }
251
252 /**
253 * Get the file path that the log is currently writing to
254 *
255 * @return string
256 */
257 public function getLogFilePath()
258 {
259 return $this->logFilePath;
260 }
261
262 /**
263 * Get the last line logged to the log file
264 *
265 * @return string
266 */
267 public function getLastLogLine()
268 {
269 return $this->lastLine;
270 }
271
272 /**
273 * Formats the message for logging.
274 *
275 * @param string $level The Log Level of the message
276 * @param string $message The message to log
277 * @param array $context The context
278 * @return string
279 */
280 protected function formatMessage($level, $message, $context)
281 {
282 if ($this->options['logFormat']) {
283 $parts = array(
284 'date' => $this->getTimestamp(),
285 'level' => strtoupper($level),
286 'level-padding' => str_repeat(' ', 9 - strlen($level)),
287 'priority' => $this->logLevels[$level],
288 'message' => $message,
289 'context' => json_encode($context),
290 );
291 $message = $this->options['logFormat'];
292 foreach ($parts as $part => $value) {
293 $message = str_replace('{'.$part.'}', $value, $message);
294 }
295
296 } else {
297 $message = "[{$this->getTimestamp()}] [{$level}] {$message}";
298 }
299
300 if ($this->options['appendContext'] && ! empty($context)) {
301 $message .= PHP_EOL.$this->indent($this->contextToString($context));
302 }
303
304 return $message.PHP_EOL;
305
306 }
307
308 /**
309 * Gets the correctly formatted Date/Time for the log entry.
310 *
311 * PHP DateTime is dump, and you have to resort to trickery to get microseconds
312 * to work correctly, so here it is.
313 *
314 * @return string
315 */
316 private function getTimestamp()
317 {
318 $originalTime = microtime(true);
319 $micro = sprintf("%06d", ($originalTime - floor($originalTime)) * 1000000);
320 $date = new DateTime(date('Y-m-d H:i:s.'.$micro, (int)$originalTime));
321
322 return $date->format($this->options['dateFormat']);
323 }
324
325 /**
326 * Takes the given context and coverts it to a string.
327 *
328 * @param array $context The Context
329 * @return string
330 */
331 protected function contextToString($context)
332 {
333 $export = '';
334 foreach ($context as $key => $value) {
335 $export .= "{$key}: ";
336 $export .= preg_replace(array(
337 '/=>\s+([a-zA-Z])/im',
338 '/array\(\s+\)/im',
339 '/^ |\G /m'
340 ), array(
341 '=> $1',
342 'array()',
343 ' '
344 ), str_replace('array (', 'array(', var_export($value, true)));
345 $export .= PHP_EOL;
346 }
347 return str_replace(array('\\\\', '\\\''), array('\\', '\''), rtrim($export));
348 }
349
350 /**
351 * Indents the given string with the given indent.
352 *
353 * @param string $string The string to indent
354 * @param string $indent What to use as the indent.
355 * @return string
356 */
357 protected function indent($string, $indent = ' ')
358 {
359 return $indent.str_replace("\n", "\n".$indent, $string);
360 }
361
362 /**
363 * System is unusable.
364 *
365 * @param string $message
366 * @param mixed[] $context
367 *
368 * @return void
369 */
370 public function emergency($message, array $context = array())
371 {
372 $this->log(self::EMERGENCY, $message, $context);
373 }
374
375 /**
376 * Action must be taken immediately.
377 *
378 * Example: Entire website down, database unavailable, etc. This should
379 * trigger the SMS alerts and wake you up.
380 *
381 * @param string $message
382 * @param mixed[] $context
383 *
384 * @return void
385 */
386 public function alert($message, array $context = array())
387 {
388 $this->log(self::ALERT, $message, $context);
389 }
390
391 /**
392 * Critical conditions.
393 *
394 * Example: Application component unavailable, unexpected exception.
395 *
396 * @param string $message
397 * @param mixed[] $context
398 *
399 * @return void
400 */
401 public function critical($message, array $context = array())
402 {
403 $this->log(self::CRITICAL, $message, $context);
404 }
405
406 /**
407 * Runtime errors that do not require immediate action but should typically
408 * be logged and monitored.
409 *
410 * @param string $message
411 * @param mixed[] $context
412 *
413 * @return void
414 */
415 public function error($message, array $context = array())
416 {
417 $this->log(self::ERROR, $message, $context);
418 }
419
420 /**
421 * Exceptional occurrences that are not errors.
422 *
423 * Example: Use of deprecated APIs, poor use of an API, undesirable things
424 * that are not necessarily wrong.
425 *
426 * @param string $message
427 * @param mixed[] $context
428 *
429 * @return void
430 */
431 public function warning($message, array $context = array())
432 {
433 $this->log(self::WARNING, $message, $context);
434 }
435
436 /**
437 * Normal but significant events.
438 *
439 * @param string $message
440 * @param mixed[] $context
441 *
442 * @return void
443 */
444 public function notice($message, array $context = array())
445 {
446 $this->log(self::NOTICE, $message, $context);
447 }
448
449 /**
450 * Interesting events.
451 *
452 * Example: User logs in, SQL logs.
453 *
454 * @param string $message
455 * @param mixed[] $context
456 *
457 * @return void
458 */
459 public function info($message, array $context = array())
460 {
461 $this->log(self::INFO, $message, $context);
462 }
463
464 /**
465 * Detailed debug information.
466 *
467 * @param string $message
468 * @param mixed[] $context
469 *
470 * @return void
471 */
472 public function debug($message, array $context = array())
473 {
474 $this->log(self::DEBUG, $message, $context);
475 }
476 }
477