PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 1.0.3
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v1.0.3
2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 0.0.2 0.0.3 All 96 releases
sureforms / inc / form-submit.php

form-submit.php in SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz 1.0.3, at inc/form-submit.php

784 lines 25.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Sureforms Submit Class file.
4 *
5 * @package sureforms.
6 * @since 0.0.1
7 */
8
9 namespace SRFM\Inc;
10
11 use SRFM\Inc\Database\Tables\Entries;
12 use SRFM\Inc\Email\Email_Template;
13 use SRFM\Inc\Lib\Browser\Browser;
14 use SRFM\Inc\Traits\Get_Instance;
15 use WP_Error;
16 use WP_REST_Server;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit; // Exit if accessed directly.
20 }
21
22 if ( ! function_exists( 'wp_handle_upload' ) ) {
23 require_once ABSPATH . 'wp-admin/includes/file.php';
24 }
25
26 /**
27 * Sureforms Submit Class.
28 *
29 * @since 0.0.1
30 */
31 class Form_Submit {
32 use Get_Instance;
33
34 /**
35 * Namespace.
36 *
37 * @var string
38 */
39 protected $namespace = 'sureforms/v1';
40
41 /**
42 * Constructor
43 *
44 * @since 0.0.1
45 */
46 public function __construct() {
47 add_action( 'rest_api_init', [ $this, 'register_custom_endpoint' ] );
48 add_action( 'wp_ajax_validation_ajax_action', [ $this, 'field_unique_validation' ] );
49 add_action( 'wp_ajax_nopriv_validation_ajax_action', [ $this, 'field_unique_validation' ] );
50 // for quick action bar.
51 add_action( 'wp_ajax_srfm_global_update_allowed_block', [ $this, 'srfm_global_update_allowed_block' ] );
52 add_action( 'wp_ajax_srfm_global_sidebar_enabled', [ $this, 'srfm_global_sidebar_enabled' ] );
53 }
54
55 /**
56 * Add custom API Route submit-form
57 *
58 * @return void
59 * @since 0.0.1
60 */
61 public function register_custom_endpoint() {
62 register_rest_route(
63 $this->namespace,
64 '/submit-form',
65 [
66 'methods' => WP_REST_Server::EDITABLE,
67 'callback' => [ $this, 'handle_form_submission' ],
68 'permission_callback' => '__return_true',
69 ]
70 );
71 }
72
73 /**
74 * Check whether a given request has permission access route.
75 *
76 * @since 0.0.1
77 * @return WP_Error|bool
78 */
79 public function permissions_check() {
80 if ( ! current_user_can( 'manage_options' ) ) {
81 return new WP_Error( 'rest_forbidden', __( 'Sorry, you cannot access this route', 'sureforms' ), [ 'status' => rest_authorization_required_code() ] );
82 }
83 return true;
84 }
85
86 /**
87 * Validate Turnstile token
88 *
89 * @param string $secret_key Turnstile token.
90 * @param string|false $response Response.
91 * @param string|false $remote_ip Remote IP.
92 * @return array<mixed>|mixed Result of the validation.
93 */
94 public static function validate_turnstile_token( $secret_key, $response, $remote_ip ) {
95
96 if ( empty( $secret_key ) || ! is_string( $secret_key ) ) {
97 return [
98 'success' => false,
99 'error' => 'Cloudflare Turnstile secret key is invalid.',
100 ];
101 }
102
103 if ( empty( $response ) ) {
104 return [
105 'success' => false,
106 'error' => 'Cloudflare Turnstile response is missing.',
107 ];
108 }
109
110 $body = [
111 'secret' => $secret_key,
112 'response' => $response,
113 'remoteip' => $remote_ip,
114 ];
115
116 $url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
117
118 $args = [
119 'body' => $body,
120 'timeout' => 15,
121 ];
122
123 $response = wp_remote_post( $url, $args );
124
125 if ( is_wp_error( $response ) ) {
126 $error_message = $response->get_error_message();
127 return [
128 'success' => false,
129 'error' => $error_message,
130 ];
131 }
132
133 return json_decode( wp_remote_retrieve_body( $response ), true );
134 }
135
136 /**
137 * Validate hCaptcha token
138 *
139 * @param string $secret_key hCaptcha token.
140 * @param string|false $response Response.
141 * @param string|false $remote_ip Remote IP.
142 * @since 0.0.5
143 * @return array<mixed>|mixed Result of the validation.
144 */
145 public static function validate_hcaptcha_token( $secret_key, $response, $remote_ip ) {
146
147 if ( empty( $secret_key ) || ! is_string( $secret_key ) ) {
148 return [
149 'success' => false,
150 'error' => 'hCaptcha secret key is invalid.',
151 ];
152 }
153
154 if ( empty( $response ) ) {
155 return [
156 'success' => false,
157 'error' => 'hCaptcha response is missing.',
158 ];
159 }
160
161 $body = [
162 'secret' => $secret_key,
163 'response' => $response,
164 'remoteip' => $remote_ip,
165 ];
166
167 $url = 'https://api.hcaptcha.com/siteverify';
168
169 $args = [
170 'body' => $body,
171 'timeout' => 15,
172 ];
173
174 $response = wp_remote_post( $url, $args );
175
176 if ( is_wp_error( $response ) ) {
177 $error_message = $response->get_error_message();
178 return [
179 'success' => false,
180 'error' => $error_message,
181 ];
182 }
183
184 return json_decode( wp_remote_retrieve_body( $response ), true );
185 }
186
187 /**
188 * Handle Form Submission
189 *
190 * @param \WP_REST_Request $request Request object or array containing form data.
191 * @since 0.0.1
192 * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure.
193 */
194 public function handle_form_submission( $request ) {
195
196 $nonce = Helper::get_string_value( $request->get_header( 'X-WP-Nonce' ) );
197
198 if ( ! wp_verify_nonce( sanitize_text_field( $nonce ), 'wp_rest' ) ) {
199 wp_send_json_error(
200 [
201 'data' => __( 'Nonce verification failed.', 'sureforms' ),
202 'status' => false,
203 ]
204 );
205 }
206
207 $form_data = Helper::sanitize_by_field_type( $request->get_params() );
208
209 if ( empty( $form_data ) || ! is_array( $form_data ) ) {
210 wp_send_json_error( __( 'Form data is not found.', 'sureforms' ) );
211 }
212
213 if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] && ! empty( $_FILES ) ) {
214 add_filter( 'upload_dir', [ $this, 'change_upload_dir' ] );
215
216 foreach ( $_FILES as $field => $file ) {
217 if ( is_array( $file['name'] ) ) {
218 foreach ( $file['name'] as $key => $filename ) {
219 $temp_path = $file['tmp_name'][ $key ];
220 $file_size = $file['size'][ $key ];
221 $file_type = $file['type'][ $key ];
222 $file_error = $file['error'][ $key ];
223
224 if ( ! $filename && ! $temp_path && ! $file_size && ! $file_type ) {
225 $form_data[ $field ][] = '';
226 continue;
227 }
228
229 $uploaded_file = [
230 'name' => $filename,
231 'type' => $file_type,
232 'tmp_name' => $temp_path,
233 'error' => $file_error,
234 'size' => $file_size,
235 ];
236
237 $upload_overrides = [
238 'test_form' => false,
239 ];
240 $move_file = wp_handle_upload( $uploaded_file, $upload_overrides );
241 remove_filter( 'upload_dir', [ $this, 'change_upload_dir' ] );
242
243 if ( $move_file && ! isset( $move_file['error'] ) ) {
244 $form_data[ $field ][] = $move_file['url'];
245 } else {
246 wp_send_json_error( __( 'File is not uploaded', 'sureforms' ) );
247 }
248 }
249 } else {
250 $form_data[ $field ][] = '';
251 }
252 }
253 }
254
255 if ( ! $form_data['form-id'] ) {
256 wp_send_json_error( __( 'Form Id is missing.', 'sureforms' ) );
257 }
258 $current_form_id = $form_data['form-id'];
259 $security_type = Helper::get_meta_value( Helper::get_integer_value( $current_form_id ), '_srfm_captcha_security_type' );
260 $selected_captcha_type = get_post_meta( Helper::get_integer_value( $current_form_id ), '_srfm_form_recaptcha', true ) ? Helper::get_string_value( get_post_meta( Helper::get_integer_value( $current_form_id ), '_srfm_form_recaptcha', true ) ) : '';
261
262 if ( 'none' !== $security_type ) {
263 $global_setting_options = get_option( 'srfm_security_settings_options' );
264 } else {
265 $global_setting_options = [];
266 }
267
268 if ( 'g-recaptcha' === $security_type ) {
269 switch ( $selected_captcha_type ) {
270 case 'v2-checkbox':
271 $key = 'srfm_v2_checkbox_secret_key';
272 break;
273 case 'v2-invisible':
274 $key = 'srfm_v2_invisible_secret_key';
275 break;
276 case 'v3-reCAPTCHA':
277 $key = 'srfm_v3_secret_key';
278 break;
279 default:
280 $key = '';
281 break;
282 }
283
284 $google_captcha_secret_key = is_array( $global_setting_options ) && isset( $global_setting_options[ $key ] ) ? $global_setting_options[ $key ] : '';
285 }
286
287 if ( 'cf-turnstile' === $security_type ) {
288 // Turnstile validation.
289 $srfm_cf_turnstile_secret_key = is_array( $global_setting_options ) && isset( $global_setting_options['srfm_cf_turnstile_secret_key'] ) ? Helper::get_string_value( $global_setting_options['srfm_cf_turnstile_secret_key'] ) : '';
290 $cf_response = ! empty( $form_data['cf-turnstile-response'] ) ? $form_data['cf-turnstile-response'] : false;
291
292 // if gdpr is enabled then set remote ip to empty.
293 $compliance = get_post_meta( Helper::get_integer_value( $current_form_id ), '_srfm_compliance', true );
294 $gdpr = false;
295
296 if ( is_array( $compliance ) && is_array( $compliance[0] ) ) {
297 $gdpr = ! empty( $compliance[0]['gdpr'] ) ? $compliance[0]['gdpr'] : false;
298 }
299
300 // check if ip logging is disabled in global settings then set remote ip to empty.
301 $gb_general_settinionsgs_opt = get_option( 'srfm_general_settings_options' );
302 $srfm_ip_log = is_array( $gb_general_settinionsgs_opt ) && isset( $gb_general_settinionsgs_opt['srfm_ip_log'] ) ? $gb_general_settinionsgs_opt['srfm_ip_log'] : '';
303
304 $remote_ip = $gdpr || ( ! $srfm_ip_log ) ? '' : ( isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '' );
305
306 $turnstile_validation_result = self::validate_turnstile_token( $srfm_cf_turnstile_secret_key, $cf_response, $remote_ip );
307
308 // If the cloudflare validation fails, return an error.
309 if ( is_array( $turnstile_validation_result ) && isset( $turnstile_validation_result['success'] ) && false === $turnstile_validation_result['success'] ) {
310 $error_message = $turnstile_validation_result['error'] ?? 'Cloudflare Turnstile validation failed.';
311 return new \WP_Error( 'cf_turnstile_error', $error_message, [ 'status' => 403 ] );
312 }
313 }
314
315 if ( 'hcaptcha' === $security_type ) {
316 $srfm_hcaptcha_secret_key = is_array( $global_setting_options ) && isset( $global_setting_options['srfm_hcaptcha_secret_key'] ) ? Helper::get_string_value( $global_setting_options['srfm_hcaptcha_secret_key'] ) : '';
317 $hcaptcha_response = ! empty( $form_data['h-captcha-response'] ) ? $form_data['h-captcha-response'] : false;
318
319 // if gdpr is enabled then set remote ip to empty.
320 $compliance = get_post_meta( Helper::get_integer_value( $current_form_id ), '_srfm_compliance', true );
321 $gdpr = false;
322
323 if ( is_array( $compliance ) && is_array( $compliance[0] ) ) {
324 $gdpr = ! empty( $compliance[0]['gdpr'] ) ? $compliance[0]['gdpr'] : false;
325 }
326
327 // check if ip logging is disabled in global settings then set remote ip to empty.
328 $gb_general_settings_options = get_option( 'srfm_general_settings_options' );
329 $srfm_ip_log = is_array( $gb_general_settings_options ) && isset( $gb_general_settings_options['srfm_ip_log'] ) ? $gb_general_settings_options['srfm_ip_log'] : '';
330
331 $remote_ip = $gdpr || ( ! $srfm_ip_log ) ? '' : ( isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '' );
332 $hcaptcha_validation_result = self::validate_hcaptcha_token( $srfm_hcaptcha_secret_key, $hcaptcha_response, $remote_ip );
333
334 // If the hcaptcha validation fails, return an error.
335 if ( is_array( $hcaptcha_validation_result ) && isset( $hcaptcha_validation_result['success'] ) && false === $hcaptcha_validation_result['success'] ) {
336 $error_message = $hcaptcha_validation_result['error'] ?? 'hCaptcha validation failed.';
337 return new \WP_Error( 'hcaptcha_error', $error_message, [ 'status' => 403 ] );
338 }
339 }
340
341 if ( isset( $form_data['srfm-honeypot-field'] ) && empty( $form_data['srfm-honeypot-field'] ) ) {
342 if ( ! empty( $google_captcha_secret_key ) ) {
343 if ( isset( $form_data['sureforms_form_submit'] ) ) {
344 $secret_key = $google_captcha_secret_key;
345 $ipaddress = isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '';
346 $captcha_response = $form_data['g-recaptcha-response'];
347 $url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secret_key . '&response=' . $captcha_response . '&ip=' . $ipaddress;
348
349 $response = wp_remote_get( $url );
350
351 if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) {
352 $json_string = wp_remote_retrieve_body( $response );
353 $data = (array) json_decode( $json_string, true );
354 } else {
355 $data = [];
356 }
357 $sureforms_captcha_data = $data;
358
359 } else {
360 return new \WP_Error( 'recaptcha_error', 'reCAPTCHA error.', [ 'status' => 403 ] );
361 }
362 if ( isset( $sureforms_captcha_data['success'] ) && true === $sureforms_captcha_data['success'] ) {
363 return rest_ensure_response( $this->handle_form_entry( $form_data ) );
364 }
365 return new \WP_Error( 'recaptcha_error', 'reCAPTCHA error.', [ 'status' => 403 ] );
366
367 }
368 return rest_ensure_response( $this->handle_form_entry( $form_data ) );
369
370 }
371 if ( ! isset( $form_data['srfm-honeypot-field'] ) ) {
372 if ( ! empty( $google_captcha_secret_key ) ) {
373 if ( isset( $form_data['sureforms_form_submit'] ) ) {
374 $secret_key = $google_captcha_secret_key;
375 $ipaddress = isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '';
376 $captcha_response = $form_data['g-recaptcha-response'];
377 $url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secret_key . '&response=' . $captcha_response . '&ip=' . $ipaddress;
378
379 $response = wp_remote_get( $url );
380
381 if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) {
382 $json_string = wp_remote_retrieve_body( $response );
383 $data = (array) json_decode( $json_string, true );
384 } else {
385 $data = [];
386 }
387 $sureforms_captcha_data = $data;
388
389 } else {
390 return new \WP_Error( 'recaptcha_error', 'reCAPTCHA error.', [ 'status' => 403 ] );
391 }
392 if ( true === $sureforms_captcha_data['success'] ) {
393 return rest_ensure_response( $this->handle_form_entry( $form_data ) );
394 }
395 return new \WP_Error( 'recaptcha_error', 'reCAPTCHA error.', [ 'status' => 403 ] );
396
397 }
398 return rest_ensure_response( $this->handle_form_entry( $form_data ) );
399
400 }
401 return new \WP_Error( 'spam_detected', 'Spam Detected', [ 'status' => 403 ] );
402 }
403
404 /**
405 * Change the upload directory
406 *
407 * @param array<mixed> $dirs upload directory.
408 * @return array<mixed>
409 * @since 0.0.1
410 */
411 public function change_upload_dir( $dirs ) {
412 $dirs['subdir'] = '/sureforms';
413 $dirs['path'] = $dirs['basedir'] . $dirs['subdir'];
414 $dirs['url'] = $dirs['baseurl'] . $dirs['subdir'];
415 return $dirs;
416 }
417
418 /**
419 * Send Email and Create Entry.
420 *
421 * @param array<string> $form_data Request object or array containing form data.
422 * @since 0.0.1
423 * @return array<mixed> Array containing the response data.
424 */
425 public function handle_form_entry( $form_data ) {
426
427 $id = sanitize_text_field( $form_data['form-id'] );
428
429 // Get the compliance settings.
430 $compliance = get_post_meta( Helper::get_integer_value( $id ), '_srfm_compliance', true );
431 $gdpr = '';
432 $do_not_store_entries = '';
433
434 if ( is_array( $compliance ) && is_array( $compliance[0] ) ) {
435 $gdpr = $compliance[0]['gdpr'] ?? '';
436 $do_not_store_entries = $compliance[0]['do_not_store_entries'] ?? '';
437 }
438
439 $submission_data = [];
440
441 $form_data_keys = array_keys( $form_data );
442 $form_data_count = count( $form_data );
443
444 for ( $i = 4; $i < $form_data_count; $i++ ) {
445 $key = strval( $form_data_keys[ $i ] );
446 $value = $form_data[ $key ];
447
448 $field_name = htmlspecialchars( str_replace( '_', ' ', $key ) );
449
450 // If the field is an array, encode the values. This is to add support for multi-upload field.
451 if ( is_array( $value ) ) {
452 $submission_data[ $field_name ] =
453 array_map(
454 static function ( $val ) {
455 return rawurlencode( $val );
456 },
457 $value
458 );
459 } else {
460 $submission_data[ $field_name ] = htmlspecialchars( $value );
461 }
462 }
463
464 $name = sanitize_text_field( get_the_title( intval( $id ) ) );
465 $send_email = $this->send_email( $id, $submission_data );
466 $emails = [];
467
468 if ( $send_email ) {
469 $emails = $send_email['emails'];
470 }
471
472 // Check if GDPR is enabled and do not store entries is enabled.
473 // If so, send email and do not store entries.
474 if ( $gdpr && $do_not_store_entries ) {
475
476 $modified_message = $this->prepare_submission_data( $submission_data );
477
478 $form_submit_response = [
479 'success' => true,
480 'form_id' => $id ? intval( $id ) : '',
481 'to_emails' => $emails,
482 'form_name' => $name ? esc_attr( $name ) : '',
483 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
484 'data' => $modified_message,
485 ];
486
487 do_action( 'srfm_form_submit', $form_submit_response );
488
489 /**
490 * Hook for enabling background processes.
491 *
492 * @param array $form_data form data related to submission.
493 */
494 do_action( 'srfm_after_submission_process', $form_data );
495
496 return [
497 'success' => true,
498 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
499 'data' => [
500 'name' => $name,
501 'after_submit' => false,
502 ],
503 'redirect_url' => Generate_Form_Markup::get_redirect_url( $form_data, $submission_data ),
504 ];
505
506 }
507
508 $global_setting_options = get_option( 'srfm_general_settings_options' );
509
510 // If GDPR is enabled, do not store IP, browser, and device info.
511 // If not, store IP, browser, and device info.
512 $user_ip = '';
513 $browser_name = '';
514 $device_name = '';
515 if ( ! $gdpr ) {
516 $srfm_ip_log = is_array( $global_setting_options ) && isset( $global_setting_options['srfm_ip_log'] ) ? $global_setting_options['srfm_ip_log'] : '';
517
518 $user_ip = $srfm_ip_log && isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '';
519 $browser = new Browser();
520 $browser_name = sanitize_text_field( $browser->getBrowser() );
521 $device_name = sanitize_text_field( $browser->getPlatform() );
522 }
523
524 $form_markup = get_the_content( null, false, Helper::get_integer_value( $form_data['form-id'] ) );
525 $pattern = '/"label":"(.*?)"/';
526 preg_match_all( $pattern, $form_markup, $matches );
527 $submission_info = [
528 'user_ip' => $user_ip,
529 'browser_name' => $browser_name,
530 'device_name' => $device_name,
531 ];
532 $entries_data = [
533 'form_id' => $id,
534 'form_data' => $submission_data,
535 'submission_info' => $submission_info,
536 ];
537 if ( is_user_logged_in() ) {
538 // If user is logged in then save their user id.
539 $entries_data['user_id'] = get_current_user_id();
540 }
541 $entry_id = Entries::add( $entries_data );
542 if ( $entry_id ) {
543
544 $response = [
545 'success' => true,
546 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
547 'data' => [
548 'name' => $name,
549 'submission_id' => $entry_id,
550 'after_submit' => true,
551 ],
552 'redirect_url' => Generate_Form_Markup::get_redirect_url( $form_data, $submission_data ),
553 ];
554
555 $modified_message = $this->prepare_submission_data( $submission_data );
556
557 $form_submit_response = apply_filters(
558 'srfm_form_submit_response',
559 [
560 'success' => true,
561 'form_id' => $id ? intval( $id ) : '',
562 'to_emails' => $emails,
563 'form_name' => $name ? esc_attr( $name ) : '',
564 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
565 'data' => $modified_message,
566 ]
567 );
568
569 do_action( 'srfm_form_submit', $form_submit_response );
570 } else {
571 $response = [
572 'success' => false,
573 'message' => __( 'Error submitting form', 'sureforms' ),
574 ];
575 }
576
577 return $response;
578 }
579
580 /**
581 * Prepare submission data.
582 *
583 * @param array<mixed> $submission_data Submission data.
584 * @since 0.0.7
585 * @return array<mixed> Modified submission data.
586 */
587 public function prepare_submission_data( $submission_data ) {
588 $modified_message = [];
589 foreach ( $submission_data as $key => $value ) {
590 $parts = explode( '-lbl-', $key );
591 $label = '';
592
593 if ( ! empty( $parts[1] ) ) {
594 $tokens = explode( '-', $parts[1] );
595 if ( count( $tokens ) > 1 ) {
596 $label = implode( '-', array_slice( $tokens, 1 ) );
597 }
598
599 $fields = explode( '-', $parts[0] );
600
601 // Since the upload field returns an array of file URLs, we need to implode them with a comma.
602 if ( 'upload' === $fields[1] && ! empty( $value ) && is_array( $value ) ) {
603 $modified_message[ $label ] = urldecode( implode( ', ', $value ) );
604 } else {
605 $modified_message[ $label ] = html_entity_decode( esc_attr( Helper::get_string_value( $value ) ) );
606 }
607 }
608 }
609
610 return $modified_message;
611 }
612
613 /**
614 * Send Email.
615 *
616 * @param string $id Form ID.
617 * @param array<mixed> $submission_data Submission data.
618 * @since 0.0.1
619 * @return array<mixed> Array containing the response data.
620 */
621 public static function send_email( $id, $submission_data ) {
622 $email_notification = get_post_meta( intval( $id ), '_srfm_email_notification' );
623 $smart_tags = new Smart_Tags();
624 $is_mail_sent = false;
625 $emails = [];
626
627 if ( is_iterable( $email_notification ) ) {
628 $entries_db_instance = Entries::get_instance();
629 $log_key = $entries_db_instance->add_log( __( 'Email Notification Initiated', 'sureforms' ) );
630
631 foreach ( $email_notification as $notification ) {
632 foreach ( $notification as $item ) {
633 if ( true === $item['status'] ) {
634 $from = Helper::get_string_value( get_option( 'admin_email' ) );
635 $to = $smart_tags->process_smart_tags( $item['email_to'], $submission_data );
636 $subject = $smart_tags->process_smart_tags( $item['subject'], $submission_data );
637 $email_body = $smart_tags->process_smart_tags( $item['email_body'], $submission_data );
638 $email_template = new Email_Template();
639 $message = $email_template->render( $submission_data, $email_body );
640 $headers = "From: {$from}\r\nX-Mailer: PHP/" . phpversion() . "\r\nContent-Type: text/html; charset=utf-8\r\n";
641 if ( isset( $item['email_reply_to'] ) && ! empty( $item['email_reply_to'] ) ) {
642 $headers .= 'Reply-To:' . $smart_tags->process_smart_tags( $item['email_reply_to'], $submission_data ) . "\r\n";
643 } else {
644 $headers .= "Reply-To: {$from}\r\n";
645 }
646 if ( isset( $item['email_cc'] ) && ! empty( $item['email_cc'] ) ) {
647 $headers .= 'Cc:' . $smart_tags->process_smart_tags( $item['email_cc'], $submission_data ) . "\r\n";
648 }
649 if ( isset( $item['email_bcc'] ) && ! empty( $item['email_bcc'] ) ) {
650 $headers .= 'Bcc:' . $smart_tags->process_smart_tags( $item['email_bcc'], $submission_data ) . "\r\n";
651 }
652
653 $sent = wp_mail( $to, $subject, $message, $headers );
654
655 if ( is_int( $log_key ) ) {
656 $entries_db_instance->update_log(
657 $log_key,
658 null,
659 [
660 /* translators: Here, %s is the comma separated emails list. */
661 $sent ? sprintf( __( 'Email notification sent to %s', 'sureforms' ), esc_html( $to ) ) : sprintf( __( 'Failed sending email notification to %s', 'sureforms' ), esc_html( $to ) ),
662 ]
663 );
664 }
665
666 $is_mail_sent = $sent;
667 $emails[] = $to;
668 }
669 }
670 }
671 }
672
673 return [
674 'success' => $is_mail_sent,
675 'emails' => $emails,
676 ];
677 }
678
679 /**
680 * Retrieve all entries data for a specific form ID to check for unique values.
681 *
682 * @since 0.0.1
683 * @return void
684 */
685 public function field_unique_validation() {
686 if ( isset( $_POST['nonce'] ) && ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'unique_validation_nonce' ) ) {
687 $error_message = 'Nonce verification failed.';
688 $error_data = [
689 'error' => $error_message,
690 ];
691 wp_send_json_error( $error_data );
692 }
693
694 global $wpdb;
695 $id = isset( $_POST['id'] ) ? absint( wp_unslash( $_POST['id'] ) ) : 0;
696 $meta_value = $id;
697
698 if ( ! $meta_value ) {
699 $error_message = 'Invalid form ID.';
700 $error_data = [
701 'error' => $error_message,
702 ];
703 wp_send_json_error( $error_data );
704 }
705
706 $_POST = array_map( 'wp_unslash', $_POST );
707
708 // Get the entry IDs for the particualr form to perform unique field validation.
709 $entry_ids = Entries::get_all_entry_ids_for_form( $id );
710
711 $all_form_entries = [];
712 $keys = array_keys( $_POST );
713 $length = count( $keys );
714
715 for ( $i = 3; $i < $length; $i++ ) {
716 $key = $keys[ $i ];
717 $value = isset( $_POST[ $key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) : '';
718 $key = str_replace( '_', ' ', $keys[ $i ] );
719
720 foreach ( $entry_ids as $entry_id ) {
721 $entry_id = is_array( $entry_id ) ? Helper::get_integer_value( $entry_id['ID'] ) : 0;
722 $form_data = Entries::get_form_data( $entry_id );
723 if ( is_array( $form_data ) && isset( $form_data[ $key ] ) && $form_data[ $key ] === $value ) {
724 $obj = [ $key => 'not unique' ];
725 array_push( $all_form_entries, $obj );
726 break;
727 }
728 }
729 }
730
731 $results = [
732 'data' => $all_form_entries,
733 ];
734
735 wp_send_json( $results );
736 }
737
738 /**
739 * Function to save allowed block data.
740 *
741 * @since 0.0.1
742 * @return void
743 */
744 public function srfm_global_update_allowed_block() {
745 if ( ! current_user_can( 'manage_options' ) ) {
746 wp_send_json_error();
747 }
748
749 if ( ! check_ajax_referer( 'srfm_ajax_nonce', 'security', false ) ) {
750 wp_send_json_error();
751 }
752
753 if ( ! empty( $_POST['defaultAllowedQuickSidebarBlocks'] ) ) {
754 $srfm_default_allowed_quick_sidebar_blocks = json_decode( sanitize_text_field( wp_unslash( $_POST['defaultAllowedQuickSidebarBlocks'] ) ), true );
755 Helper::update_admin_settings_option( 'srfm_quick_sidebar_allowed_blocks', $srfm_default_allowed_quick_sidebar_blocks );
756 wp_send_json_success();
757 }
758 wp_send_json_error();
759 }
760
761 /**
762 * Function to save enable/disable data.
763 *
764 * @since 0.0.1
765 * @return void
766 */
767 public function srfm_global_sidebar_enabled() {
768 if ( ! current_user_can( 'manage_options' ) ) {
769 wp_send_json_error();
770 }
771
772 if ( ! check_ajax_referer( 'srfm_ajax_nonce', 'security', false ) ) {
773 wp_send_json_error();
774 }
775
776 if ( ! empty( $_POST['enableQuickActionSidebar'] ) ) {
777 $srfm_enable_quick_action_sidebar = ( 'enabled' === $_POST['enableQuickActionSidebar'] ? 'enabled' : 'disabled' );
778 Helper::update_admin_settings_option( 'srfm_enable_quick_action_sidebar', $srfm_enable_quick_action_sidebar );
779 wp_send_json_success();
780 }
781 wp_send_json_error();
782 }
783 }
784