PluginProbe
Debug Log Viewer / 2.4
Debug Log Viewer v2.4
2.5 2.5.1 2.5.2 2.4 trunk 1.0.2 1.0.3 1.1 1.1.1 1.2 1.2.1 1.3 1.4 1.4.1 1.4.2 1.4.3 2.0.1 2.0.3 2.0.4 2.0.5 2.1 2.2.3
debug-log-viewer / admin / controllers / AlertController.php

AlertController.php in Debug Log Viewer 2.4, at admin/controllers/AlertController.php

305 lines 8.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace DebugLogViewer\Admin\Controllers;
4
5 use DebugLogViewer\Admin\Services\EmailService;
6 use DebugLogViewer\Admin\Models\LogModel;
7
8 if (!defined('ABSPATH')) {
9 exit;
10 // Exit if accessed directly
11 }
12
13 class AlertController {
14
15
16 public $action;
17 public $options;
18 public $emailRecurrences;
19 public $sendTestEmailHandler;
20
21 public function __construct() {
22 $this->action = LogController::SCHEDULE_MAIL_SEND;
23 $this->sendTestEmailHandler = [ $this, 'sendTestEmail' ];
24
25 $this->emailRecurrences = [
26 'hourly' => __('Hourly', 'debug-log-viewer'),
27 'twicedaily' => __('Twice Daily', 'debug-log-viewer'),
28 'daily' => __('Daily', 'debug-log-viewer'),
29 'weekly' => __('Weekly', 'debug-log-viewer'),
30 ];
31 $this->options = get_option($this->buildUniqueEventName());
32 }
33
34 public function buildUniqueEventName() {
35 return strtoupper($this->action . '_user_' . \wp_get_current_user()->ID);
36 }
37
38 public function getNotificationEmails() {
39 if ($this->options && array_key_exists('dbg_lv_notifications_emails', $this->options)) {
40 return $this->limitNotificationEmails($this->options['dbg_lv_notifications_emails']);
41 }
42
43 return [];
44 }
45
46 private function limitNotificationEmails( array $emails ): array {
47 if (FreemiusController::is_premium()) {
48 return $emails;
49 }
50
51 return array_slice($emails, 0, 1);
52 }
53
54 public function isEnabled() {
55 return (bool) $this->options && array_key_exists('dbg_lv_notifications_emails', $this->options);
56 }
57
58 public function getRecurrence() {
59 foreach ($this->emailRecurrences as $key => $value) {
60 $selected = $key == $this->getRecurrences() ? 'selected="selected"' : '';
61 printf('<option value="%s" %s>%s</option>', esc_attr($key), esc_html($selected), esc_html($value));
62 }
63 }
64
65 private function getRecurrences() {
66 if (!$this->options) {
67 return null;
68 }
69
70 if (array_key_exists('dbg_lv_notifications_email_recurrence', $this->options)) {
71 return $this->options['dbg_lv_notifications_email_recurrence'];
72 }
73 return null;
74 }
75
76 public function getLevelsToReport() {
77 if ($this->options && array_key_exists('dbg_lv_notifications_levels', $this->options)) {
78 return $this->options['dbg_lv_notifications_levels'];
79 }
80
81 // Default levels if none are configured
82 return [
83 LogModel::LOG_LEVEL_DATABASE,
84 LogModel::LOG_LEVEL_FATAL,
85 LogModel::LOG_LEVEL_PARSE,
86 LogModel::LOG_LEVEL_DEPRECATED,
87 ];
88 }
89
90 public function getAllAvailableLevels() {
91 return [
92 LogModel::LOG_LEVEL_DATABASE => __('Database Errors', 'debug-log-viewer'),
93 LogModel::LOG_LEVEL_FATAL => __('Fatal Errors', 'debug-log-viewer'),
94 LogModel::LOG_LEVEL_PARSE => __('Parse Errors', 'debug-log-viewer'),
95 LogModel::LOG_LEVEL_DEPRECATED => __('Deprecated', 'debug-log-viewer'),
96 LogModel::LOG_LEVEL_WARNING => __('Warnings', 'debug-log-viewer'),
97 LogModel::LOG_LEVEL_NOTICE => __('Notices', 'debug-log-viewer'),
98 LogModel::LOG_LEVEL_CUSTOM => __('Custom', 'debug-log-viewer'),
99 ];
100 }
101
102 public function getSelectedLevels() {
103 // Always return the levels that should be selected (either saved or defaults)
104 return $this->getLevelsToReport();
105 }
106
107 private function sendTestEmail( $args ) {
108 $emails = $args['dbg_lv_notifications_emails'] ?? [];
109
110 if (empty($emails)) {
111 return;
112 }
113
114 $entries = [];
115 foreach ($this->getLevelsToReport() as $type) {
116 $timestamp = new \DateTime();
117 $datetime = $timestamp->format('Y-m-d H:i:s e');
118 $text = $type . ' error test description';
119 $hash = md5($text . '::' . $datetime);
120
121 $entries[ $type ][ $hash ] = [
122 'datetime' => $datetime,
123 'line' => wp_rand(1, 100),
124 'file' => 'example.php',
125 'type' => $type,
126 'description' => [
127 'text' => $text,
128 'stack_trace' => null,
129 ],
130 'hits' => 1,
131 ];
132 }
133
134 $emailService = new EmailService();
135 $emailService->setEmails($emails);
136 $emailService->setSubject(__('Debug Log Viewer: Log Monitoring Test Email', 'debug-log-viewer'));
137 $emailService->prepare(
138 'monitoring.tpl',
139 [
140 'website' => get_site_url(),
141 'entries' => $entries,
142 ]
143 );
144 $emailService->send();
145 }
146
147 public function sendTestEmailToRecipients( $options ) {
148 if (isset($this->sendTestEmailHandler) && is_callable($this->sendTestEmailHandler)) {
149 call_user_func($this->sendTestEmailHandler, $options);
150 }
151 }
152
153 public function sendLogsHandler( $event ) {
154 $options = get_option($event);
155
156 if (!$options) {
157 // Clean up orphaned scheduled event and exit silently
158 wp_clear_scheduled_hook($this->action, [ $event ]);
159 return;
160 }
161
162 $emails = $options['dbg_lv_notifications_emails'] ?? [];
163
164 if (empty($emails)) {
165 wp_clear_scheduled_hook($this->action, [ $event ]);
166 error_log(__('Alert email was not found in the options for the event ', 'debug-log-viewer') . $event);
167 return;
168 }
169
170 if (!array_key_exists('dbg_lv_notifications_email_recurrence', $options)) {
171 wp_clear_scheduled_hook($this->action, [ $event ]);
172 error_log(__('Alert email recurrence was not found in the options for the event ', 'debug-log-viewer') . $event);
173 return;
174 }
175
176 $recurrence = $options['dbg_lv_notifications_email_recurrence'];
177
178 $entries = ( new LogController() )->getEntriesByLevel($recurrence);
179
180 if (!$entries) {
181 return;
182 }
183
184 $emailService = new EmailService();
185 $emailService->setEmails($emails);
186 $emailService->setSubject(__('Debug Log Viewer: Monitoring has detected some problems on your website', 'debug-log-viewer'));
187 $emailService->prepare(
188 'monitoring.tpl',
189 [
190 'website' => get_site_url(),
191 'entries' => $entries,
192 ]
193 );
194 $emailService->send();
195 }
196
197 public function getNextScheduledTime() {
198 if (!$this->isEnabled()) {
199 return null;
200 }
201
202 $event_name = $this->buildUniqueEventName();
203 $timestamp = wp_next_scheduled($this->action, [ $event_name ]);
204
205 if ($timestamp) {
206 return $timestamp;
207 }
208
209 return null;
210 }
211
212 public function getFormattedNextScheduledTime() {
213 $timestamp = $this->getNextScheduledTime();
214
215 if (!$timestamp) {
216 return __('Not scheduled', 'debug-log-viewer');
217 }
218
219 $datetime = new \DateTime();
220 $datetime->setTimestamp($timestamp);
221 $datetime->setTimezone(new \DateTimeZone(wp_timezone_string()));
222
223 $date_format = get_option('date_format');
224 $time_format = get_option('time_format');
225
226 return sprintf(
227 /* translators: %1$s: date, %2$s: time */
228 __('Next run: %1$s at %2$s', 'debug-log-viewer'),
229 $datetime->format($date_format),
230 $datetime->format($time_format)
231 );
232 }
233
234 public function getTimeUntilNextEmail() {
235 $timestamp = $this->getNextScheduledTime();
236
237 if (!$timestamp) {
238 return null;
239 }
240
241 // Use time() instead of current_time('timestamp') to get UTC timestamp
242 $current_time = time();
243 $time_diff = $timestamp - $current_time;
244
245 if ($time_diff <= 0) {
246 return __('Sending soon...', 'debug-log-viewer');
247 }
248
249 $days = floor($time_diff / 86400); // 86400 seconds in a day
250 $hours = floor(( $time_diff % 86400 ) / 3600);
251 $minutes = floor(( $time_diff % 3600 ) / 60);
252
253 if ($days > 0) {
254 if ($hours > 0) {
255 return sprintf(
256 /* translators: %d: number of days */
257 _n('%d day', '%d days', $days, 'debug-log-viewer') . ' ' .
258 /* translators: %d: number of hours */
259 _n('%d hour', '%d hours', $hours, 'debug-log-viewer'),
260 $days,
261 $hours
262 );
263 } else {
264 return sprintf(
265 /* translators: %d: number of days */
266 _n('%d day', '%d days', $days, 'debug-log-viewer'),
267 $days
268 );
269 }
270 } elseif ($hours > 0) {
271 return sprintf(
272 /* translators: %d: number of hours */
273 _n('%d hour', '%d hours', $hours, 'debug-log-viewer'),
274 $hours
275 );
276 } else {
277 return sprintf(
278 /* translators: %d: number of minutes */
279 _n('%d minute', '%d minutes', $minutes, 'debug-log-viewer'),
280 $minutes
281 );
282 }
283 }
284
285 public function getNextScheduledTimeForAjax() {
286 $timestamp = $this->getNextScheduledTime();
287
288 if (!$timestamp) {
289 return [
290 'success' => true,
291 'scheduled' => false,
292 'message' => __('Not scheduled', 'debug-log-viewer'),
293 ];
294 }
295
296 return [
297 'success' => true,
298 'scheduled' => true,
299 'timestamp' => $timestamp,
300 'formatted_time' => $this->getFormattedNextScheduledTime(),
301 'time_until' => $this->getTimeUntilNextEmail(),
302 ];
303 }
304 }
305