PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.3.1
Defender Security – Malware Scanner, Login Security & Firewall v5.3.1
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / controller / class-notification.php

class-notification.php in Defender Security – Malware Scanner, Login Security & Firewall 5.3.1, at src/controller/class-notification.php

927 lines 25.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handles notification operations.
4 *
5 * @package WP_Defender\Controller
6 */
7
8 namespace WP_Defender\Controller;
9
10 use Exception;
11 use WP_Defender\Event;
12 use Calotes\Helper\HTTP;
13 use WP_Defender\Traits\User;
14 use Calotes\Component\Request;
15 use WP_Defender\Traits\Formats;
16 use Calotes\Component\Response;
17 use WP_Defender\Model\Notification\Malware_Report;
18 use WP_Defender\Component\Config\Config_Hub_Helper;
19 use WP_Defender\Model\Notification as Model_Notification;
20
21 /**
22 * Methods for handling notifications.
23 */
24 class Notification extends Event {
25
26 use User;
27 use Formats;
28
29 /**
30 * Slug identifier for subscribe page.
31 *
32 * @var string
33 */
34 public const SLUG_SUBSCRIBE = 'defender_listen_user_subscribe';
35
36 /**
37 * Slug identifier for unsubscribe page.
38 *
39 * @var string
40 */
41 public const SLUG_UNSUBSCRIBE = 'defender_listen_user_unsubscribe';
42 /**
43 * The slug identifier for this controller.
44 *
45 * @var string
46 */
47 public $slug = 'wdf-notification';
48
49 /**
50 * Service for handling logic.
51 *
52 * @var \WP_Defender\Component\Notification
53 */
54 protected $service;
55
56 /**
57 * Initializes the model and service, registers routes, and sets up scheduled events if the model is active.
58 */
59 public function __construct() {
60 $this->register_page(
61 esc_html__( 'Notifications', 'defender-security' ),
62 $this->slug,
63 array( $this, 'main_view' ),
64 $this->parent_slug
65 );
66 $this->register_routes();
67 $this->service = wd_di()->get( \WP_Defender\Component\Notification::class );
68 add_action( 'defender_enqueue_assets', array( $this, 'enqueue_assets' ) );
69 // We use custom ajax endpoint here as the nonce would fail with other user.
70 add_action( 'wp_ajax_' . self::SLUG_SUBSCRIBE, array( $this, 'verify_subscriber' ) );
71 add_action( 'wp_ajax_nopriv_' . self::SLUG_SUBSCRIBE, array( $this, 'verify_subscriber' ) );
72 add_action( 'wp_ajax_' . self::SLUG_UNSUBSCRIBE, array( $this, 'unsubscribe_and_send_email' ) );
73 add_action( 'wp_ajax_nopriv_' . self::SLUG_UNSUBSCRIBE, array( $this, 'unsubscribe_and_send_email' ) );
74 add_action( 'defender_notify', array( $this, 'send_notify' ), 10, 2 );
75 // We will schedule the time to send reports.
76 if ( ! wp_next_scheduled( 'wdf_maybe_send_report' ) ) {
77 $timestamp = gmmktime( wp_date( 'H' ), 0, 0 );
78 wp_schedule_event( $timestamp, 'thirty_minutes', 'wdf_maybe_send_report' );
79 }
80 add_action( 'wdf_maybe_send_report', array( $this, 'report_sender' ) );
81 add_action( 'admin_notices', array( $this, 'show_actions_with_subscription' ) );
82 }
83
84 /**
85 * For users who have subscribed or unsubscribed confirmation.
86 *
87 * @return null|void
88 */
89 public function show_actions_with_subscription() {
90 if ( ! defined( 'IS_PROFILE_PAGE' ) || false === constant( 'IS_PROFILE_PAGE' ) ) {
91 return null;
92 }
93 $slug = defender_get_data_from_request( 'slug', 'g' );
94 if ( empty( $slug ) ) {
95 return null;
96 }
97 $m = $this->service->find_module_by_slug( $slug );
98 if ( ! is_object( $m ) ) {
99 return null;
100 }
101 $context = defender_get_data_from_request( 'context', 'g' );
102 if ( 'subscribed' === $context ) {
103 $unsubscribe_link = $this->service->create_unsubscribe_url( $m->slug, $this->get_current_user_email() );
104 $strings = sprintf(
105 /* translators: 1. Module title. 2. Unsubscribed link. */
106 esc_html__(
107 'You are now subscribed to receive %1$s. Made a mistake? %2$s',
108 'defender-security'
109 ),
110 '<strong>' . $m->title . '</strong>',
111 '<a href="' . esc_url_raw( $unsubscribe_link ) . '" style="text-decoration: none">' . esc_html__( 'Unsubscribe', 'defender-security' ) . '</a>'
112 );
113 } elseif ( 'unsubscribe' === $context ) {
114 $strings = sprintf(
115 /* translators: %s: Module title. */
116 esc_html__( 'You are now unsubscribed from %s.', 'defender-security' ),
117 '<strong>' . $m->title . '</strong>'
118 );
119 } else {
120 return null;
121 }
122 ?>
123 <div class="notice notice-success" style="position:relative;">
124 <p><?php echo wp_kses_post( $strings ); ?></p>
125 <a href="<?php echo esc_url_raw( get_edit_profile_url() ); ?>" class="notice-dismiss"
126 style="text-decoration: none">
127 <span class="screen-reader-text"><?php esc_attr_e( 'Dismiss this notice.', 'defender-security' ); ?></span>
128 </a>
129 </div>
130 <?php
131 }
132
133 /**
134 * Trigger report check signals.
135 */
136 public function report_sender() {
137 $this->service->maybe_dispatch_report();
138 }
139
140 /**
141 * Renders the main view for this page.
142 */
143 public function main_view() {
144 $this->render( 'main' );
145 }
146
147 /**
148 * Dispatch notification.
149 *
150 * @param string $slug Module slug to identify the notification handler.
151 * @param object $args The arguments to pass to the notification.
152 */
153 public function send_notify( $slug, $args ) {
154 $this->service->dispatch_notification( $slug, $args );
155 }
156
157 /**
158 * Validates an email address provided in the request data.
159 *
160 * @param Request $request The request object .The request object containing the data to validate.
161 *
162 * @return Response The response object indicating the validation result.
163 * @defender_route
164 */
165 public function validate_email( Request $request ): Response {
166 $data = $request->get_data(
167 array(
168 'email' => array(
169 'type' => 'string',
170 'sanitize' => 'sanitize_text_field',
171 ),
172 )
173 );
174 $email = $data['email'] ?? false;
175 if ( filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
176 return new Response(
177 true,
178 array(
179 'error' => false,
180 'avatar' => get_avatar_url( $data['email'] ),
181 )
182 );
183 } else {
184 return new Response( false, array( 'error' => esc_html__( 'Invalid email address.', 'defender-security' ) ) );
185 }
186 }
187
188 /**
189 * Unsubscribe process.
190 */
191 public function unsubscribe_and_send_email() {
192 $slug = HTTP::get( 'slug', '' );
193 $hash = HTTP::get( 'hash', '' );
194 $slug = sanitize_text_field( $slug );
195 if ( empty( $slug ) || empty( $hash ) ) {
196 wp_die( esc_html__( 'You shall not pass.', 'defender-security' ) );
197 }
198 $m = $this->service->find_module_by_slug( $slug );
199 if ( ! is_object( $m ) ) {
200 wp_die( esc_html__( 'You shall not pass.', 'defender-security' ) );
201 }
202 $inhouse = false;
203 foreach ( $m->in_house_recipients as &$recipient ) {
204 $email = $recipient['email'];
205 if ( hash_equals( $hash, hash( 'sha256', $email . AUTH_SALT ) ) ) {
206 // We skip even an un-logged user, because the admin can change the user's access without notice.
207 if ( is_user_logged_in() ) {
208 if ( $email !== $this->get_current_user_email() ) {
209 wp_die( esc_html__( 'Invalid request.', 'defender-security' ) );
210 }
211 $inhouse = true;
212 }
213 $recipient['status'] = Model_Notification::USER_SUBSCRIBE_CANCELED;
214 $m->save();
215 // Send email.
216 $this->service->send_unsubscribe_email( $m, $email, $inhouse, $recipient['name'] );
217 break;
218 }
219 }
220
221 if ( false === $inhouse ) {
222 // No match on in-house, check the outhouse list.
223 foreach ( $m->out_house_recipients as &$recipient ) {
224 $email = $recipient['email'];
225 if ( hash_equals( $hash, hash( 'sha256', $email . AUTH_SALT ) ) ) {
226 $recipient['status'] = Model_Notification::USER_SUBSCRIBE_CANCELED;
227 $m->save();
228 $this->service->send_unsubscribe_email( $m, $email, $inhouse, $recipient['name'] );
229 }
230 }
231 }
232 if ( $inhouse ) {
233 wp_safe_redirect(
234 add_query_arg(
235 array(
236 'slug' => $slug,
237 'context' => 'unsubscribe',
238 ),
239 get_edit_profile_url()
240 )
241 );
242 } else {
243 wp_safe_redirect( get_home_url() );
244 }
245 exit;
246 }
247
248 /**
249 * An endpoint for saving single config from frontend.
250 *
251 * @param Request $request The request object .The request object containing the data to save.
252 *
253 * @defender_route
254 * @return Response
255 * @throws Exception Emits Exception in case of an error.
256 */
257 public function save( Request $request ): Response {
258 $raw_data = $request->get_data();
259 if ( empty( $raw_data['slug'] ) ) {
260 return new Response( false, array( 'message' => esc_html__( 'Invalid data.', 'defender-security' ) ) );
261 }
262 $slug = sanitize_textarea_field( $raw_data['slug'] );
263 $model = $this->service->find_module_by_slug( $slug );
264
265 if ( ! is_object( $model ) ) {
266 return new Response( false, array( 'message' => esc_html__( 'Invalid data.', 'defender-security' ) ) );
267 }
268 $data = $request->get_data_by_model( $model );
269 // Check config-values.
270 $data['configs'] = $model->type_casting( $data['configs'] );
271
272 $model->import( $data );
273 $model->status = Model_Notification::STATUS_ACTIVE;
274 if ( $model->validate() ) {
275 if ( 0 === $model->last_sent ) {
276 // This means that the notification or report never sent, we will use the moment that it get activate.
277 $model->last_sent = time();
278 }
279 $model->save();
280 $this->service->send_subscription_confirm_email( $model );
281 Config_Hub_Helper::set_clear_active_flag();
282 // Track.
283 if ( $this->is_tracking_active() ) {
284 $track_data = array( 'Notification type' => $raw_data['title'] );
285 // For reports. Separated check for 'Security Recommendations - Notification'.
286 if ( 'report' === $raw_data['type'] ) {
287 $track_data['Notification schedule'] = ucfirst( $data['frequency'] );
288 } elseif ( 'tweak-reminder' === $raw_data['slug'] ) {
289 $track_data['Notification schedule'] = ucfirst( $data['configs']['reminder'] );
290 }
291 $this->track_feature( 'def_notification_activated', $track_data );
292 }
293
294 return new Response(
295 true,
296 array_merge(
297 array(
298 'message' => esc_html__(
299 'You have activated the notification successfully. Note, recipients will need to confirm their subscriptions to begin receiving notifications.',
300 'defender-security'
301 ),
302 ),
303 $this->data_frontend()
304 )
305 );
306 }
307
308 return new Response( false, array( 'message' => $model->get_formatted_errors() ) );
309 }
310
311 /**
312 * Bulk update and save changes.
313 *
314 * @param Request $request The request object.
315 *
316 * @defender_route
317 * @return Response
318 */
319 public function save_bulk( Request $request ): Response {
320 $data = $request->get_data(
321 array(
322 'reports' => array(
323 'type' => 'array',
324 'sanitize' => 'sanitize_textarea_field',
325 ),
326 'notifications' => array(
327 'type' => 'array',
328 'sanitize' => 'sanitize_textarea_field',
329 ),
330 )
331 );
332 $this->save_reports( $data['reports'] );
333 $this->save_notifications( $data['notifications'] );
334 Config_Hub_Helper::set_clear_active_flag();
335
336 return new Response(
337 true,
338 array_merge(
339 $this->data_frontend(),
340 array(
341 'message' => esc_html__(
342 'Your settings have been updated successfully. Any new recipients will receive an email to confirm their subscription.',
343 'defender-security'
344 ),
345 )
346 )
347 );
348 }
349
350 /**
351 * Process bulk reports saving.
352 *
353 * @param array $data Data to save.
354 *
355 * @throws Exception Emits Exception in case of an error.
356 */
357 private function save_reports( $data ) {
358 foreach ( $data['configs'] as $datum ) {
359 $slug = $datum['slug'];
360 $model = $this->service->find_module_by_slug( $slug );
361 if ( ! is_object( $model ) ) {
362 continue;
363 }
364
365 $import = array(
366 // Saving after Bulk-Update must always change the status to Active.
367 'status' => Model_Notification::STATUS_ACTIVE,
368 'configs' => $model->type_casting( $datum ),
369 'in_house_recipients' => $data['in_house_recipients'],
370 'out_house_recipients' => $data['out_house_recipients'],
371 );
372 // since 2.7.0.
373 if ( Malware_Report::SLUG !== $slug ) {
374 $import['frequency'] = $data['frequency'];
375 $import['day_n'] = $data['day_n'];
376 $import['day'] = $data['day'];
377 $import['time'] = $data['time'];
378 }
379 foreach ( $import['out_house_recipients'] as $key => $val ) {
380 if ( ! filter_var( $val['email'], FILTER_VALIDATE_EMAIL ) ) {
381 unset( $import['out_house_recipients'][ $key ] );
382 }
383 }
384 $model->import( $import );
385 if ( $model->validate() ) {
386 if ( 0 === $model->last_sent ) {
387 $model->last_sent = time();
388 }
389 $model->save();
390 $this->service->send_subscription_confirm_email( $model );
391 // Track.
392 if ( $this->is_tracking_active() ) {
393 $track_data = array(
394 'Notification type' => $model->title,
395 'Notification schedule' => 'tweak-reminder' === $slug
396 ? ucfirst( $data['configs']['reminder'] )
397 : ucfirst( $data['frequency'] ),
398 );
399 $this->track_feature( 'def_notification_activated', $track_data );
400 }
401 }
402 }
403 }
404
405 /**
406 * Saves the notifications based on the provided data.
407 *
408 * @param array $data The data containing the configurations for the notifications.
409 *
410 * @return void
411 * @throws Exception Emits Exception in case of an error.
412 */
413 private function save_notifications( $data ) {
414 foreach ( $data['configs'] as $datum ) {
415 $slug = $datum['slug'];
416 $model = $this->service->find_module_by_slug( $slug );
417 if ( ! is_object( $model ) ) {
418 continue;
419 }
420 $import = array(
421 // Saving after Bulk-Update must always change the status to Active.
422 'status' => Model_Notification::STATUS_ACTIVE,
423 'configs' => $model->type_casting( $datum ),
424 'in_house_recipients' => $data['in_house_recipients'],
425 'out_house_recipients' => $data['out_house_recipients'],
426 );
427 foreach ( $import['out_house_recipients'] as $key => $val ) {
428 if ( ! filter_var( $val['email'], FILTER_VALIDATE_EMAIL ) ) {
429 unset( $import['out_house_recipients'][ $key ] );
430 }
431 }
432 $model->import( $import );
433 if ( $model->validate() ) {
434 if ( 0 === $model->last_sent ) {
435 $model->last_sent = time();
436 }
437 $model->save();
438 $this->service->send_subscription_confirm_email( $model );
439 // Track.
440 if ( $this->is_tracking_active() ) {
441 $this->track_feature( 'def_notification_activated', array( 'Notification type' => $model->title ) );
442 }
443 }
444 }
445 }
446
447 /**
448 * Bulk activate.
449 *
450 * @param Request $request The request object.
451 *
452 * @defender_route
453 * @return Response
454 * @throws Exception Emits Exception in case of an error.
455 */
456 public function bulk_activate( Request $request ): Response {
457 $data = $request->get_data(
458 array(
459 'slugs' => array(
460 'type' => 'array',
461 'sanitize' => 'sanitize_text_field',
462 ),
463 )
464 );
465 $slugs = $data['slugs'];
466 if ( empty( $slugs ) ) {
467 return new Response( false, array() );
468 }
469
470 foreach ( $slugs as $slug ) {
471 $model = $this->service->find_module_by_slug( $slug );
472 if ( is_object( $model ) ) {
473 $model->status = Model_Notification::STATUS_ACTIVE;
474 if ( 0 === $model->last_sent ) {
475 // This means that the notification or report never sent, we will use the moment that it get activate.
476 $model->last_sent = time();
477 }
478 $model->save();
479 }
480 }
481
482 return new Response(
483 true,
484 array_merge(
485 array(
486 'message' => 'You have activated the notification successfully. Note, recipients will need to confirm their subscriptions to begin receiving notifications.',
487 ),
488 $this->data_frontend()
489 )
490 );
491 }
492
493 /**
494 * Bulk deactivate.
495 *
496 * @param Request $request The request object.
497 *
498 * @defender_route
499 * @return Response
500 */
501 public function bulk_deactivate( Request $request ): Response {
502 $data = $request->get_data(
503 array(
504 'slugs' => array(
505 'type' => 'array',
506 'sanitize' => 'sanitize_text_field',
507 ),
508 )
509 );
510 $slugs = $data['slugs'];
511 if ( empty( $slugs ) ) {
512 return new Response( false, array() );
513 }
514
515 foreach ( $slugs as $slug ) {
516 $model = $this->service->find_module_by_slug( $slug );
517 if ( is_object( $model ) ) {
518 $model->status = Model_Notification::STATUS_DISABLED;
519 $model->save();
520 }
521 }
522
523 return new Response(
524 true,
525 array_merge(
526 array( 'message' => esc_html__( 'You have deactivated the notifications successfully.', 'defender-security' ) ),
527 $this->data_frontend()
528 )
529 );
530 }
531
532 /**
533 * Disable a notification module.
534 *
535 * @param Request $request The request object .The request object containing the data to disable the module.
536 *
537 * @defender_route
538 * @return Response The response object indicating the success or failure of the operation.
539 */
540 public function disable( Request $request ): Response {
541 $data = $request->get_data(
542 array(
543 'slug' => array(
544 'type' => 'string',
545 'sanitize' => 'sanitize_text_field',
546 ),
547 )
548 );
549
550 $slug = $data['slug'];
551 $model = $this->service->find_module_by_slug( $slug );
552 if ( ! is_object( $model ) ) {
553 return new Response( false, array( 'message' => esc_html__( 'Invalid data.', 'defender-security' ) ) );
554 }
555
556 $model->status = Model_Notification::STATUS_DISABLED;
557 $model->save();
558
559 return new Response(
560 true,
561 array_merge(
562 $this->data_frontend(),
563 array(
564 'message' => esc_html__( 'You have deactivated the notification successfully.', 'defender-security' ),
565 )
566 )
567 );
568 }
569
570 /**
571 * This is a receiver to process subscribe confirmation from email.
572 */
573 public function verify_subscriber() {
574 $hash = HTTP::get( 'hash', '' );
575 $slug = HTTP::get( 'uid', '' );
576 $inhouse = HTTP::get( 'inhouse', 0 );
577 if ( $inhouse && ! is_user_logged_in() ) {
578 // This is in-house, so we need to redirect.
579 auth_redirect();
580 }
581 if ( empty( $hash ) || empty( $slug ) ) {
582 wp_die( esc_html__( 'You shall not pass.', 'defender-security' ) );
583 }
584 $m = $this->service->find_module_by_slug( $slug );
585 if ( ! is_object( $m ) ) {
586 wp_die( esc_html__( 'You shall not pass.', 'defender-security' ) );
587 }
588 if ( $inhouse ) {
589 $processed = false;
590 foreach ( $m->in_house_recipients as &$recipient ) {
591 if ( Model_Notification::USER_SUBSCRIBED === $recipient['status'] ) {
592 continue;
593 }
594
595 $email = $recipient['email'];
596 $name = $recipient['name'];
597 if ( hash_equals( $hash, hash( 'sha256', $email . AUTH_SALT ) )
598 && $email === $this->get_current_user_email() ) {
599 $recipient['status'] = Model_Notification::USER_SUBSCRIBED;
600 $this->service->send_subscribed_email( $email, $m, $name );
601 $processed = true;
602 }
603 }
604 } else {
605 foreach ( $m->out_house_recipients as &$recipient ) {
606 if ( Model_Notification::USER_SUBSCRIBED === $recipient['status'] ) {
607 continue;
608 }
609
610 $email = $recipient['email'];
611 $name = $recipient['name'];
612 if ( hash_equals( $hash, hash( 'sha256', $email . AUTH_SALT ) ) ) {
613 $recipient['status'] = Model_Notification::USER_SUBSCRIBED;
614 $this->service->send_subscribed_email( $email, $m, $name );
615 }
616 }
617 }
618 $m->save();
619 if ( $inhouse ) {
620 if ( $processed ) {
621 wp_safe_redirect(
622 add_query_arg(
623 array(
624 'slug' => $m->slug,
625 'context' => 'subscribed',
626 ),
627 get_edit_profile_url()
628 )
629 );
630 } else {
631 wp_safe_redirect( home_url() );
632 }
633 } else {
634 wp_safe_redirect( home_url() );
635 }
636 exit;
637 }
638
639 /**
640 * Enqueues scripts and styles for this page.
641 * Only enqueues assets if the page is active.
642 */
643 public function enqueue_assets() {
644 if ( ! $this->is_page_active() ) {
645 return;
646 }
647 wp_localize_script(
648 'def-notification',
649 'notification',
650 array_merge( $this->data_frontend(), $this->dump_routes_and_nonces() )
651 );
652 wp_enqueue_script( 'def-momentjs', defender_asset_url( '/assets/js/vendor/moment/moment.min.js' ), array(), DEFENDER_VERSION, true );
653 wp_enqueue_script( 'def-notification' );
654 $this->enqueue_main_assets();
655 wp_enqueue_style(
656 'def-select2',
657 defender_asset_url( '/assets/css/select2.min.css' ),
658 array(),
659 DEFENDER_VERSION,
660 true
661 );
662 }
663
664 /**
665 * An endpoint for fetching users pool.
666 *
667 * @param Request $request The request object .Request data.
668 *
669 * @defender_route
670 */
671 public function get_users( Request $request ) {
672 $data = $request->get_data(
673 array(
674 'paged' => array(
675 'type' => 'int',
676 'sanitize' => 'sanitize_text_field',
677 ),
678 'search' => array(
679 'type' => 'string',
680 'sanitize' => 'sanitize_text_field',
681 ),
682 'exclude' => array(
683 'type' => 'array',
684 ),
685 'module' => array(
686 'type' => 'string',
687 'sanitize' => 'sanitize_text_field',
688 ),
689 'user_role_filter' => array(
690 'type' => 'string',
691 'sanitize' => 'sanitize_text_field',
692 ),
693 'user_sort' => array(
694 'type' => 'string',
695 'sanitize' => 'sanitize_text_field',
696 ),
697 )
698 );
699 $paged = 1;
700 $exclude = $data['exclude'] ?? array();
701 $username = $data['search'] ?? '';
702 $slug = $data['module'] ?? null;
703 $role = '';
704
705 if (
706 isset( $data['user_role_filter'] ) &&
707 'all' !== $data['user_role_filter']
708 ) {
709 $role = $data['user_role_filter'];
710 }
711
712 $order_by = 'ID';
713 $order = 'DESC';
714 if ( isset( $data['user_sort'] ) ) {
715 switch ( $data['user_sort'] ) {
716 case 'recent':
717 $order_by = 'registered';
718 $order = 'DESC';
719 break;
720 case 'alpha_asc':
721 $order_by = 'display_name';
722 $order = 'ASC';
723 break;
724 case 'alpha_desc':
725 default:
726 $order_by = 'display_name';
727 $order = 'DESC';
728 break;
729 }
730 }
731
732 if ( strlen( $username ) ) {
733 $username = "*$username*";
734 }
735
736 $users = $this->service->get_users_pool(
737 $exclude,
738 $role,
739 $username,
740 $order_by,
741 $order,
742 10,
743 $paged
744 );
745
746 if ( ! is_null( $slug ) ) {
747 $notification = $this->service->find_module_by_slug( $slug );
748 if ( is_object( $notification ) ) {
749 foreach ( $notification->in_house_recipients as $recipient ) {
750 foreach ( $users as &$user ) {
751 if ( $user['email'] === $recipient['email'] ) {
752 $user['status'] = $recipient['status'];
753 }
754 }
755 }
756 }
757 }
758
759 wp_send_json_success( $users );
760 }
761
762 /**
763 * Removes settings for all submodules.
764 */
765 public function remove_settings() {
766 foreach ( $this->service->get_modules_as_objects() as $module ) {
767 $module->delete();
768 }
769 }
770
771 /**
772 * Delete all the data & the cache.
773 */
774 public function remove_data() {
775 }
776
777 /**
778 * Converts the current object state to an array.
779 *
780 * @return array The array representation of the object.
781 */
782 public function to_array(): array {
783 return array();
784 }
785
786 /**
787 * Provides data for the frontend.
788 *
789 * @return array An array of data for the frontend.
790 */
791 public function data_frontend(): array {
792 return array(
793 'notifications' => $this->service->get_modules(),
794 'inactive_notifications' => $this->service->get_inactive_modules(),
795 'active_count' => $this->service->count_active(),
796 'next_run' => $this->service->get_next_run(),
797 'misc' => array(
798 'days_of_week' => $this->get_days_of_week(),
799 'times_of_day' => $this->get_times(),
800 'timezone_text' => sprintf(
801 /* translators: 1. Timezone. 2. Time. */
802 esc_html__(
803 'Your timezone is set to %1$s, so your current time is %2$s.',
804 'defender-security'
805 ),
806 '<strong>' . wp_timezone_string() . '</strong>',
807 '<strong>' . wp_date( 'H:i', time() ) . '</strong>'
808 ),
809 'default_recipient' => $this->get_default_recipient(),
810 ),
811 );
812 }
813
814 /**
815 * Imports data into the model.
816 *
817 * @param array $data Data to be imported into the model.
818 */
819 public function import_data( array $data ) {
820 }
821
822 /**
823 * Exports strings.
824 *
825 * @return array An array of strings.
826 */
827 public function export_strings(): array {
828 $modules = wd_di()->get( self::class )->service->get_modules_as_objects();
829 $strings = array();
830 foreach ( $modules as $module ) {
831 /* translators: %s - module title, %s - module status */
832 $string = esc_html__( '%1$s: %2$s', 'defender-security' );
833 if ( 'notification' === $module->type ) {
834 $string = sprintf(
835 $string,
836 $module->title,
837 Model_Notification::STATUS_ACTIVE === $module->status ? esc_html__(
838 'Enabled',
839 'defender-security'
840 ) : esc_html__( 'Disabled', 'defender-security' )
841 );
842 } else {
843 $string = sprintf(
844 $string,
845 $module->title,
846 Model_Notification::STATUS_ACTIVE === $module->status ? $module->to_string() : esc_html__(
847 'Disabled',
848 'defender-security'
849 )
850 );
851 }
852 $strings[] = $string;
853 }
854
855 return $strings;
856 }
857
858 /**
859 * Resend invite email.
860 *
861 * @param Request $request The request object.
862 *
863 * @defender_route
864 * @return Response
865 */
866 public function resend_invite_email( Request $request ): Response {
867 $data = $request->get_data(
868 array(
869 'slug' => array(
870 'type' => 'string',
871 'sanitize' => 'sanitize_textarea_field',
872 ),
873 'email' => array(
874 'type' => 'string',
875 'sanitize' => 'sanitize_text_field',
876 ),
877 'id' => array(
878 'type' => 'integer',
879 ),
880 'name' => array(
881 'type' => 'string',
882 'sanitize' => 'sanitize_text_field',
883 ),
884 )
885 );
886
887 $model = $this->service->find_module_by_slug( $data['slug'] );
888
889 if ( ! is_object( $model ) ) {
890 return new Response( false, array( 'message' => esc_html__( 'Module not found.', 'defender-security' ) ) );
891 }
892
893 $subscriber = array(
894 'email' => $data['email'],
895 'name' => $data['name'],
896 );
897
898 if ( ! empty( $data['id'] ) ) {
899 $subscriber['id'] = $data['id'];
900 }
901 // Resend invite email now.
902 $sent = $this->service->send_email( $subscriber, $model );
903
904 if ( $sent ) {
905 return new Response( true, array( 'message' => esc_html__( 'Invitation sent successfully.', 'defender-security' ) ) );
906 }
907
908 return new Response(
909 false,
910 array(
911 'message' => esc_html__( 'Sorry! We could not send the invitation, Please try again later.', 'defender-security' ),
912 )
913 );
914 }
915
916 /**
917 * Get user roles with count.
918 *
919 * @defender_route
920 */
921 public function get_user_roles() {
922 $user_roles = $this->service->get_user_roles();
923
924 wp_send_json_success( $user_roles );
925 }
926 }
927