PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 4.9.0
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v4.9.0
4.9.0 0.9.6 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.2 1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 2.0.0 2.0.1 2.1.1 2.2.1 2.3.1 2.4.0 2.5.0 2.5.1 2.6.0 2.7.0 2.8.0 2.9.0 3.0.1 3.0.2 3.0.3 3.1.0 3.10.0 3.11.0 3.11.1 3.2.0 3.2.1 3.3.0 3.4.0 3.5.0 3.5.1 3.5.2 3.6.1 3.7.0 3.8.0 3.8.2 3.9.0 4.0.1 4.1.0 4.1.1 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.8.0 trunk 0.10.0 0.10.1 0.11.1 0.11.2 0.3.1 0.3.2 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.5.2 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.5 0.8.6 0.8.7 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5
wp-mail-smtp / src / Admin / Notifications.php
wp-mail-smtp / src / Admin Last commit date
DebugEvents 6 days ago EmailSendingErrors 6 days ago Pages 6 days ago Recommendations 6 days ago AdminBarMenu.php 6 days ago Area.php 6 days ago ConnectionSettings.php 6 days ago DashboardWidget.php 6 days ago DomainChecker.php 6 days ago Education.php 6 days ago FlyoutMenu.php 6 days ago Notifications.php 6 days ago PageAbstract.php 6 days ago PageInterface.php 6 days ago ParentPageAbstract.php 6 days ago PluginsInstallSkin.php 6 days ago Review.php 6 days ago SetupWizard.php 6 days ago WooCommerceActiveLayerEducation.php 6 days ago
Notifications.php
545 lines
1 <?php
2
3 namespace WPMailSMTP\Admin;
4
5 use WPMailSMTP\Helpers\Helpers;
6 use WPMailSMTP\Options;
7 use WPMailSMTP\WP;
8
9 /**
10 * Notifications.
11 *
12 * @since 2.3.0
13 */
14 class Notifications {
15
16 /**
17 * Source of notifications content.
18 *
19 * @since 2.3.0
20 *
21 * @var string
22 */
23 const SOURCE_URL = 'https://wpmailsmtpapi.com/feeds/v1/notifications';
24
25 /**
26 * The WP option key for storing the notification options.
27 *
28 * @since 2.3.0
29 *
30 * @var string
31 */
32 const OPTION_KEY = 'wp_mail_smtp_notifications';
33
34 /**
35 * Option value.
36 *
37 * @since 2.3.0
38 *
39 * @var bool|array
40 */
41 public $option = false;
42
43 /**
44 * Initialize class.
45 *
46 * @since 2.3.0
47 */
48 public function init() {
49
50 $this->hooks();
51 }
52
53 /**
54 * Register hooks.
55 *
56 * @since 2.3.0
57 */
58 public function hooks() {
59
60 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
61 add_action( 'wp_mail_smtp_admin_pages_before_content', [ $this, 'output' ] );
62 add_action( 'wp_ajax_wp_mail_smtp_notification_dismiss', [ $this, 'dismiss' ] );
63 }
64
65 /**
66 * Check if notifications are enabled.
67 *
68 * @since 4.3.0
69 *
70 * @return bool
71 */
72 public function is_enabled() {
73
74 return ! Options::init()->get( 'general', 'am_notifications_hidden' );
75 }
76
77 /**
78 * Check if user has access and is enabled.
79 *
80 * @since 2.3.0
81 *
82 * @return bool
83 */
84 public function has_access() {
85
86 $access = false;
87
88 if (
89 current_user_can( wp_mail_smtp()->get_capability_manage_options() ) &&
90 $this->is_enabled()
91 ) {
92 $access = true;
93 }
94
95 return apply_filters( 'wp_mail_smtp_admin_notifications_has_access', $access );
96 }
97
98 /**
99 * Get option value.
100 *
101 * @since 2.3.0
102 *
103 * @param bool $cache Reference property cache if available.
104 *
105 * @return array
106 */
107 public function get_option( $cache = true ) {
108
109 if ( $this->option && $cache ) {
110 return $this->option;
111 }
112
113 $option = get_option( self::OPTION_KEY, [] );
114
115 $this->option = [
116 'update' => ! empty( $option['update'] ) ? $option['update'] : 0,
117 'events' => ! empty( $option['events'] ) ? $option['events'] : [],
118 'feed' => ! empty( $option['feed'] ) ? $option['feed'] : [],
119 'dismissed' => ! empty( $option['dismissed'] ) ? $option['dismissed'] : [],
120 ];
121
122 return $this->option;
123 }
124
125 /**
126 * Fetch notifications from feed.
127 *
128 * @since 2.3.0
129 *
130 * @return array
131 */
132 protected function fetch_feed() {
133
134 $feed_url = self::SOURCE_URL . '/' . wp_mail_smtp()->get_license_type();
135
136 $response = wp_remote_get(
137 $feed_url,
138 [
139 'user-agent' => Helpers::get_default_user_agent(),
140 ]
141 );
142
143 if ( is_wp_error( $response ) ) {
144 return [];
145 }
146
147 $body = wp_remote_retrieve_body( $response );
148
149 if ( empty( $body ) ) {
150 return [];
151 }
152
153 return $this->verify( json_decode( $body, true ) );
154 }
155
156 /**
157 * Verify notification data before it is saved.
158 *
159 * @since 2.3.0
160 *
161 * @param array $notifications Array of notification items to verify.
162 *
163 * @return array
164 */
165 protected function verify( $notifications ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
166
167 $data = [];
168
169 if ( ! is_array( $notifications ) || empty( $notifications ) ) {
170 return $data;
171 }
172
173 $option = $this->get_option();
174
175 foreach ( $notifications as $notification ) {
176
177 // The message and license should never be empty, if they are, ignore.
178 if ( empty( $notification['content'] ) || empty( $notification['type'] ) ) {
179 continue;
180 }
181
182 // Ignore if license type does not match.
183 if ( ! in_array( wp_mail_smtp()->get_license_type(), $notification['type'], true ) ) {
184 continue;
185 }
186
187 // Ignore if expired.
188 if ( ! empty( $notification['end'] ) && time() > strtotime( $notification['end'] ) ) {
189 continue;
190 }
191
192 // Ignore if notification has already been dismissed.
193 if ( ! empty( $option['dismissed'] ) && in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
194 continue;
195 }
196
197 // Ignore if notification existed before installing WPForms.
198 // Prevents bombarding the user with notifications after activation.
199 $activated = get_option( 'wp_mail_smtp_activated_time' );
200
201 if (
202 ! empty( $activated ) &&
203 ! empty( $notification['start'] ) &&
204 $activated > strtotime( $notification['start'] )
205 ) {
206 continue;
207 }
208
209 $data[] = $notification;
210 }
211
212 return $data;
213 }
214
215 /**
216 * Verify saved notification data for active notifications.
217 *
218 * @since 2.3.0
219 *
220 * @param array $notifications Array of notification items to verify.
221 *
222 * @return array
223 */
224 protected function verify_active( $notifications ) {
225
226 if ( ! is_array( $notifications ) || empty( $notifications ) ) {
227 return [];
228 }
229
230 // Remove notifications that are not active.
231 foreach ( $notifications as $key => $notification ) {
232 if (
233 ( ! empty( $notification['start'] ) && time() < strtotime( $notification['start'] ) ) ||
234 ( ! empty( $notification['end'] ) && time() > strtotime( $notification['end'] ) )
235 ) {
236 unset( $notifications[ $key ] );
237 }
238 }
239
240 return $notifications;
241 }
242
243 /**
244 * Get notification data.
245 *
246 * @since 2.3.0
247 * @since 3.9.0 Make the AS a recurring task.
248 *
249 * @return array
250 */
251 public function get() {
252
253 if ( ! $this->has_access() ) {
254 return [];
255 }
256
257 $option = $this->get_option();
258 $events = ! empty( $option['events'] ) ? $this->verify_active( $option['events'] ) : [];
259 $feed = ! empty( $option['feed'] ) ? $this->verify_active( $option['feed'] ) : [];
260
261 return array_merge( $events, $feed );
262 }
263
264 /**
265 * Get the update notifications interval.
266 *
267 * @since 3.9.0
268 *
269 * @return int
270 */
271 public function get_notification_update_task_interval() {
272
273 /**
274 * Filters the interval for the notifications update task.
275 *
276 * @since 3.9.0
277 *
278 * @param int $interval The interval in seconds. Default to a day (in seconds).
279 */
280 return (int) apply_filters( 'wp_mail_smtp_admin_notifications_get_notification_update_task_interval', DAY_IN_SECONDS );
281 }
282
283 /**
284 * Get notification count.
285 *
286 * @since 2.3.0
287 *
288 * @return int
289 */
290 public function get_count() {
291
292 return count( $this->get() );
293 }
294
295 /**
296 * Add a manual notification event.
297 *
298 * @since 2.3.0
299 *
300 * @param array $notification Notification data.
301 */
302 public function add( $notification ) {
303
304 if ( empty( $notification['id'] ) ) {
305 return;
306 }
307
308 $option = $this->get_option();
309
310 if ( in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
311 return;
312 }
313
314 foreach ( $option['events'] as $item ) {
315 if ( $item['id'] === $notification['id'] ) {
316 return;
317 }
318 }
319
320 $notification = $this->verify( [ $notification ] );
321
322 update_option(
323 self::OPTION_KEY,
324 [
325 'update' => $option['update'],
326 'feed' => $option['feed'],
327 'events' => array_merge( $notification, $option['events'] ),
328 'dismissed' => $option['dismissed'],
329 ]
330 );
331 }
332
333 /**
334 * Update notification data from feed.
335 *
336 * @since 2.3.0
337 */
338 public function update() {
339
340 $option = $this->get_option();
341
342 // Bail if feed was updated less than an interval ago.
343 if ( time() - (int) $option['update'] < $this->get_notification_update_task_interval() ) {
344 return;
345 }
346
347 $feed = $this->fetch_feed();
348
349 update_option(
350 self::OPTION_KEY,
351 [
352 'update' => time(),
353 'feed' => $feed,
354 'events' => $option['events'],
355 'dismissed' => $option['dismissed'],
356 ]
357 );
358 }
359
360 /**
361 * Admin area assets.
362 *
363 * @since 2.3.0
364 *
365 * @param string $hook Hook suffix for the current admin page.
366 */
367 public function enqueue_assets( $hook ) {
368
369 if ( strpos( $hook, Area::SLUG ) === false ) {
370 return;
371 }
372
373 if ( ! $this->has_access() ) {
374 return;
375 }
376
377 $notifications = $this->get();
378
379 if ( empty( $notifications ) ) {
380 return;
381 }
382
383 wp_enqueue_style(
384 'wp-mail-smtp-admin-notifications',
385 wp_mail_smtp()->assets_url . '/css/admin-notifications.min.css',
386 [],
387 WPMS_PLUGIN_VER
388 );
389
390 wp_enqueue_script(
391 'wp-mail-smtp-admin-notifications',
392 wp_mail_smtp()->assets_url . '/js/smtp-notifications' . WP::asset_min() . '.js',
393 [ 'jquery' ],
394 WPMS_PLUGIN_VER,
395 true
396 );
397 }
398
399 /**
400 * Output notifications.
401 *
402 * @since 2.3.0
403 */
404 public function output() { // phpcs:ignore Generic.Metrics.NestingLevel.MaxExceeded
405
406 $notifications = $this->get();
407
408 if ( empty( $notifications ) ) {
409 return;
410 }
411
412 $notifications_html = '';
413 $current_class = ' current';
414 $content_allowed_tags = [
415 'em' => [],
416 'i' => [],
417 'strong' => [],
418 'span' => [
419 'style' => [],
420 ],
421 'a' => [
422 'href' => [],
423 'target' => [],
424 'rel' => [],
425 ],
426 'br' => [],
427 'p' => [
428 'id' => [],
429 'class' => [],
430 ],
431 ];
432
433 foreach ( $notifications as $notification ) {
434
435 // Buttons HTML.
436 $buttons_html = '';
437 if ( ! empty( $notification['btns'] ) && is_array( $notification['btns'] ) ) {
438 foreach ( $notification['btns'] as $btn_type => $btn ) {
439 if ( empty( $btn['text'] ) ) {
440 continue;
441 }
442 $buttons_html .= sprintf(
443 '<a href="%1$s" class="button button-%2$s"%3$s>%4$s</a>',
444 ! empty( $btn['url'] ) ? esc_url( $btn['url'] ) : '',
445 $btn_type === 'main' ? 'primary' : 'secondary',
446 ! empty( $btn['target'] ) && $btn['target'] === '_blank' ? ' target="_blank" rel="noopener noreferrer"' : '',
447 sanitize_text_field( $btn['text'] )
448 );
449 }
450 $buttons_html = ! empty( $buttons_html ) ? '<div class="wp-mail-smtp-notifications-buttons">' . $buttons_html . '</div>' : '';
451 }
452
453 // Notification HTML.
454 $notifications_html .= sprintf(
455 '<div class="wp-mail-smtp-notifications-message%5$s" data-message-id="%4$s">
456 <h3 class="wp-mail-smtp-notifications-title">%1$s</h3>
457 <div class="wp-mail-smtp-notifications-content">%2$s</div>
458 %3$s
459 </div>',
460 ! empty( $notification['title'] ) ? sanitize_text_field( $notification['title'] ) : '',
461 ! empty( $notification['content'] ) ? wp_kses( wpautop( $notification['content'] ), $content_allowed_tags ) : '',
462 $buttons_html,
463 ! empty( $notification['id'] ) ? esc_attr( sanitize_text_field( $notification['id'] ) ) : 0,
464 $current_class
465 );
466
467 // Only first notification is current.
468 $current_class = '';
469 }
470 ?>
471
472 <div id="wp-mail-smtp-notifications">
473
474 <div class="wp-mail-smtp-notifications-header">
475 <div class="wp-mail-smtp-notifications-bell">
476 <svg width="16" height="20" viewBox="0 0 16 20" fill="none" xmlns="http://www.w3.org/2000/svg">
477 <path fill-rule="evenodd" clip-rule="evenodd" d="M12.8173 8.92686C12.4476 9.01261 12.0624 9.05794 11.6666 9.05794C8.86542 9.05794 6.59455 6.78729 6.59419 3.98616C4.22974 4.54931 2.51043 6.64293 2.51043 9.23824C2.51043 12.4695 1.48985 13.6147 0.849845 14.3328C0.796894 14.3922 0.746548 14.4487 0.699601 14.5032C0.505584 14.707 0.408575 14.9787 0.440912 15.2165C0.440912 15.7939 0.828946 16.3034 1.47567 16.3034H13.8604C14.5071 16.3034 14.8952 15.7939 14.9275 15.2165C14.9275 14.9787 14.8305 14.707 14.6365 14.5032C14.5895 14.4487 14.5392 14.3922 14.4862 14.3328C13.8462 13.6147 12.8257 12.4695 12.8257 9.23824C12.8257 9.13361 12.8229 9.02979 12.8173 8.92686ZM9.72139 17.3904C9.72139 18.6132 8.81598 19.5643 7.68421 19.5643C6.52011 19.5643 5.6147 18.6132 5.6147 17.3904H9.72139Z" fill="#777777"/>
478 <path d="M11.6666 7.60868C13.6677 7.60868 15.2898 5.98653 15.2898 3.9855C15.2898 1.98447 13.6677 0.36232 11.6666 0.36232C9.66561 0.36232 8.04346 1.98447 8.04346 3.9855C8.04346 5.98653 9.66561 7.60868 11.6666 7.60868Z" fill="#d63638"/>
479 </svg>
480 </div>
481 <div class="wp-mail-smtp-notifications-title"><?php esc_html_e( 'Notifications', 'wp-mail-smtp' ); ?></div>
482 </div>
483
484 <div class="wp-mail-smtp-notifications-body">
485 <a class="dismiss" title="<?php echo esc_attr__( 'Dismiss this message', 'wp-mail-smtp' ); ?>"><i class="dashicons dashicons-dismiss" aria-hidden="true"></i></a>
486
487 <?php if ( count( $notifications ) > 1 ) : ?>
488 <div class="navigation">
489 <a class="prev">
490 <span class="screen-reader-text"><?php esc_attr_e( 'Previous message', 'wp-mail-smtp' ); ?></span>
491 <span aria-hidden="true"></span>
492 </a>
493 <a class="next">
494 <span class="screen-reader-text"><?php esc_attr_e( 'Next message', 'wp-mail-smtp' ); ?>"></span>
495 <span aria-hidden="true">›</span>
496 </a>
497 </div>
498 <?php endif; ?>
499
500 <div class="wp-mail-smtp-notifications-messages">
501 <?php echo $notifications_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
502 </div>
503 </div>
504 </div>
505 <?php
506 }
507
508 /**
509 * Dismiss notification via AJAX.
510 *
511 * @since 2.3.0
512 */
513 public function dismiss() {
514
515 // Run a security check.
516 check_ajax_referer( 'wp-mail-smtp-admin', 'nonce' );
517
518 // Check for access and required param.
519 if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) || empty( $_POST['id'] ) ) {
520 wp_send_json_error();
521 }
522
523 $id = sanitize_text_field( wp_unslash( $_POST['id'] ) );
524 $option = $this->get_option();
525 $type = is_numeric( $id ) ? 'feed' : 'events';
526
527 $option['dismissed'][] = $id;
528 $option['dismissed'] = array_unique( $option['dismissed'] );
529
530 // Remove notification.
531 if ( is_array( $option[ $type ] ) && ! empty( $option[ $type ] ) ) {
532 foreach ( $option[ $type ] as $key => $notification ) {
533 if ( $notification['id'] == $id ) { // phpcs:ignore WordPress.PHP.StrictComparisons
534 unset( $option[ $type ][ $key ] );
535 break;
536 }
537 }
538 }
539
540 update_option( self::OPTION_KEY, $option );
541
542 wp_send_json_success();
543 }
544 }
545