PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.0.0
Defender Security – Malware Scanner, Login Security & Firewall v6.0.0
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-recipients.php

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

379 lines 10.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Manages notification recipients.
4 *
5 * @package WP_Defender\Controller
6 */
7
8 namespace WP_Defender\Controller;
9
10 use WP_Defender\Event;
11 use Calotes\Helper\HTTP;
12 use Calotes\Component\Request;
13 use Calotes\Component\Response;
14 use WP_Defender\Component\Recipient_Directory;
15 use WP_Defender\Component\Recipient_Verification;
16
17 /**
18 * Handles recipient routes.
19 */
20 class Recipients extends Event {
21
22 /**
23 * Route slug.
24 *
25 * @var string
26 */
27 protected $slug = 'wdf-recipients';
28
29 /**
30 * Notification service.
31 *
32 * @var \WP_Defender\Component\Notification
33 */
34 protected $service;
35
36 /**
37 * Recipient service.
38 *
39 * @var \WP_Defender\Component\Recipients
40 */
41 protected $recipient_service;
42
43 /**
44 * Recipient directory service.
45 *
46 * @var Recipient_Directory
47 */
48 protected $recipient_directory;
49
50 /**
51 * Recipient verification service.
52 *
53 * @var Recipient_Verification
54 */
55 protected $recipient_verification;
56
57 /**
58 * Register routes and hooks.
59 */
60 public function __construct() {
61 $this->register_routes();
62 $this->service = wd_di()->get( \WP_Defender\Component\Notification::class );
63 $this->recipient_service = wd_di()->get( \WP_Defender\Component\Recipients::class );
64 $this->recipient_directory = wd_di()->get( Recipient_Directory::class );
65 $this->recipient_verification = wd_di()->get( Recipient_Verification::class );
66 add_action( 'wp_ajax_' . Notification::SLUG_SUBSCRIBE, array( $this, 'verify_subscriber' ) );
67 add_action( 'wp_ajax_nopriv_' . Notification::SLUG_SUBSCRIBE, array( $this, 'verify_subscriber' ) );
68 }
69
70 /**
71 * Add a recipient to selected notification modules.
72 *
73 * @param Request $request Request data.
74 * @return Response Response data.
75 * @defender_route
76 */
77 public function add_recipient( Request $request ): Response {
78 if ( ! $this->check_permission() ) {
79 return new Response( false, array( 'message' => esc_html__( 'You do not have permission to perform this action.', 'defender-security' ) ) );
80 }
81
82 $data = $request->get_data(
83 array(
84 'name' => array(
85 'type' => 'string',
86 'sanitize' => 'sanitize_text_field',
87 ),
88 'email' => array(
89 'type' => 'string',
90 'sanitize' => 'sanitize_email',
91 ),
92 'statuses' => array( 'type' => 'array' ),
93 '_inHouse' => array( 'type' => 'bool' ),
94 'id' => array( 'type' => 'integer' ),
95 )
96 );
97
98 $name = trim( (string) ( $data['name'] ?? '' ) );
99 $email = trim( (string) ( $data['email'] ?? '' ) );
100 $statuses = array_map( 'sanitize_key', is_array( $data['statuses'] ?? null ) ? $data['statuses'] : array() );
101 $in_house = (bool) ( $data['_inHouse'] ?? false );
102
103 if ( '' === $name || ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
104 return new Response( false, array( 'message' => esc_html__( 'Invalid recipient data.', 'defender-security' ) ) );
105 }
106
107 if ( empty( $statuses ) ) {
108 return new Response( false, array( 'message' => esc_html__( 'Please enable at least one notification module before inviting a recipient.', 'defender-security' ) ) );
109 }
110
111 $user_id = $in_house ? absint( $data['id'] ?? 0 ) : 0;
112 $subscriber = array(
113 'name' => $name,
114 'email' => $email,
115 );
116 if ( $in_house ) {
117 $subscriber['id'] = $user_id;
118 }
119
120 $this->recipient_service->upsert_recipient_to_modules( $statuses, $subscriber );
121
122 return new Response( true, $this->data_frontend() );
123 }
124
125 /**
126 * Update a recipient across notification modules.
127 *
128 * @param Request $request Request.
129 * @return Response Response data.
130 * @defender_route
131 */
132 public function update_recipient( Request $request ): Response {
133 if ( ! $this->check_permission() ) {
134 return new Response( false, array( 'message' => esc_html__( 'You do not have permission to perform this action.', 'defender-security' ) ) );
135 }
136
137 $data = $request->get_data(
138 array(
139 'id' => array(
140 'type' => 'string',
141 'sanitize' => 'sanitize_text_field',
142 ),
143 'statuses' => array( 'type' => 'array' ),
144 'profile' => array( 'type' => 'array' ),
145 'unsubscribed' => array( 'type' => 'array' ),
146 )
147 );
148
149 $recipient_id = trim( (string) ( $data['id'] ?? '' ) );
150 $statuses = array_map( 'sanitize_key', is_array( $data['statuses'] ?? null ) ? $data['statuses'] : array() );
151 $profile = is_array( $data['profile'] ?? null ) ? $data['profile'] : array();
152 $unsubscribed = array_map( 'sanitize_key', is_array( $data['unsubscribed'] ?? null ) ? $data['unsubscribed'] : array() );
153
154 if ( '' === $recipient_id ) {
155 return new Response( false, array( 'message' => esc_html__( 'Invalid recipient ID.', 'defender-security' ) ) );
156 }
157
158 $name = trim( (string) ( $profile['name'] ?? '' ) );
159 $email = sanitize_email( trim( (string) ( $profile['email'] ?? '' ) ) );
160 $in_house = is_numeric( $recipient_id );
161
162 if ( '' === $name || ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
163 return new Response( false, array( 'message' => esc_html__( 'Invalid recipient data.', 'defender-security' ) ) );
164 }
165
166 $subscriber = array(
167 'name' => $name,
168 'email' => $email,
169 );
170 if ( $in_house ) {
171 $subscriber['id'] = (int) $recipient_id;
172 $subscriber['first_name'] = sanitize_text_field( trim( (string) ( $profile['firstName'] ?? '' ) ) );
173 $subscriber['last_name'] = sanitize_text_field( trim( (string) ( $profile['lastName'] ?? '' ) ) );
174 }
175
176 $this->recipient_service->upsert_recipient_to_modules( $statuses, $subscriber, $unsubscribed );
177
178 return new Response( true, $this->data_frontend() );
179 }
180
181 /**
182 * Delete a recipient from all notification modules.
183 *
184 * @param Request $request Request data.
185 * @return Response Response data.
186 * @defender_route
187 */
188 public function delete_recipient( Request $request ): Response {
189 if ( ! $this->check_permission() ) {
190 return new Response( false, array( 'message' => esc_html__( 'You do not have permission to perform this action.', 'defender-security' ) ) );
191 }
192
193 $data = $request->get_data(
194 array(
195 'id' => array(
196 'type' => 'string',
197 'sanitize' => 'sanitize_text_field',
198 ),
199 )
200 );
201
202 $recipient_id = trim( (string) ( $data['id'] ?? '' ) );
203 if ( '' === $recipient_id ) {
204 return new Response( false, array( 'message' => esc_html__( 'Invalid recipient ID.', 'defender-security' ) ) );
205 }
206
207 $this->recipient_directory->delete_recipient( $recipient_id );
208
209 return new Response( true, $this->data_frontend() );
210 }
211
212 /**
213 * Search WordPress users by name or email.
214 *
215 * @param Request $request Request data.
216 * @return Response Response data.
217 * @defender_route
218 */
219 public function search_users( Request $request ): Response {
220 if ( ! $this->check_permission() ) {
221 return new Response( false, array( 'message' => esc_html__( 'You do not have permission to perform this action.', 'defender-security' ) ) );
222 }
223
224 $data = $request->get_data(
225 array(
226 'search' => array(
227 'type' => 'string',
228 'sanitize' => 'sanitize_text_field',
229 ),
230 )
231 );
232 $search = trim( (string) ( $data['search'] ?? '' ) );
233
234 return new Response( true, array( 'users' => $this->recipient_directory->search_users( $search ) ) );
235 }
236
237 /**
238 * Resend verification email for a pending recipient.
239 *
240 * @param Request $request Request data.
241 * @return Response Response data.
242 * @defender_route
243 */
244 public function resend_verification( Request $request ): Response {
245 if ( ! $this->check_permission() ) {
246 return new Response( false, array( 'message' => esc_html__( 'You do not have permission to perform this action.', 'defender-security' ) ) );
247 }
248
249 $data = $request->get_data(
250 array(
251 'id' => array(
252 'type' => 'string',
253 'sanitize' => 'sanitize_text_field',
254 ),
255 'pending' => array( 'type' => 'array' ),
256 )
257 );
258
259 $result = $this->recipient_verification->resend_verification( $data );
260
261 return new Response( $result['success'], $result['data'] );
262 }
263
264 /**
265 * Confirm a subscriber from an email link.
266 *
267 * @return void
268 */
269 public function verify_subscriber(): void {
270 $hash = HTTP::get( 'hash', '' );
271 $slug = HTTP::get( 'uid', '' );
272 $uids = HTTP::get( 'uids', '' );
273 $inhouse = HTTP::get( 'inhouse', '0' );
274
275 if ( '1' === $inhouse && ! is_user_logged_in() ) {
276 auth_redirect();
277 }
278 if ( ! is_string( $hash ) || '' === trim( $hash ) ) {
279 wp_die( esc_html__( 'You shall not pass.', 'defender-security' ) );
280 }
281
282 $slugs = $this->recipient_verification->parse_subscription_slugs( $slug, $uids );
283 if ( array() === $slugs ) {
284 wp_die( esc_html__( 'You shall not pass.', 'defender-security' ) );
285 }
286
287 $is_bulk = is_string( $uids ) && '' !== trim( $uids );
288 $result = $this->recipient_verification->confirm_subscriptions( $slugs, $hash, $inhouse, $is_bulk );
289
290 if ( ! $result['found_module'] ) {
291 wp_die( esc_html__( 'You shall not pass.', 'defender-security' ) );
292 }
293
294 $this->redirect_after_verify( $inhouse, $result );
295 exit; // Required after wp_safe_redirect().
296 }
297
298 /**
299 * Redirect the user after subscription verification.
300 *
301 * @param string $inhouse Whether the recipient is in-house ('1' or '0').
302 * @param array $result Confirmation result from recipient service.
303 * @return void
304 */
305 private function redirect_after_verify( string $inhouse, array $result ): void {
306 if ( '1' === $inhouse && $result['processed'] ) {
307 wp_safe_redirect(
308 add_query_arg(
309 array(
310 'slug' => $result['redirect_slug'],
311 'context' => 'subscribed',
312 ),
313 get_edit_profile_url()
314 )
315 );
316 } else {
317 wp_safe_redirect( home_url() );
318 }
319 }
320
321 /**
322 * Get recipient data for the frontend.
323 *
324 * @return array Frontend recipient data.
325 */
326 public function data_frontend(): array {
327 return array_merge(
328 $this->dump_routes_and_nonces(),
329 array(
330 'recipients' => $this->recipient_directory->get_all_recipients(),
331 'notifications' => $this->service->get_modules(),
332 )
333 );
334 }
335
336 /**
337 * Remove saved settings.
338 *
339 * @return void
340 */
341 public function remove_settings(): void {
342 }
343
344 /**
345 * Remove stored data.
346 *
347 * @return void
348 */
349 public function remove_data(): void {
350 }
351
352 /**
353 * Export controller data.
354 *
355 * @return array Exported controller data.
356 */
357 public function to_array(): array {
358 return array();
359 }
360
361 /**
362 * Import controller data.
363 *
364 * @param array $data Import data.
365 * @return void
366 */
367 public function import_data( array $data ): void {
368 }
369
370 /**
371 * Get translatable strings.
372 *
373 * @return array Translatable strings.
374 */
375 public function export_strings(): array {
376 return array();
377 }
378 }
379