PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.8.1
Defender Security – Malware Scanner, Login Security & Firewall v5.8.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.8.1, at src/controller/class-notification.php

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