PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 1.1.2
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v1.1.2
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.1.2, at inc/form-submit.php

849 lines 27.7 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.', 'sureforms' ),
100 ];
101 }
102
103 if ( empty( $response ) ) {
104 return [
105 'success' => false,
106 'error' => __( 'Cloudflare Turnstile response is missing.', 'sureforms' ),
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.', 'sureforms' ),
151 ];
152 }
153
154 if ( empty( $response ) ) {
155 return [
156 'success' => false,
157 'error' => __( 'hCaptcha response is missing.', 'sureforms' ),
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 ( ! $form_data['form-id'] ) {
214 wp_send_json_error( __( 'Form Id is missing.', 'sureforms' ) );
215 }
216 $current_form_id = $form_data['form-id'];
217 $security_type = Helper::get_meta_value( Helper::get_integer_value( $current_form_id ), '_srfm_captcha_security_type' );
218 $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 ) ) : '';
219
220 if ( 'none' !== $security_type ) {
221 $global_setting_options = get_option( 'srfm_security_settings_options' );
222 } else {
223 $global_setting_options = [];
224 }
225
226 if ( 'g-recaptcha' === $security_type ) {
227 switch ( $selected_captcha_type ) {
228 case 'v2-checkbox':
229 $key = 'srfm_v2_checkbox_secret_key';
230 break;
231 case 'v2-invisible':
232 $key = 'srfm_v2_invisible_secret_key';
233 break;
234 case 'v3-reCAPTCHA':
235 $key = 'srfm_v3_secret_key';
236 break;
237 default:
238 $key = '';
239 break;
240 }
241
242 $google_captcha_secret_key = is_array( $global_setting_options ) && isset( $global_setting_options[ $key ] ) ? $global_setting_options[ $key ] : '';
243 }
244
245 if ( 'cf-turnstile' === $security_type ) {
246 // Turnstile validation.
247 $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'] ) : '';
248 $cf_response = ! empty( $form_data['cf-turnstile-response'] ) ? $form_data['cf-turnstile-response'] : false;
249
250 // if gdpr is enabled then set remote ip to empty.
251 $compliance = get_post_meta( Helper::get_integer_value( $current_form_id ), '_srfm_compliance', true );
252 $gdpr = false;
253
254 if ( is_array( $compliance ) && is_array( $compliance[0] ) ) {
255 $gdpr = ! empty( $compliance[0]['gdpr'] ) ? $compliance[0]['gdpr'] : false;
256 }
257
258 // check if ip logging is disabled in global settings then set remote ip to empty.
259 $gb_general_settinionsgs_opt = get_option( 'srfm_general_settings_options' );
260 $srfm_ip_log = is_array( $gb_general_settinionsgs_opt ) && isset( $gb_general_settinionsgs_opt['srfm_ip_log'] ) ? $gb_general_settinionsgs_opt['srfm_ip_log'] : '';
261
262 $remote_ip = $gdpr || ( ! $srfm_ip_log ) ? '' : ( isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '' );
263
264 $turnstile_validation_result = self::validate_turnstile_token( $srfm_cf_turnstile_secret_key, $cf_response, $remote_ip );
265
266 // If the cloudflare validation fails, return an error.
267 if ( is_array( $turnstile_validation_result ) && isset( $turnstile_validation_result['success'] ) && false === $turnstile_validation_result['success'] ) {
268 $error_message = $turnstile_validation_result['error'] ?? __( 'Cloudflare Turnstile validation failed.', 'sureforms' );
269 return new \WP_Error( 'cf_turnstile_error', $error_message, [ 'status' => 403 ] );
270 }
271 }
272
273 if ( 'hcaptcha' === $security_type ) {
274 $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'] ) : '';
275 $hcaptcha_response = ! empty( $form_data['h-captcha-response'] ) ? $form_data['h-captcha-response'] : false;
276
277 // if gdpr is enabled then set remote ip to empty.
278 $compliance = get_post_meta( Helper::get_integer_value( $current_form_id ), '_srfm_compliance', true );
279 $gdpr = false;
280
281 if ( is_array( $compliance ) && is_array( $compliance[0] ) ) {
282 $gdpr = ! empty( $compliance[0]['gdpr'] ) ? $compliance[0]['gdpr'] : false;
283 }
284
285 // check if ip logging is disabled in global settings then set remote ip to empty.
286 $gb_general_settings_options = get_option( 'srfm_general_settings_options' );
287 $srfm_ip_log = is_array( $gb_general_settings_options ) && isset( $gb_general_settings_options['srfm_ip_log'] ) ? $gb_general_settings_options['srfm_ip_log'] : '';
288
289 $remote_ip = $gdpr || ( ! $srfm_ip_log ) ? '' : ( isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '' );
290 $hcaptcha_validation_result = self::validate_hcaptcha_token( $srfm_hcaptcha_secret_key, $hcaptcha_response, $remote_ip );
291
292 // If the hcaptcha validation fails, return an error.
293 if ( is_array( $hcaptcha_validation_result ) && isset( $hcaptcha_validation_result['success'] ) && false === $hcaptcha_validation_result['success'] ) {
294 $error_message = $hcaptcha_validation_result['error'] ?? __( 'hCaptcha validation failed.', 'sureforms' );
295 return new \WP_Error( 'hcaptcha_error', $error_message, [ 'status' => 403 ] );
296 }
297 }
298
299 if ( isset( $form_data['srfm-honeypot-field'] ) && empty( $form_data['srfm-honeypot-field'] ) ) {
300 if ( ! empty( $google_captcha_secret_key ) ) {
301 if ( isset( $form_data['sureforms_form_submit'] ) ) {
302 $secret_key = $google_captcha_secret_key;
303 $ipaddress = isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '';
304 $captcha_response = $form_data['g-recaptcha-response'];
305 $url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secret_key . '&response=' . $captcha_response . '&ip=' . $ipaddress;
306
307 $response = wp_remote_get( $url );
308
309 if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) {
310 $json_string = wp_remote_retrieve_body( $response );
311 $data = (array) json_decode( $json_string, true );
312 } else {
313 $data = [];
314 }
315 $sureforms_captcha_data = $data;
316
317 } else {
318 return new \WP_Error( 'recaptcha_error', __( 'reCAPTCHA error.', 'sureforms' ), [ 'status' => 403 ] );
319 }
320 if ( isset( $sureforms_captcha_data['success'] ) && true === $sureforms_captcha_data['success'] ) {
321 return rest_ensure_response( $this->handle_form_entry( $form_data ) );
322 }
323 return new \WP_Error( 'recaptcha_error', __( 'reCAPTCHA error.', 'sureforms' ), [ 'status' => 403 ] );
324
325 }
326 return rest_ensure_response( $this->handle_form_entry( $form_data ) );
327
328 }
329 if ( ! isset( $form_data['srfm-honeypot-field'] ) ) {
330 if ( ! empty( $google_captcha_secret_key ) ) {
331 if ( isset( $form_data['sureforms_form_submit'] ) ) {
332 $secret_key = $google_captcha_secret_key;
333 $ipaddress = isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '';
334 $captcha_response = $form_data['g-recaptcha-response'];
335 $url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secret_key . '&response=' . $captcha_response . '&ip=' . $ipaddress;
336
337 $response = wp_remote_get( $url );
338
339 if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) {
340 $json_string = wp_remote_retrieve_body( $response );
341 $data = (array) json_decode( $json_string, true );
342 } else {
343 $data = [];
344 }
345 $sureforms_captcha_data = $data;
346
347 } else {
348 return new \WP_Error( 'recaptcha_error', __( 'reCAPTCHA error.', 'sureforms' ), [ 'status' => 403 ] );
349 }
350 if ( true === $sureforms_captcha_data['success'] ) {
351 return rest_ensure_response( $this->handle_form_entry( $form_data ) );
352 }
353 return new \WP_Error( 'recaptcha_error', __( 'reCAPTCHA error.', 'sureforms' ), [ 'status' => 403 ] );
354
355 }
356 return rest_ensure_response( $this->handle_form_entry( $form_data ) );
357
358 }
359 return new \WP_Error( 'spam_detected', __( 'Spam Detected', 'sureforms' ), [ 'status' => 403 ] );
360 }
361
362 /**
363 * Change the upload directory
364 *
365 * @param array<mixed> $dirs upload directory.
366 * @return array<mixed>
367 * @since 0.0.1
368 */
369 public function change_upload_dir( $dirs ) {
370 $dirs['subdir'] = '/sureforms';
371 $dirs['path'] = $dirs['basedir'] . $dirs['subdir'];
372 $dirs['url'] = $dirs['baseurl'] . $dirs['subdir'];
373 return $dirs;
374 }
375
376 /**
377 * Send Email and Create Entry.
378 *
379 * @param array<string> $form_data Request object or array containing form data.
380 * @since 0.0.1
381 * @return array<mixed> Array containing the response data.
382 */
383 public function handle_form_entry( $form_data ) {
384 $is_error = false;
385 if ( defined( 'SRFM_PRO_VER' ) && isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] && ! empty( $_FILES ) ) {
386 add_filter( 'upload_dir', [ $this, 'change_upload_dir' ] );
387
388 // Get the file types.
389 $file_types = Helper::get_wp_file_types();
390
391 // Get the allowed file types.
392 $allowed_file_types = $file_types['formats'];
393
394 // Allowed file types should be array.
395 if ( ! is_array( $allowed_file_types ) ) {
396 $is_error = true;
397 wp_send_json_error(
398 [
399 'message' => __( 'File types are not allowed', 'sureforms' ),
400 ]
401 );
402 }
403
404 foreach ( $_FILES as $field => $file ) {
405 if ( is_array( $file['name'] ) ) {
406 foreach ( $file['name'] as $key => $filename ) {
407 $temp_path = $file['tmp_name'][ $key ];
408 $file_size = $file['size'][ $key ];
409 $file_type = $file['type'][ $key ];
410 $file_error = $file['error'][ $key ];
411
412 if ( ! $filename && ! $temp_path && ! $file_size && ! $file_type ) {
413 $form_data[ $field ][] = '';
414 continue;
415 }
416
417 // Check if the file type is allowed.
418 $get_file_type = explode( '/', $file_type );
419
420 // Check isset $get_file_type[1] it should be string.
421 if ( ! isset( $get_file_type[1] ) ) {
422 $is_error = true;
423 continue;
424 }
425
426 // $get_file_type[1] should be string.
427 if ( ! is_string( $get_file_type[1] ) ) {
428 $is_error = true;
429 continue;
430 }
431
432 // Check if the file type is allowed.
433 if ( ! in_array( $get_file_type[1], $allowed_file_types, true ) ) {
434 $is_error = true;
435 continue;
436 }
437
438 $uploaded_file = [
439 'name' => sanitize_file_name( $filename ),
440 'type' => $file_type,
441 'tmp_name' => $temp_path,
442 'error' => $file_error,
443 'size' => $file_size,
444 ];
445
446 $upload_overrides = [
447 'test_form' => false,
448 ];
449 $move_file = wp_handle_upload( $uploaded_file, $upload_overrides );
450 remove_filter( 'upload_dir', [ $this, 'change_upload_dir' ] );
451
452 if ( $move_file && ! isset( $move_file['error'] ) ) {
453 $form_data[ $field ][] = $move_file['url'];
454 } else {
455 $is_error = true;
456 continue;
457 }
458 }
459 } else {
460 $form_data[ $field ][] = '';
461 }
462 }
463 }
464
465 if ( $is_error ) {
466 wp_send_json_error(
467 [
468 'message' => __( 'File is not uploaded', 'sureforms' ),
469 ]
470 );
471 }
472
473 $id = sanitize_text_field( $form_data['form-id'] );
474
475 // Get the compliance settings.
476 $compliance = get_post_meta( Helper::get_integer_value( $id ), '_srfm_compliance', true );
477 $gdpr = '';
478 $do_not_store_entries = '';
479
480 if ( is_array( $compliance ) && is_array( $compliance[0] ) ) {
481 $gdpr = $compliance[0]['gdpr'] ?? '';
482 $do_not_store_entries = $compliance[0]['do_not_store_entries'] ?? '';
483 }
484
485 $submission_data = [];
486
487 $form_data_keys = array_keys( $form_data );
488 $form_data_count = count( $form_data );
489
490 for ( $i = 0; $i < $form_data_count; $i++ ) {
491 $key = strval( $form_data_keys[ $i ] );
492
493 /**
494 * This will allow to pass only sureforms fields
495 * checking -lbl- as thats mandatory for in key of sureforms fields.
496 */
497 if ( false === str_contains( $key, '-lbl-' ) ) {
498 continue;
499 }
500
501 $value = $form_data[ $key ];
502
503 $field_name = htmlspecialchars( str_replace( '_', ' ', $key ) );
504
505 // If the field is an array, encode the values. This is to add support for multi-upload field.
506 if ( is_array( $value ) ) {
507 $submission_data[ $field_name ] =
508 array_map(
509 static function ( $val ) {
510 return rawurlencode( $val );
511 },
512 $value
513 );
514 } else {
515 $submission_data[ $field_name ] = htmlspecialchars( $value );
516 }
517 }
518
519 $modified_message = $this->prepare_submission_data( $submission_data );
520
521 $form_before_submission_data = [
522 'form_id' => $id ? intval( $id ) : '',
523 'data' => $modified_message,
524 ];
525
526 /**
527 * Fires before submission process starts.
528 */
529 do_action( 'srfm_before_submission', $form_before_submission_data );
530
531 $name = sanitize_text_field( get_the_title( intval( $id ) ) );
532 $send_email = $this->send_email( $id, $submission_data, $form_data );
533 $emails = [];
534
535 if ( $send_email ) {
536 $emails = $send_email['emails'];
537 }
538
539 // Check if GDPR is enabled and do not store entries is enabled.
540 // If so, send email and do not store entries.
541 if ( $gdpr && $do_not_store_entries ) {
542
543 $form_submit_response = [
544 'success' => true,
545 'form_id' => $id ? intval( $id ) : '',
546 'to_emails' => $emails,
547 'form_name' => $name ? esc_attr( $name ) : '',
548 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
549 'data' => $modified_message,
550 ];
551
552 do_action( 'srfm_form_submit', $form_submit_response );
553
554 /**
555 * Hook for enabling background processes.
556 *
557 * @param array $form_data form data related to submission.
558 */
559 $form_data['form_id'] = $id ? intval( $id ) : '';
560 do_action( 'srfm_after_submission_process', $form_data );
561
562 return [
563 'success' => true,
564 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
565 'data' => [
566 'name' => $name,
567 'after_submit' => false,
568 ],
569 'redirect_url' => Generate_Form_Markup::get_redirect_url( $form_data, $submission_data ),
570 ];
571
572 }
573
574 $global_setting_options = get_option( 'srfm_general_settings_options' );
575
576 // If GDPR is enabled, do not store IP, browser, and device info.
577 // If not, store IP, browser, and device info.
578 $user_ip = '';
579 $browser_name = '';
580 $device_name = '';
581 if ( ! $gdpr ) {
582 $srfm_ip_log = is_array( $global_setting_options ) && isset( $global_setting_options['srfm_ip_log'] ) ? $global_setting_options['srfm_ip_log'] : '';
583
584 $user_ip = $srfm_ip_log && isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '';
585 $browser = new Browser();
586 $browser_name = sanitize_text_field( $browser->getBrowser() );
587 $device_name = sanitize_text_field( $browser->getPlatform() );
588 }
589
590 $form_markup = get_the_content( null, false, Helper::get_integer_value( $form_data['form-id'] ) );
591 $pattern = '/"label":"(.*?)"/';
592 preg_match_all( $pattern, $form_markup, $matches );
593 $submission_info = [
594 'user_ip' => $user_ip,
595 'browser_name' => $browser_name,
596 'device_name' => $device_name,
597 ];
598 $entries_data = [
599 'form_id' => $id,
600 'form_data' => $submission_data,
601 'submission_info' => $submission_info,
602 ];
603 if ( is_user_logged_in() ) {
604 // If user is logged in then save their user id.
605 $entries_data['user_id'] = get_current_user_id();
606 }
607 $entry_id = Entries::add( $entries_data );
608 if ( $entry_id ) {
609
610 $response = [
611 'success' => true,
612 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
613 'data' => [
614 'name' => $name,
615 'submission_id' => $entry_id,
616 'after_submit' => true,
617 ],
618 'redirect_url' => Generate_Form_Markup::get_redirect_url( $form_data, $submission_data ),
619 ];
620
621 $form_submit_response = apply_filters(
622 'srfm_form_submit_response',
623 [
624 'success' => true,
625 'form_id' => $id ? intval( $id ) : '',
626 'to_emails' => $emails,
627 'form_name' => $name ? esc_attr( $name ) : '',
628 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
629 'data' => $modified_message,
630 ]
631 );
632
633 do_action( 'srfm_form_submit', $form_submit_response );
634 } else {
635 $response = [
636 'success' => false,
637 'message' => __( 'Error submitting form', 'sureforms' ),
638 ];
639 }
640
641 return $response;
642 }
643
644 /**
645 * Prepare submission data.
646 *
647 * @param array<mixed> $submission_data Submission data.
648 * @since 0.0.7
649 * @return array<mixed> Modified submission data.
650 */
651 public function prepare_submission_data( $submission_data ) {
652 $modified_message = [];
653 foreach ( $submission_data as $key => $value ) {
654 $parts = explode( '-lbl-', $key );
655 $label = '';
656
657 if ( ! empty( $parts[1] ) ) {
658 $tokens = explode( '-', $parts[1] );
659 if ( count( $tokens ) > 1 ) {
660 $label = implode( '-', array_slice( $tokens, 1 ) );
661 }
662
663 $fields = explode( '-', $parts[0] );
664
665 // Since the upload field returns an array of file URLs, we need to implode them with a comma.
666 if ( 'upload' === $fields[1] && ! empty( $value ) && is_array( $value ) ) {
667 $modified_message[ $label ] = urldecode( implode( ', ', $value ) );
668 } else {
669 $modified_message[ $label ] = html_entity_decode( esc_attr( Helper::get_string_value( $value ) ) );
670 }
671 }
672 }
673
674 return $modified_message;
675 }
676
677 /**
678 * Send Email.
679 *
680 * @param string $id Form ID.
681 * @param array<mixed> $submission_data Submission data.
682 * @param array<string> $form_data Request object or array containing form data.
683 * @since 0.0.1
684 * @return array<mixed> Array containing the response data.
685 */
686 public static function send_email( $id, $submission_data, $form_data = [] ) {
687 $email_notification = get_post_meta( intval( $id ), '_srfm_email_notification' );
688 $smart_tags = new Smart_Tags();
689 $is_mail_sent = false;
690 $emails = [];
691
692 if ( is_iterable( $email_notification ) ) {
693 $entries_db_instance = Entries::get_instance();
694 $log_key = $entries_db_instance->add_log( __( 'Email Notification Initiated', 'sureforms' ) );
695
696 foreach ( $email_notification as $notification ) {
697 foreach ( $notification as $item ) {
698 if ( true === $item['status'] ) {
699 $from = Helper::get_string_value( get_option( 'admin_email' ) );
700 $to = $smart_tags->process_smart_tags( $item['email_to'], $submission_data );
701 $subject = $smart_tags->process_smart_tags( $item['subject'], $submission_data, $form_data );
702 $email_body = $smart_tags->process_smart_tags( $item['email_body'], $submission_data, $form_data );
703 $email_template = new Email_Template();
704 $message = $email_template->render( $submission_data, $email_body );
705 $headers = "From: {$from}\r\nX-Mailer: PHP/" . phpversion() . "\r\nContent-Type: text/html; charset=utf-8\r\n";
706 if ( isset( $item['email_reply_to'] ) && ! empty( $item['email_reply_to'] ) ) {
707 $headers .= 'Reply-To:' . $smart_tags->process_smart_tags( $item['email_reply_to'], $submission_data ) . "\r\n";
708 } else {
709 $headers .= "Reply-To: {$from}\r\n";
710 }
711 if ( isset( $item['email_cc'] ) && ! empty( $item['email_cc'] ) ) {
712 $headers .= 'Cc:' . $smart_tags->process_smart_tags( $item['email_cc'], $submission_data ) . "\r\n";
713 }
714 if ( isset( $item['email_bcc'] ) && ! empty( $item['email_bcc'] ) ) {
715 $headers .= 'Bcc:' . $smart_tags->process_smart_tags( $item['email_bcc'], $submission_data ) . "\r\n";
716 }
717
718 $sent = wp_mail( $to, $subject, $message, $headers );
719
720 if ( is_int( $log_key ) ) {
721 $entries_db_instance->update_log(
722 $log_key,
723 null,
724 [
725 /* translators: Here, %s is the comma separated emails list. */
726 $sent ? sprintf( __( 'Email notification sent to %s', 'sureforms' ), esc_html( $to ) ) : sprintf( __( 'Failed sending email notification to %s', 'sureforms' ), esc_html( $to ) ),
727 ]
728 );
729 }
730
731 $is_mail_sent = $sent;
732 $emails[] = $to;
733 }
734 }
735 }
736 }
737
738 return [
739 'success' => $is_mail_sent,
740 'emails' => $emails,
741 ];
742 }
743
744 /**
745 * Retrieve all entries data for a specific form ID to check for unique values.
746 *
747 * @since 0.0.1
748 * @return void
749 */
750 public function field_unique_validation() {
751 if ( isset( $_POST['nonce'] ) && ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'unique_validation_nonce' ) ) {
752 $error_message = __( 'Nonce verification failed.', 'sureforms' );
753 $error_data = [
754 'error' => $error_message,
755 ];
756 wp_send_json_error( $error_data );
757 }
758
759 global $wpdb;
760 $id = isset( $_POST['id'] ) ? absint( wp_unslash( $_POST['id'] ) ) : 0;
761 $meta_value = $id;
762
763 if ( ! $meta_value ) {
764 $error_message = __( 'Invalid form ID.', 'sureforms' );
765 $error_data = [
766 'error' => $error_message,
767 ];
768 wp_send_json_error( $error_data );
769 }
770
771 $_POST = array_map( 'wp_unslash', $_POST );
772
773 // Get the entry IDs for the particualr form to perform unique field validation.
774 $entry_ids = Entries::get_all_entry_ids_for_form( $id );
775
776 $all_form_entries = [];
777 $keys = array_keys( $_POST );
778 $length = count( $keys );
779
780 for ( $i = 3; $i < $length; $i++ ) {
781 $key = $keys[ $i ];
782 $value = isset( $_POST[ $key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) : '';
783 $key = str_replace( '_', ' ', $keys[ $i ] );
784
785 foreach ( $entry_ids as $entry_id ) {
786 $entry_id = is_array( $entry_id ) ? Helper::get_integer_value( $entry_id['ID'] ) : 0;
787 $form_data = Entries::get_form_data( $entry_id );
788 if ( is_array( $form_data ) && isset( $form_data[ $key ] ) && $form_data[ $key ] === $value ) {
789 $obj = [ $key => 'not unique' ];
790 array_push( $all_form_entries, $obj );
791 break;
792 }
793 }
794 }
795
796 $results = [
797 'data' => $all_form_entries,
798 ];
799
800 wp_send_json( $results );
801 }
802
803 /**
804 * Function to save allowed block data.
805 *
806 * @since 0.0.1
807 * @return void
808 */
809 public function srfm_global_update_allowed_block() {
810 if ( ! current_user_can( 'manage_options' ) ) {
811 wp_send_json_error();
812 }
813
814 if ( ! check_ajax_referer( 'srfm_ajax_nonce', 'security', false ) ) {
815 wp_send_json_error();
816 }
817
818 if ( ! empty( $_POST['defaultAllowedQuickSidebarBlocks'] ) ) {
819 $srfm_default_allowed_quick_sidebar_blocks = json_decode( sanitize_text_field( wp_unslash( $_POST['defaultAllowedQuickSidebarBlocks'] ) ), true );
820 Helper::update_admin_settings_option( 'srfm_quick_sidebar_allowed_blocks', $srfm_default_allowed_quick_sidebar_blocks );
821 wp_send_json_success();
822 }
823 wp_send_json_error();
824 }
825
826 /**
827 * Function to save enable/disable data.
828 *
829 * @since 0.0.1
830 * @return void
831 */
832 public function srfm_global_sidebar_enabled() {
833 if ( ! current_user_can( 'manage_options' ) ) {
834 wp_send_json_error();
835 }
836
837 if ( ! check_ajax_referer( 'srfm_ajax_nonce', 'security', false ) ) {
838 wp_send_json_error();
839 }
840
841 if ( ! empty( $_POST['enableQuickActionSidebar'] ) ) {
842 $srfm_enable_quick_action_sidebar = ( 'enabled' === $_POST['enableQuickActionSidebar'] ? 'enabled' : 'disabled' );
843 Helper::update_admin_settings_option( 'srfm_enable_quick_action_sidebar', $srfm_enable_quick_action_sidebar );
844 wp_send_json_success();
845 }
846 wp_send_json_error();
847 }
848 }
849