LoggerService.php 3.41 KB
Newer Older
1
2
<?php

3
namespace Kudos\Service;
4

5
use DateTimeZone;
6
use Monolog\Handler\StreamHandler;
7
use Monolog\Logger as Monolog;
8

9
//PHP < 7.2 Define it as 0 so it does nothing
Michael Iseard's avatar
Michael Iseard committed
10
11
if ( ! defined( 'JSON_INVALID_UTF8_SUBSTITUTE' ) ) {
	define( 'JSON_INVALID_UTF8_SUBSTITUTE', 0 );
12
13
}

14
class LoggerService extends Monolog {
15

16
17
	const LOG_DIR = KUDOS_STORAGE_DIR . 'logs/';
	const LOG_FILE = self::LOG_DIR . 'kudos.log';
18
19
20
21
22
23
24

	/**
	 * Kudos_Logger constructor.
	 *
	 * @since    1.0.0
	 */
	public function __construct() {
25

26
27
28
29
30
31
		parent::__construct(
			'kudos',
			[new StreamHandler( self::LOG_FILE )],
			[],
			new DateTimeZone(wp_timezone_string())
		);
32

33
34
35
36
37
38
39
40
	}

	/**
	 * Create the log directory
	 *
	 * @since    1.0.0
	 */
	public static function init() {
41

Michael Iseard's avatar
Michael Iseard committed
42
		if ( wp_mkdir_p( self::LOG_DIR ) ) {
Michael Iseard's avatar
Michael Iseard committed
43
44
45
			return;
		}

Michael Iseard's avatar
Michael Iseard committed
46
47
48
49
		error_log( 'Unable to create Kudos Donations log directory: ' . self::LOG_DIR );

	}

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
	/**
	 * The class factory. In most cases this
	 * should be used instead of instantiating the object
	 * directly.
	 *
	 * @return static
	 * @since   2.0.0
	 */
	public static function factory() {

		static $instance = false;

		if ( ! $instance ) {
			$instance = new static;
		}

		return $instance;

	}

Michael Iseard's avatar
Michael Iseard committed
70
71
72
73
74
75
76
77
	/**
	 * Clears the log file
	 *
	 * @return bool|false|int
	 * @since   2.0.0
	 */
	public static function clear() {

78
		if ( ! self::is_writeable() ) {
Michael Iseard's avatar
Michael Iseard committed
79
80
81
82
			return false;
		}

		return file_put_contents( self::LOG_FILE, '' );
83

84
85
	}

86
87
88
89
	/**
	 * Checks if log file is writeable and returns true if it is
	 *
	 * @return bool
Michael Iseard's avatar
Michael Iseard committed
90
	 * @since   1.0.1
91
	 */
92
	private static function is_writeable() {
93

Michael Iseard's avatar
Michael Iseard committed
94
		if ( is_writable( self::LOG_DIR ) ) {
95
			return true;
96
		}
97

98
		return false;
99

100
101
102
	}

	/**
Michael Iseard's avatar
Michael Iseard committed
103
	 * Downloads the log file
104
105
106
	 *
	 * @since   2.0.0
	 */
Michael Iseard's avatar
Michael Iseard committed
107
	public static function download() {
108

Michael Iseard's avatar
Michael Iseard committed
109
		$file = self::LOG_FILE;
110

Michael Iseard's avatar
Michael Iseard committed
111
112
113
114
115
116
117
118
119
120
		header( 'Content-Description: File Transfer' );
		header( 'Content-Disposition: attachment; filename=kudos_' . sanitize_title( get_bloginfo( 'name' ) ) . '_' . date( 'Y-m-d' ) . '.log' );
		header( "Content-Type: application/octet-stream" );
		header( 'Expires: 0' );
		header( 'Cache-Control: must-revalidate' );
		header( 'Pragma: public' );
		header( 'Content-Length: ' . filesize( $file ) );

		readfile( $file );
		exit;
121

122
123
	}

124
	/**
125
	 * Add checks to parent function
126
127
	 *
	 * @param string $message
128
	 * @param int $level
129
	 * @param array $context
130
131
132
	 *
	 * @return bool
	 * @since    2.0.0
133
	 */
Michael Iseard's avatar
Michael Iseard committed
134
	public function addRecord( int $level, string $message, array $context = [] ): bool {
135
136

		// Don't log debug if not enabled
Michael Iseard's avatar
Michael Iseard committed
137
		if ( $level === self::DEBUG && ! KUDOS_DEBUG ) {
138
139
140
141
			return false;
		}

		// Check ig log is writeable before proceeding
142
		if ( ! $this->is_writeable() ) {
143
			return false;
144
		}
145

Michael Iseard's avatar
Michael Iseard committed
146
		return parent::addRecord( $level, $message, $context );
147
148
149
150
151
	}

	/**
	 * Get the contents of the log file and return as array
	 *
152
	 * @return array|false
153
154
	 * @since   2.0.0
	 */
155
	public function get_as_array() {
156

Michael Iseard's avatar
Michael Iseard committed
157
158
159
160
161
162
		if ( file_exists( self::LOG_FILE ) ) {
			$reg  = '/^\[(?<date>.*)\]\s(?<env>\w+)\.(?<type>\w+):(?<message>.*)/m';
			$text = file_get_contents( self::LOG_FILE );
			preg_match_all( $reg, $text, $matches, PREG_SET_ORDER, 0 );
			usort( $matches, [ $this, 'date_compare' ] );

163
164
165
166
167
			return $matches;
		}

		return false;

168
169
170
171
172
	}

	/**
	 * Compares dates to sort log
	 *
Michael Iseard's avatar
Michael Iseard committed
173
174
	 * @param array $a
	 * @param array $b
Michael Iseard's avatar
Michael Iseard committed
175
	 *
176
	 * @return false|int
177
	 * @since   2.0.0
178
	 */
Michael Iseard's avatar
Michael Iseard committed
179
	private function date_compare( array $a, array $b ) {
180

Michael Iseard's avatar
Michael Iseard committed
181
182
		$t1 = strtotime( $a['date'] );
		$t2 = strtotime( $b['date'] );
183

184
		return $t2 - $t1;
185

186
187
188
	}

}