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

803 lines 26.6 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 ( 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.', 'sureforms' );
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.', 'sureforms' );
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.', 'sureforms' ), [ '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.', 'sureforms' ), [ '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.', 'sureforms' ), [ '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.', 'sureforms' ), [ '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', 'sureforms' ), [ '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 = 0; $i < $form_data_count; $i++ ) {
445 $key = strval( $form_data_keys[ $i ] );
446
447 /**
448 * This will allow to pass only sureforms fields
449 * checking -lbl- as thats mandatory for in key of sureforms fields.
450 */
451 if ( false === str_contains( $key, '-lbl-' ) ) {
452 continue;
453 }
454
455 $value = $form_data[ $key ];
456
457 $field_name = htmlspecialchars( str_replace( '_', ' ', $key ) );
458
459 // If the field is an array, encode the values. This is to add support for multi-upload field.
460 if ( is_array( $value ) ) {
461 $submission_data[ $field_name ] =
462 array_map(
463 static function ( $val ) {
464 return rawurlencode( $val );
465 },
466 $value
467 );
468 } else {
469 $submission_data[ $field_name ] = htmlspecialchars( $value );
470 }
471 }
472
473 $modified_message = $this->prepare_submission_data( $submission_data );
474
475 $form_before_submission_data = [
476 'form_id' => $id ? intval( $id ) : '',
477 'data' => $modified_message,
478 ];
479
480 /**
481 * Fires before submission process starts.
482 */
483 do_action( 'srfm_before_submission', $form_before_submission_data );
484
485 $name = sanitize_text_field( get_the_title( intval( $id ) ) );
486 $send_email = $this->send_email( $id, $submission_data, $form_data );
487 $emails = [];
488
489 if ( $send_email ) {
490 $emails = $send_email['emails'];
491 }
492
493 // Check if GDPR is enabled and do not store entries is enabled.
494 // If so, send email and do not store entries.
495 if ( $gdpr && $do_not_store_entries ) {
496
497 $form_submit_response = [
498 'success' => true,
499 'form_id' => $id ? intval( $id ) : '',
500 'to_emails' => $emails,
501 'form_name' => $name ? esc_attr( $name ) : '',
502 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
503 'data' => $modified_message,
504 ];
505
506 do_action( 'srfm_form_submit', $form_submit_response );
507
508 /**
509 * Hook for enabling background processes.
510 *
511 * @param array $form_data form data related to submission.
512 */
513 $form_data['form_id'] = $id ? intval( $id ) : '';
514 do_action( 'srfm_after_submission_process', $form_data );
515
516 return [
517 'success' => true,
518 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
519 'data' => [
520 'name' => $name,
521 'after_submit' => false,
522 ],
523 'redirect_url' => Generate_Form_Markup::get_redirect_url( $form_data, $submission_data ),
524 ];
525
526 }
527
528 $global_setting_options = get_option( 'srfm_general_settings_options' );
529
530 // If GDPR is enabled, do not store IP, browser, and device info.
531 // If not, store IP, browser, and device info.
532 $user_ip = '';
533 $browser_name = '';
534 $device_name = '';
535 if ( ! $gdpr ) {
536 $srfm_ip_log = is_array( $global_setting_options ) && isset( $global_setting_options['srfm_ip_log'] ) ? $global_setting_options['srfm_ip_log'] : '';
537
538 $user_ip = $srfm_ip_log && isset( $_SERVER['REMOTE_ADDR'] ) ? filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) : '';
539 $browser = new Browser();
540 $browser_name = sanitize_text_field( $browser->getBrowser() );
541 $device_name = sanitize_text_field( $browser->getPlatform() );
542 }
543
544 $form_markup = get_the_content( null, false, Helper::get_integer_value( $form_data['form-id'] ) );
545 $pattern = '/"label":"(.*?)"/';
546 preg_match_all( $pattern, $form_markup, $matches );
547 $submission_info = [
548 'user_ip' => $user_ip,
549 'browser_name' => $browser_name,
550 'device_name' => $device_name,
551 ];
552 $entries_data = [
553 'form_id' => $id,
554 'form_data' => $submission_data,
555 'submission_info' => $submission_info,
556 ];
557 if ( is_user_logged_in() ) {
558 // If user is logged in then save their user id.
559 $entries_data['user_id'] = get_current_user_id();
560 }
561 $entry_id = Entries::add( $entries_data );
562 if ( $entry_id ) {
563
564 $response = [
565 'success' => true,
566 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
567 'data' => [
568 'name' => $name,
569 'submission_id' => $entry_id,
570 'after_submit' => true,
571 ],
572 'redirect_url' => Generate_Form_Markup::get_redirect_url( $form_data, $submission_data ),
573 ];
574
575 $form_submit_response = apply_filters(
576 'srfm_form_submit_response',
577 [
578 'success' => true,
579 'form_id' => $id ? intval( $id ) : '',
580 'to_emails' => $emails,
581 'form_name' => $name ? esc_attr( $name ) : '',
582 'message' => Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ),
583 'data' => $modified_message,
584 ]
585 );
586
587 do_action( 'srfm_form_submit', $form_submit_response );
588 } else {
589 $response = [
590 'success' => false,
591 'message' => __( 'Error submitting form', 'sureforms' ),
592 ];
593 }
594
595 return $response;
596 }
597
598 /**
599 * Prepare submission data.
600 *
601 * @param array<mixed> $submission_data Submission data.
602 * @since 0.0.7
603 * @return array<mixed> Modified submission data.
604 */
605 public function prepare_submission_data( $submission_data ) {
606 $modified_message = [];
607 foreach ( $submission_data as $key => $value ) {
608 $parts = explode( '-lbl-', $key );
609 $label = '';
610
611 if ( ! empty( $parts[1] ) ) {
612 $tokens = explode( '-', $parts[1] );
613 if ( count( $tokens ) > 1 ) {
614 $label = implode( '-', array_slice( $tokens, 1 ) );
615 }
616
617 $fields = explode( '-', $parts[0] );
618
619 // Since the upload field returns an array of file URLs, we need to implode them with a comma.
620 if ( 'upload' === $fields[1] && ! empty( $value ) && is_array( $value ) ) {
621 $modified_message[ $label ] = urldecode( implode( ', ', $value ) );
622 } else {
623 $modified_message[ $label ] = html_entity_decode( esc_attr( Helper::get_string_value( $value ) ) );
624 }
625 }
626 }
627
628 return $modified_message;
629 }
630
631 /**
632 * Send Email.
633 *
634 * @param string $id Form ID.
635 * @param array<mixed> $submission_data Submission data.
636 * @param array<string> $form_data Request object or array containing form data.
637 * @since 0.0.1
638 * @return array<mixed> Array containing the response data.
639 */
640 public static function send_email( $id, $submission_data, $form_data = [] ) {
641 $email_notification = get_post_meta( intval( $id ), '_srfm_email_notification' );
642 $smart_tags = new Smart_Tags();
643 $is_mail_sent = false;
644 $emails = [];
645
646 if ( is_iterable( $email_notification ) ) {
647 $entries_db_instance = Entries::get_instance();
648 $log_key = $entries_db_instance->add_log( __( 'Email Notification Initiated', 'sureforms' ) );
649
650 foreach ( $email_notification as $notification ) {
651 foreach ( $notification as $item ) {
652 if ( true === $item['status'] ) {
653 $from = Helper::get_string_value( get_option( 'admin_email' ) );
654 $to = $smart_tags->process_smart_tags( $item['email_to'], $submission_data );
655 $subject = $smart_tags->process_smart_tags( $item['subject'], $submission_data, $form_data );
656 $email_body = $smart_tags->process_smart_tags( $item['email_body'], $submission_data, $form_data );
657 $email_template = new Email_Template();
658 $message = $email_template->render( $submission_data, $email_body );
659 $headers = "From: {$from}\r\nX-Mailer: PHP/" . phpversion() . "\r\nContent-Type: text/html; charset=utf-8\r\n";
660 if ( isset( $item['email_reply_to'] ) && ! empty( $item['email_reply_to'] ) ) {
661 $headers .= 'Reply-To:' . $smart_tags->process_smart_tags( $item['email_reply_to'], $submission_data ) . "\r\n";
662 } else {
663 $headers .= "Reply-To: {$from}\r\n";
664 }
665 if ( isset( $item['email_cc'] ) && ! empty( $item['email_cc'] ) ) {
666 $headers .= 'Cc:' . $smart_tags->process_smart_tags( $item['email_cc'], $submission_data ) . "\r\n";
667 }
668 if ( isset( $item['email_bcc'] ) && ! empty( $item['email_bcc'] ) ) {
669 $headers .= 'Bcc:' . $smart_tags->process_smart_tags( $item['email_bcc'], $submission_data ) . "\r\n";
670 }
671
672 $sent = wp_mail( $to, $subject, $message, $headers );
673
674 if ( is_int( $log_key ) ) {
675 $entries_db_instance->update_log(
676 $log_key,
677 null,
678 [
679 /* translators: Here, %s is the comma separated emails list. */
680 $sent ? sprintf( __( 'Email notification sent to %s', 'sureforms' ), esc_html( $to ) ) : sprintf( __( 'Failed sending email notification to %s', 'sureforms' ), esc_html( $to ) ),
681 ]
682 );
683 }
684
685 $is_mail_sent = $sent;
686 $emails[] = $to;
687 }
688 }
689 }
690 }
691
692 return [
693 'success' => $is_mail_sent,
694 'emails' => $emails,
695 ];
696 }
697
698 /**
699 * Retrieve all entries data for a specific form ID to check for unique values.
700 *
701 * @since 0.0.1
702 * @return void
703 */
704 public function field_unique_validation() {
705 if ( isset( $_POST['nonce'] ) && ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'unique_validation_nonce' ) ) {
706 $error_message = __( 'Nonce verification failed.', 'sureforms' );
707 $error_data = [
708 'error' => $error_message,
709 ];
710 wp_send_json_error( $error_data );
711 }
712
713 global $wpdb;
714 $id = isset( $_POST['id'] ) ? absint( wp_unslash( $_POST['id'] ) ) : 0;
715 $meta_value = $id;
716
717 if ( ! $meta_value ) {
718 $error_message = __( 'Invalid form ID.', 'sureforms' );
719 $error_data = [
720 'error' => $error_message,
721 ];
722 wp_send_json_error( $error_data );
723 }
724
725 $_POST = array_map( 'wp_unslash', $_POST );
726
727 // Get the entry IDs for the particualr form to perform unique field validation.
728 $entry_ids = Entries::get_all_entry_ids_for_form( $id );
729
730 $all_form_entries = [];
731 $keys = array_keys( $_POST );
732 $length = count( $keys );
733
734 for ( $i = 3; $i < $length; $i++ ) {
735 $key = $keys[ $i ];
736 $value = isset( $_POST[ $key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) : '';
737 $key = str_replace( '_', ' ', $keys[ $i ] );
738
739 foreach ( $entry_ids as $entry_id ) {
740 $entry_id = is_array( $entry_id ) ? Helper::get_integer_value( $entry_id['ID'] ) : 0;
741 $form_data = Entries::get_form_data( $entry_id );
742 if ( is_array( $form_data ) && isset( $form_data[ $key ] ) && $form_data[ $key ] === $value ) {
743 $obj = [ $key => 'not unique' ];
744 array_push( $all_form_entries, $obj );
745 break;
746 }
747 }
748 }
749
750 $results = [
751 'data' => $all_form_entries,
752 ];
753
754 wp_send_json( $results );
755 }
756
757 /**
758 * Function to save allowed block data.
759 *
760 * @since 0.0.1
761 * @return void
762 */
763 public function srfm_global_update_allowed_block() {
764 if ( ! current_user_can( 'manage_options' ) ) {
765 wp_send_json_error();
766 }
767
768 if ( ! check_ajax_referer( 'srfm_ajax_nonce', 'security', false ) ) {
769 wp_send_json_error();
770 }
771
772 if ( ! empty( $_POST['defaultAllowedQuickSidebarBlocks'] ) ) {
773 $srfm_default_allowed_quick_sidebar_blocks = json_decode( sanitize_text_field( wp_unslash( $_POST['defaultAllowedQuickSidebarBlocks'] ) ), true );
774 Helper::update_admin_settings_option( 'srfm_quick_sidebar_allowed_blocks', $srfm_default_allowed_quick_sidebar_blocks );
775 wp_send_json_success();
776 }
777 wp_send_json_error();
778 }
779
780 /**
781 * Function to save enable/disable data.
782 *
783 * @since 0.0.1
784 * @return void
785 */
786 public function srfm_global_sidebar_enabled() {
787 if ( ! current_user_can( 'manage_options' ) ) {
788 wp_send_json_error();
789 }
790
791 if ( ! check_ajax_referer( 'srfm_ajax_nonce', 'security', false ) ) {
792 wp_send_json_error();
793 }
794
795 if ( ! empty( $_POST['enableQuickActionSidebar'] ) ) {
796 $srfm_enable_quick_action_sidebar = ( 'enabled' === $_POST['enableQuickActionSidebar'] ? 'enabled' : 'disabled' );
797 Helper::update_admin_settings_option( 'srfm_enable_quick_action_sidebar', $srfm_enable_quick_action_sidebar );
798 wp_send_json_success();
799 }
800 wp_send_json_error();
801 }
802 }
803