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

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