PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.5.3
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.5.3
3.6.0 3.5.3 3.5.2 3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / includes / class-evf-form-task.php
everest-forms / includes Last commit date
Helpers 1 year ago Integrations 1 week ago RestApi 1 month ago abilities 1 month ago abstracts 1 month ago admin 1 week ago blocks 1 year ago elementor 2 years ago export 3 months ago fields 1 week ago interfaces 8 years ago libraries 2 years ago log-handlers 1 year ago shortcodes 1 month ago stats 6 months ago templates 4 months ago traits 1 month ago class-everest-forms.php 1 week ago class-evf-addon-upsell.php 1 month ago class-evf-ajax.php 1 week ago class-evf-autoloader.php 8 years ago class-evf-background-process-import-entries.php 2 years ago class-evf-background-updater.php 8 years ago class-evf-cache-helper.php 3 months ago class-evf-cron.php 2 years ago class-evf-deprecated-action-hooks.php 6 years ago class-evf-deprecated-filter-hooks.php 5 years ago class-evf-email-entries-report.php 4 months ago class-evf-emails.php 1 month ago class-evf-fields.php 1 month ago class-evf-form-handler.php 1 month ago class-evf-form-task.php 1 month ago class-evf-forms-features.php 1 month ago class-evf-frontend-scripts.php 1 month ago class-evf-install.php 3 months ago class-evf-integrations.php 4 months ago class-evf-log-levels.php 8 years ago class-evf-logger.php 5 years ago class-evf-post-types.php 1 year ago class-evf-privacy.php 6 years ago class-evf-report-cron.php 3 months ago class-evf-reporting.php 3 months ago class-evf-session-handler.php 7 years ago class-evf-shortcodes.php 1 year ago class-evf-smart-tags.php 10 months ago class-evf-template-loader.php 1 year ago class-evf-validation.php 6 years ago evf-conditional-functions.php 6 years ago evf-core-functions.php 1 month ago evf-deprecated-functions.php 6 years ago evf-entry-functions.php 5 months ago evf-formatting-functions.php 4 years ago evf-notice-functions.php 4 years ago evf-template-functions.php 4 years ago evf-template-hooks.php 8 years ago evf-update-functions.php 5 years ago
class-evf-form-task.php
2370 lines
1 <?php
2 /**
3 * Process form data
4 *
5 * @package EverestForms
6 * @since 1.0.0
7 */
8
9 defined( 'ABSPATH' ) || exit;
10
11 use Cleantalk\Antispam\CleantalkRequest;
12 use EverestForms\Helpers\FormHelper;
13
14 /**
15 * EVF_Form_Task class.
16 */
17 class EVF_Form_Task {
18
19 /**
20 * Holds errors.
21 *
22 * @since 1.0.0
23 * @var array
24 */
25 public $errors;
26
27 /**
28 * Holds formatted fields.
29 *
30 * @since 1.0.0
31 * @var array
32 */
33 public $form_fields;
34
35 /**
36 * Holds the ID of a successful entry.
37 *
38 * @since 1.0.0
39 * @var int
40 */
41 public $entry_id = 0;
42
43 /**
44 * Form data and settings.
45 *
46 * @since 1.5.0
47 *
48 * @var array
49 */
50 public $form_data = array();
51
52 /**
53 * Is hash validation?
54 *
55 * @var 1.7.4
56 */
57 public $is_valid_hash = false;
58
59 /**
60 * Ajax error array.
61 */
62 public $ajax_err = array();
63
64 /**
65 * Is notice print?
66 */
67 public $evf_notice_print = false;
68
69 /**
70 * Primary class constructor.
71 *
72 * @since 1.0.0
73 */
74 public function __construct() {
75 add_action( 'wp', array( $this, 'listen_task' ) );
76 add_filter( 'everest_forms_field_properties', array( $this, 'load_previous_field_value' ), 99, 3 );
77 add_action( 'everest_forms_complete_entry_save', array( $this, 'update_slot_booking_value' ), 10, 5 );
78 add_action( 'everest_forms_complete_entry_save', array( $this, 'evf_set_approval_status' ), 10, 2 );
79 add_action( 'admin_init', array( $this, 'evf_admin_approve_entry' ), 10, 2 );
80 add_action( 'admin_init', array( $this, 'evf_admin_deny_entry' ) );
81 add_action( 'admin_init', array( $this, 'evf_mark_entry_spam' ), 10 );
82 add_action( 'admin_init', array( $this, 'evf_remove_entry_from_spam' ), 10 );
83 /**
84 * Delete files.
85 *
86 * @since 3.3.0
87 */
88 add_action( 'before_delete_post', array( $this, 'delete_entry_files_before_form_delete' ), 10, 1 );
89 add_action( 'everest_forms_before_delete_entries', array( $this, 'delete_entry_files' ), 10, 1 );
90 }
91
92 /**
93 * Listen to see if this is a return callback or a posted form entry.
94 *
95 * @since 1.0.0
96 */
97 public function listen_task() {
98 if ( ! empty( $_GET['everest_forms_return'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
99 $this->entry_confirmation_redirect( '', sanitize_text_field( wp_unslash( $_GET['everest_forms_return'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
100 }
101
102 $form_id = ! empty( $_POST['everest_forms']['id'] ) ? absint( $_POST['everest_forms']['id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
103
104 if ( ! $form_id ) {
105 return;
106 }
107
108 if ( ! empty( $_POST['everest_forms']['id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
109 $this->do_task( evf_sanitize_entry( wp_unslash( $_POST['everest_forms'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
110 }
111
112 if ( ! evf_is_amp() ) {
113 return;
114 }
115
116 $settings = $this->form_data['settings'];
117 $success_message = isset( $settings['successful_form_submission_message'] ) ? $settings['successful_form_submission_message'] : __( 'Thanks for contacting us! We will be in touch with you shortly.', 'everest-forms' );
118 // Send 400 Bad Request when there are errors.
119 if ( empty( $this->errors[ $form_id ] ) ) {
120 wp_send_json(
121 array(
122 'message' => $success_message,
123 ),
124 200
125 );
126
127 return;
128 }
129 $message = $this->errors[ $form_id ]['header'];
130
131 if ( ! empty( $this->errors[ $form_id ]['footer'] ) ) {
132 $message .= ' ' . $this->errors[ $form_id ]['footer'];
133 }
134
135 wp_send_json(
136 array(
137 'message' => $message,
138 ),
139 400
140 );
141 }
142
143 /**
144 * Do task of form entry
145 *
146 * @since 1.0.0
147 * @param array $entry $_POST object.
148 */
149 public function do_task( $entry ) {
150 $logger = evf_get_logger();
151 try {
152 $this->errors = array();
153 $this->form_fields = array();
154 $form_id = absint( $entry['id'] );
155 $form = evf()->form->get( $form_id );
156 $honeypot = false;
157 $response_data = array();
158 $this->ajax_err = array();
159 $this->evf_notice_print = false;
160 $logger = evf_get_logger();
161
162 /**
163 * Filter to bypass the form nonce validation.
164 * By default it is false.
165 *
166 * @since 3.3.0
167 */
168 if ( ! apply_filters( 'evf_bypass_form_nonce_validation', false, $form_id ) ) {
169 // Check nonce for form submission.
170
171 if ( empty( $_POST[ '_wpnonce' . $form_id ] ) || ! wp_verify_nonce( wp_unslash( sanitize_key( $_POST[ '_wpnonce' . $form_id ] ) ), 'everest-forms_process_submit' ) ) { // phpcs:ignore WordPress.Security.NonceVerification
172 $this->errors[ $form_id ]['header'] = esc_html__( 'We were unable to process your form, please try again.', 'everest-forms' );
173 $logger->error(
174 $this->errors[ $form_id ]['header'],
175 array( 'source' => 'form-submission' )
176 );
177 return $this->errors;
178 }
179 }
180
181 // Validate form is real and active (published).
182 if ( ! $form || 'publish' !== $form->post_status ) {
183 $this->errors[ $form_id ]['header'] = esc_html__( 'Invalid form. Please check again.', 'everest-forms' );
184 $logger->error(
185 $this->errors[ $form_id ]['header'],
186 array( 'source' => 'form-submission' )
187 );
188 return $this->errors;
189 }
190
191 // Check if the form is enabled or not.
192 $form_enabled = evf_decode( $form->post_content );
193 if ( isset( $form_enabled['form_enabled'] ) && ! $form_enabled['form_enabled'] ) {
194 $this->errors[ $form_id ]['header'] = esc_html__( 'This form is disabled.', 'everest-forms' );
195 $logger->error(
196 $this->errors[ $form_id ]['header'],
197 array( 'source' => 'form-submission' )
198 );
199 return $this->errors;
200 }
201
202 // Formatted form data for hooks.
203 $this->form_data = apply_filters( 'everest_forms_process_before_form_data', evf_decode( $form->post_content ), $entry );
204
205 // Remove locked (Pro/addon) fields from processing. They are shown in the
206 // builder for upsell but never rendered on the published form, so they must
207 // not be validated, formatted, or stored as entries (a required locked field
208 // would otherwise block every submission).
209 if ( ! empty( $this->form_data['form_fields'] ) ) {
210 foreach ( $this->form_data['form_fields'] as $field_key => $field ) {
211 if ( isset( $field['type'] ) && evf_is_field_locked( $field['type'] ) ) {
212 unset( $this->form_data['form_fields'][ $field_key ] );
213 }
214 }
215 }
216
217 // Pre-process/validate hooks and filter. Data is not validated or cleaned yet so use with caution.
218 $entry = apply_filters( 'everest_forms_process_before_filter', $entry, $this->form_data );
219 $this->form_data['page_id'] = array_key_exists( 'post_id', $entry ) ? $entry['post_id'] : $form_id;
220
221 $logger->info(
222 __( 'Everest Forms Process Before.', 'everest-forms' ),
223 array( 'source' => 'form-submission' )
224 );
225 do_action( 'everest_forms_process_before', $entry, $this->form_data );
226 $logger->info(
227 __( 'Everest Forms Process Before Form ID.', 'everest-forms' ),
228 array( 'source' => 'form-submission' )
229 );
230 do_action( "everest_forms_process_before_{$form_id}", $entry, $this->form_data );
231
232 $ajax_form_submission = isset( $this->form_data['settings']['ajax_form_submission'] ) ? $this->form_data['settings']['ajax_form_submission'] : 0;
233 $stripe_via_selector = function_exists( 'evf_is_gateway_in_selector_allowlist' ) && evf_is_gateway_in_selector_allowlist( array( 'form_data' => $this->form_data, 'gateway' => 'stripe' ) );
234 $square_via_selector = function_exists( 'evf_is_gateway_in_selector_allowlist' ) && evf_is_gateway_in_selector_allowlist( array( 'form_data' => $this->form_data, 'gateway' => 'square' ) );
235 $paypal_via_selector = function_exists( 'evf_is_gateway_in_selector_allowlist' ) && evf_is_gateway_in_selector_allowlist( array( 'form_data' => $this->form_data, 'gateway' => 'paypal' ) );
236 if ( ( isset( $this->form_data['payments']['stripe']['enable_stripe'] ) && '1' === $this->form_data['payments']['stripe']['enable_stripe'] ) || $stripe_via_selector || ( isset( $this->form_data['payments']['square']['enable_square'] ) && '1' === $this->form_data['payments']['square']['enable_square'] ) || $square_via_selector || $paypal_via_selector ) {
237 $ajax_form_submission = '1';
238 }
239 if ( '1' === $ajax_form_submission ) {
240 // For the sake of validation we completely remove the validator option.
241 update_option( 'evf_validation_error', '' );
242
243 // Prepare fields for entry_save.
244 foreach ( $this->form_data['form_fields'] as $field ) {
245 if ( '' === isset( $this->form_data['form_fields']['meta-key'] ) ) {
246 continue;
247 }
248
249 $field_id = $field['id'];
250 $field_type = $field['type'];
251 $field_submit = isset( $entry['form_fields'][ $field_id ] ) ? $entry['form_fields'][ $field_id ] : '';
252
253 if ( 'signature' === $field_type ) {
254 $field_submit = isset( $field_submit['signature_image'] ) ? $field_submit['signature_image'] : '';
255 }
256
257 $exclude = array( 'title', 'html', 'captcha', 'image-upload', 'file-upload', 'divider', 'reset', 'recaptcha', 'hcaptcha', 'turnstile', 'private-note', 'payment_summary' );
258
259 if ( ! in_array( $field_type, $exclude, true ) ) {
260
261 $this->form_fields[ $field_id ] = array(
262 'id' => $field_id,
263 'name' => sanitize_text_field( $field['label'] ),
264 'meta_key' => $this->form_data['form_fields'][ $field_id ]['meta-key'],
265 'type' => $field_type,
266 'value' => evf_sanitize_textarea_field( $field_submit ),
267 );
268 }
269 }
270 }
271
272 $this->form_data['entry'] = $entry;
273
274 // Validate fields.
275 foreach ( $this->form_data['form_fields'] as $field ) {
276 $field_id = $field['id'];
277 $field_type = $field['type'];
278 $repeater_fields = array_key_exists( 'repeater-fields', $field ) ? $field['repeater-fields'] : 'no';
279
280 $field_submit = isset( $entry['form_fields'][ $field_id ] ) ? $entry['form_fields'][ $field_id ] : '';
281
282 if ( 'no' === $repeater_fields || 'repeater-fields' === $field_type ) {
283 $logger->info(
284 "Everest Forms Process Before validate {$field_type}.",
285 array( 'source' => 'form-submission' )
286 );
287 if ( 'payment-coupon' != $field_type ) {
288 do_action( "everest_forms_process_validate_{$field_type}", $field_id, $field_submit, $this->form_data, $field_type );
289 }
290 }
291
292 if ( 'credit-card' === $field_type && isset( $_POST['everest_form_stripe_payment_intent_id'] ) ) {
293 $this->evf_notice_print = true;
294 }
295
296 if ( 'yes' === get_option( 'evf_validation_error' ) && $ajax_form_submission ) {
297 if ( count( $this->errors ) ) {
298 foreach ( $this->errors as $_error ) {
299 $this->ajax_err [] = $_error;
300 }
301 }
302 update_option( 'evf_validation_error', '' );
303 }
304 }
305
306 if ( function_exists( 'evf_validate_submitted_payment_gateway' ) && function_exists( 'evf_get_total_payment' ) ) {
307 $payment_total = evf_sanitize_amount( evf_get_total_payment( $this->form_fields, $entry, $this->form_data ) );
308 if ( $payment_total > 0 ) {
309 $gateway_validation = evf_validate_submitted_payment_gateway( $this->form_data, $entry );
310 if ( is_wp_error( $gateway_validation ) ) {
311 $this->errors[ $form_id ]['header'] = $gateway_validation->get_error_message();
312 $logger->error(
313 $gateway_validation->get_error_message(),
314 array( 'source' => 'form-submission' )
315 );
316 if ( $ajax_form_submission ) {
317 $this->ajax_err[] = $this->errors[ $form_id ];
318 update_option( 'evf_validation_error', 'yes' );
319 }
320 }
321 }
322 }
323
324 // If validation issues occur, send the results accordingly.
325 if ( $ajax_form_submission && count( $this->ajax_err ) ) {
326 $response_data['error'] = $this->ajax_err;
327 $response_data['message'] = apply_filters( 'everest_forms_process_form_error_header', __( 'Form has not been submitted, please see the errors below.', 'everest-forms' ) );
328 $response_data['response'] = 'error';
329 $logger->error(
330 __( 'Form has not been submitted.', 'everest-forms' ),
331 array( 'source' => 'form-submission' )
332 );
333 return $response_data;
334 }
335
336 // reCAPTCHA check.
337 if ( ! apply_filters( 'everest_forms_recaptcha_disabled', false ) ) {
338 $recaptcha_type = get_option( 'everest_forms_recaptcha_type', 'v2' );
339 $invisible_recaptcha = get_option( 'everest_forms_recaptcha_v2_invisible', 'no' );
340
341 if ( 'v2' === $recaptcha_type && 'no' === $invisible_recaptcha ) {
342 $site_key = get_option( 'everest_forms_recaptcha_v2_site_key' );
343 $secret_key = get_option( 'everest_forms_recaptcha_v2_secret_key' );
344 } elseif ( 'v2' === $recaptcha_type && 'yes' === $invisible_recaptcha ) {
345 $site_key = get_option( 'everest_forms_recaptcha_v2_invisible_site_key' );
346 $secret_key = get_option( 'everest_forms_recaptcha_v2_invisible_secret_key' );
347 } elseif ( 'v3' === $recaptcha_type ) {
348 $site_key = get_option( 'everest_forms_recaptcha_v3_site_key' );
349 $secret_key = get_option( 'everest_forms_recaptcha_v3_secret_key' );
350 } elseif ( 'hcaptcha' === $recaptcha_type ) {
351 $site_key = get_option( 'everest_forms_recaptcha_hcaptcha_site_key' );
352 $secret_key = get_option( 'everest_forms_recaptcha_hcaptcha_secret_key' );
353 } elseif ( 'turnstile' === $recaptcha_type ) {
354 $site_key = get_option( 'everest_forms_recaptcha_turnstile_site_key' );
355 $secret_key = get_option( 'everest_forms_recaptcha_turnstile_secret_key' );
356 $theme_mode = get_option( 'everest_forms_recaptcha_turnstile_theme' );
357 }
358 $recaptcha_verified = false;
359 $error = '';
360 foreach ( (array) $this->form_data['form_fields'] as $field ) {
361 $field_type = isset( $field['type'] ) ? $field['type'] : '';
362 $captcha = array( 'recaptcha', 'hcaptcha', 'turnstile' );
363
364 if (
365 ( ! empty( $site_key ) && ! empty( $secret_key ) &&
366 isset( $this->form_data['settings']['recaptcha_support'] ) &&
367 '1' === $this->form_data['settings']['recaptcha_support'] &&
368 ! isset( $_POST['__amp_form_verify'] ) &&
369 ( 'v3' === $recaptcha_type || ! evf_is_amp() )
370 )
371 ||
372 ( ! empty( $site_key ) && ! empty( $secret_key ) && in_array( $field_type, $captcha, true ) )
373 ) {
374 // Get the token based on CAPTCHA type
375 $token = ! empty( $_POST['g-recaptcha-response'] ) ? evf_clean( wp_unslash( $_POST['g-recaptcha-response'] ) ) : false;
376
377 if ( 'v3' === $recaptcha_type ) {
378 $token = ! empty( $_POST['everest_forms']['recaptcha'] ) ? evf_clean( wp_unslash( $_POST['everest_forms']['recaptcha'] ) ) : false;
379 } elseif ( 'hcaptcha' === $recaptcha_type ) {
380 $token = ! empty( $_POST['h-captcha-response'] ) ? evf_clean( wp_unslash( $_POST['h-captcha-response'] ) ) : false;
381 } elseif ( 'turnstile' === $recaptcha_type ) {
382 $token = ! empty( $_POST['cf-turnstile-response'] ) ? evf_clean( wp_unslash( $_POST['cf-turnstile-response'] ) ) : false;
383 }
384
385 if ( ! $token ) {
386 $error = esc_html__( 'CAPTCHA token missing. Please try again.', 'everest-forms' );
387 $this->errors[ $form_id ]['header'] = $error;
388 $logger->error( $error, array( 'source' => 'CAPTCHA' ) );
389 return $this->errors;
390 }
391
392 // Validate the token
393 if ( 'hcaptcha' === $recaptcha_type ) {
394 $raw_response = wp_safe_remote_get( 'https://hcaptcha.com/siteverify?secret=' . $secret_key . '&response=' . $token );
395 } elseif ( 'turnstile' === $recaptcha_type ) {
396 $url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
397 $params = array(
398 'method' => 'POST',
399 'body' => array(
400 'secret' => $secret_key,
401 'response' => $token,
402 ),
403 );
404 $raw_response = wp_safe_remote_post( $url, $params );
405 } else {
406 $raw_response = wp_safe_remote_get( 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secret_key . '&response=' . $token );
407 }
408
409 if ( ! is_wp_error( $raw_response ) ) {
410 $response = json_decode( wp_remote_retrieve_body( $raw_response ) );
411
412 $recaptcha_passed = ! empty( $response->success );
413
414 if ( $recaptcha_passed && 'v3' === $recaptcha_type ) {
415 $threshold = get_option( 'everest_forms_recaptcha_v3_threshold_score', apply_filters( 'everest_forms_recaptcha_v3_threshold', '0.5' ) );
416 if ( ! isset( $response->score ) || $response->score < floatval( $threshold ) ) {
417 $recaptcha_passed = false;
418 if ( isset( $response->score ) ) {
419 $error .= ' (' . esc_html( $response->score ) . ')';
420 }
421 }
422 }
423
424 if ( ! $recaptcha_passed ) {
425 if ( 'hcaptcha' === $recaptcha_type ) {
426 $error = esc_html__( 'hCaptcha verification failed, please try again later.', 'everest-forms' );
427 } elseif ( 'turnstile' === $recaptcha_type ) {
428 $error = esc_html__( 'Cloudflare Turnstile verification failed, please try again later.', 'everest-forms' );
429 } else {
430 $error = esc_html__( 'Google reCAPTCHA verification failed, please try again later.', 'everest-forms' );
431 }
432
433 $this->errors[ $form_id ]['header'] = $error;
434 $logger->error( $error, array( 'source' => 'CAPTCHA' ) );
435 return $this->errors;
436 }
437 }
438
439 $recaptcha_verified = true;
440 break;
441 }
442 }
443 }
444
445 // Initial error check.
446 $errors = apply_filters( 'everest_forms_process_initial_errors', $this->errors, $this->form_data );
447
448 // Minimum time to submit check.
449 $min_submit_time = $this->form_submission_waiting_time( $this->errors, $this->form_data );
450 if ( isset( $min_submit_time[ $form_id ]['header'] ) && ! empty( $min_submit_time ) ) {
451 $this->errors[ $form_id ]['header'] = $min_submit_time[ $form_id ]['header'];
452 $logger->error(
453 $min_submit_time[ $form_id ]['header'],
454 array( 'source' => 'Minimum time to submit' )
455 );
456 return $this->errors;
457 }
458
459 if ( isset( $_POST['__amp_form_verify'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
460 if ( empty( $errors[ $form_id ] ) ) {
461 wp_send_json( array(), 200 );
462 } else {
463 $verify_errors = array();
464
465 foreach ( $errors[ $form_id ] as $field_id => $error_fields ) {
466 $field = $this->form_data['fields'][ $field_id ];
467 $field_properties = EVF_Shortcode_Form::get_field_properties( $field, $this->form_data );
468
469 if ( is_string( $error_fields ) ) {
470
471 if ( 'checkbox' === $field['type'] || 'radio' === $field['type'] || 'select' === $field['type'] ) {
472 $first = current( $field_properties['inputs'] );
473 $name = $first['attr']['name'];
474 } elseif ( isset( $field_properties['inputs']['primary']['attr']['name'] ) ) {
475 $name = $field_properties['inputs']['primary']['attr']['name'];
476 }
477
478 $verify_errors[] = array(
479 'name' => $name,
480 'message' => $error_fields,
481 );
482 } else {
483 foreach ( $error_fields as $error_field => $error_message ) {
484
485 if ( isset( $field_properties['inputs'][ $error_field ]['attr']['name'] ) ) {
486 $name = $field_properties['inputs'][ $error_field ]['attr']['name'];
487 }
488
489 $verify_errors[] = array(
490 'name' => $name,
491 'message' => $error_message,
492 );
493 }
494 }
495 }
496
497 wp_send_json(
498 array(
499 'verifyErrors' => $verify_errors,
500 ),
501 400
502 );
503 }
504 return;
505 }
506 if ( ! empty( $errors[ $form_id ] ) ) {
507 if ( empty( $errors[ $form_id ]['header'] ) ) {
508 $errors[ $form_id ]['header'] = apply_filters( 'everest_forms_process_form_error_header', __( 'Form has not been submitted, please see the errors below.', 'everest-forms' ) );
509 $logger->error(
510 $errors[ $form_id ]['header'],
511 array( 'source' => 'form-submission' )
512 );
513 }
514 $this->errors = $errors;
515 return $this->errors;
516 }
517
518 // Early honeypot validation - before actual processing.
519 if ( isset( $this->form_data['settings']['honeypot'] ) && '1' === $this->form_data['settings']['honeypot'] && ! empty( $entry['hp'] ) ) {
520 $honeypot = esc_html__( 'Everest Forms honeypot field triggered.', 'everest-forms' );
521 }
522
523 $honeypot = apply_filters( 'everest_forms_process_honeypot', $honeypot, $this->form_fields, $entry, $this->form_data );
524
525 // If spam - return early.
526 if ( $honeypot ) {
527 $logger = evf_get_logger();
528 $logger->notice( sprintf( 'Spam entry for Form ID %d Response: %s', absint( $this->form_data['id'] ), evf_print_r( $entry, true ) ), array( 'source' => 'honeypot' ) );
529 return $this->errors;
530 }
531
532 /** Akismet anit-spam protection.
533 * If spam - return early
534 *
535 * @since 2.4.0
536 */
537 if ( $this->get_akismet_validate( $entry, $form_id ) ) {
538 $logger = evf_get_logger();
539 $logger->notice( sprintf( 'Spam entry for Form ID %d Response: %s', absint( $this->form_data['id'] ), evf_print_r( $entry, true ) ), array( 'source' => 'akismet' ) );
540
541 if ( isset( $this->form_data['settings']['akismet_protection_type'] ) && 'validation_failed' === $this->form_data['settings']['akismet_protection_type'] ) {
542
543 $akismet_message = apply_filters( 'evf_akisment_validatation_error_message', sprintf( 'Akismet anti-spam verification failed, please try again later.', 'everest-forms' ) );
544 $errors[ $form_id ]['header'] = $akismet_message;
545 $this->errors = $errors;
546
547 return $this->errors;
548 }
549 $entry['evf_spam_status'] = 'spam';
550 }
551
552 /** CleanTalk anit-spam protection.
553 * If spam - return early.
554 *
555 * @since 3.2.0
556 */
557 if ( $this->get_clean_talk_validate( $entry, $form_id ) ) {
558 $logger = evf_get_logger();
559 $logger->notice( sprintf( 'Spam entry for Form ID %d Response: %s', absint( $this->form_data['id'] ), evf_print_r( $entry, true ) ), array( 'source' => 'cleantalk' ) );
560 if ( isset( $this->form_data['settings']['cleantalk_protection_type'] ) && 'validation_failed' === $this->form_data['settings']['cleantalk_protection_type'] ) {
561
562 $cleantalk_message = apply_filters( 'evf_cleantalk_validatation_error_message', sprintf( 'CleanTalk anti-spam verification failed, please try again later.', 'everest-forms' ) );
563 $errors[ $form_id ]['header'] = $cleantalk_message;
564 $this->errors = $errors;
565
566 return $this->errors;
567 }
568 $entry['evf_spam_status'] = 'spam';
569 }
570 // Pass the form created date into the form data.
571 $this->form_data['created'] = $form->post_date;
572
573 // Format and Sanitize inputs.
574 foreach ( (array) $this->form_data['form_fields'] as $field ) {
575 $field_id = $field['id'];
576 $field_key = isset( $field['meta-key'] ) ? $field['meta-key'] : '';
577 $field_type = $field['type'];
578 $field_submit = isset( $entry['form_fields'][ $field_id ] ) ? $entry['form_fields'][ $field_id ] : array();
579
580 // Handle file uploads for save continue.
581 if ( in_array( $field_type, array( 'file-upload', 'image-upload' ), true ) ) {
582 if ( is_array( $field_submit ) ) {
583 unset( $field_submit['old_files'], $field_submit['new_files'] );
584 }
585
586 if ( defined( 'EVF_SAVE_AND_CONTINUE_VERSION' ) ) {
587 if ( ! is_array( $field_submit ) ) {
588 $field_submit = array();
589 }
590
591 $field_submit['new_files'] = isset( $_POST[ 'everest_forms_' . $form_id . '_' . $field_id ] )
592 ? stripslashes_deep( $_POST[ 'everest_forms_' . $form_id . '_' . $field_id ] )
593 : array();
594 $field_submit['old_files'] = isset( $_POST[ 'everest_forms_' . $form_id . '_old_' . $field_id ] )
595 ? stripslashes_deep( $_POST[ 'everest_forms_' . $form_id . '_old_' . $field_id ] )
596 : array();
597
598 $deleted_files = isset( $_POST[ 'everest_forms_' . $form_id . '_delete_' . $field_id ] )
599 ? stripslashes_deep( $_POST[ 'everest_forms_' . $form_id . '_delete_' . $field_id ] )
600 : '';
601
602 if ( ! empty( $deleted_files ) ) {
603 $deleted_files = json_decode( $deleted_files, true );
604
605 if ( is_array( $deleted_files ) ) {
606 $upload_dir = wp_get_upload_dir();
607 $uploads_baseurl = trailingslashit( $upload_dir['baseurl'] );
608 $uploads_basedir = wp_normalize_path( trailingslashit( $upload_dir['basedir'] ) );
609
610 foreach ( $deleted_files as $file ) {
611 $file = json_decode( $file, true );
612
613 if ( empty( $file['value'] ) || ! is_string( $file['value'] ) ) {
614 continue;
615 }
616
617 $file_url = esc_url_raw( $file['value'] );
618
619 if ( 0 !== strpos( $file_url, $uploads_baseurl ) ) {
620 continue;
621 }
622
623 $path = wp_parse_url( $file_url, PHP_URL_PATH );
624 $base_path = wp_parse_url( $uploads_baseurl, PHP_URL_PATH );
625
626 if ( ! is_string( $path ) || ! is_string( $base_path ) || 0 !== strpos( $path, $base_path ) ) {
627 continue;
628 }
629
630 $relative_path = ltrim( substr( $path, strlen( $base_path ) ), '/' );
631 $candidate = wp_normalize_path( $uploads_basedir . $relative_path );
632 $resolved_path = realpath( $candidate );
633
634 if ( false === $resolved_path ) {
635 continue;
636 }
637
638 $resolved_path = wp_normalize_path( $resolved_path );
639
640 if ( 0 !== strpos( $resolved_path, $uploads_basedir ) ) {
641 continue;
642 }
643
644 FormHelper::remove_file( $file_url );
645 }
646 }
647 }
648 }
649 }
650
651 $repeater_fields = array_key_exists( 'repeater-fields', $field ) ? $field['repeater-fields'] : 'no';
652
653 if ( 'no' === $repeater_fields || 'repeater-fields' === $field_type ) {
654 $logger->info(
655 sprintf( 'Everest Forms Process Format %s.', $field_type ),
656 array( 'source' => 'form-submission' )
657 );
658 do_action( "everest_forms_process_format_{$field_type}", $field_id, $field_submit, $this->form_data, $field_key );
659 }
660 }
661
662 // This hook is for internal purposes and should not be leveraged.
663 $logger->info(
664 'Everest Forms Process Format After.',
665 array( 'source' => 'form-submission' )
666 );
667 do_action( 'everest_forms_process_format_after', $this->form_data );
668
669 // Process hooks/filter - this is where most addons should hook
670 // because at this point we have completed all field validation and
671 // formatted the data.
672 $this->form_fields = apply_filters( 'everest_forms_process_filter', $this->form_fields, $entry, $this->form_data );
673
674 $all_data = array(
675 'form_fields' => $this->form_fields,
676 'entry' => $entry,
677 'form_data' => $this->form_data,
678 );
679
680 if ( ! empty( $_POST[ 'applied_coupons_data' ] ) ) {
681 $applied_coupons_data = json_decode( wp_unslash( $_POST[ 'applied_coupons_data' ] ), true );
682 $all_data['applied_coupons_data'] = $applied_coupons_data;
683 }
684
685 foreach ( $this->form_data['form_fields'] as $field ) {
686 $field_id = $field['id'];
687 $field_type = $field['type'];
688
689 $field_submit = isset( $entry['form_fields'][ $field_id ] ) ? $entry['form_fields'][ $field_id ] : '';
690
691 if ( 'payment-coupon' === $field_type ) {
692 $logger->info(
693 "Everest Forms Process coupon validating {$field_type}.",
694 array( 'source' => 'form-submission' )
695 );
696 do_action( "everest_forms_process_validate_{$field_type}", $field_id, $field_submit, $all_data);
697 }
698
699 if ( 'yes' === get_option( 'evf_validation_error' ) && $ajax_form_submission ) {
700 if ( count( $this->errors ) ) {
701 foreach ( $this->errors as $_error ) {
702 $this->ajax_err [] = $_error;
703 }
704 }
705 update_option( 'evf_validation_error', '' );
706 }
707 }
708 $logger->notice( sprintf( 'Everest Form Process: %s', evf_print_r( $this->form_fields, true ) ) );
709
710 $logger->info(
711 'Everest Forms Process.',
712 array( 'source' => 'form-submission' )
713 );
714 do_action( 'everest_forms_process', $this->form_fields, $entry, $this->form_data );
715 $logger->info(
716 "Everest Forms Process {$form_id}.",
717 array( 'source' => 'form-submission' )
718 );
719 do_action( "everest_forms_process_{$form_id}", $this->form_fields, $entry, $this->form_data );
720
721 $this->form_fields = apply_filters( 'everest_forms_process_after_filter', $this->form_fields, $entry, $this->form_data );
722 $logger->notice( sprintf( 'Everest Form Process After: %s', evf_print_r( $this->form_fields, true ) ) );
723
724 /**
725 * Apply smart tags to form fields values.
726 *
727 * @since 3.2.3
728 */
729 foreach ( $this->form_fields as $key => $value ) {
730 if ( ! empty( $value['value'] ) && is_string( $value['value'] ) && strpos( $value['value'], '{' ) !== false ) {
731 $this->form_fields[ $key ]['value'] = apply_filters( 'everest_forms_process_smart_tags', $value['value'], $this->form_data, $this->form_fields );
732 }
733 }
734
735 // One last error check - don't proceed if there are any errors.
736 if ( ! empty( $this->errors[ $form_id ] ) ) {
737 if ( empty( $this->errors[ $form_id ]['header'] ) ) {
738 $this->errors[ $form_id ]['header'] = apply_filters( 'everest_forms_process_form_error_header', esc_html__( 'Form has not been submitted, please see the errors below.', 'everest-forms' ) );
739 }
740 $logger->error(
741 __( 'Form has not been submitted', 'everest-forms' ),
742 array( 'source' => 'form-submission' )
743 );
744 return $this->errors;
745 }
746
747 $logger->notice( sprintf( 'Entry is Saving to DataBase' ) );
748 // Success - add entry to database.
749 $logger->info(
750 __( 'Entry Added to Database.', 'everest-forms' ),
751 array( 'source' => 'form-submission' )
752 );
753
754 $applied_coupons_data = ! empty( $_POST['applied_coupons_data'] ) ? $_POST['applied_coupons_data'] : '';
755 $this->form_data['applied_coupons_data'] = $applied_coupons_data;
756
757 if ( ! empty( $applied_coupons_data ) ) {
758 $decoded_coupons = $applied_coupons_data;
759 if ( is_string( $decoded_coupons ) ) {
760 $decoded = json_decode( wp_unslash( $decoded_coupons ), true );
761 if ( is_array( $decoded ) ) {
762 $decoded_coupons = $decoded;
763 }
764 }
765
766 if ( is_array( $decoded_coupons ) ) {
767 foreach ( $decoded_coupons as $coupon ) {
768 $field_id = isset( $coupon['field_id'] ) ? $coupon['field_id'] : '';
769 if ( ! empty( $field_id ) && isset( $this->form_fields[ $field_id ] ) ) {
770 if ( ! is_array( $this->form_fields[ $field_id ]['value'] ) ) {
771 $this->form_fields[ $field_id ]['value'] = array();
772 }
773 $this->form_fields[ $field_id ]['value'][] = $coupon;
774 }
775 }
776 }
777 }
778 $entry_id = $this->entry_save( $this->form_fields, $entry, $this->form_data['id'], $this->form_data );
779
780 do_action( 'everest_forms_process_user_registration', $this->form_fields, $entry, $this->form_data, $entry_id );
781
782 $logger->notice( sprintf( 'Entry is Saved to DataBase' ) );
783
784 $logger->notice( sprintf( 'Sending Email' ) );
785 // Success - send email notification.
786 $logger->info(
787 __( 'Sent Email Notification.', 'everest-forms' ),
788 array( 'source' => 'form-submission' )
789 );
790 $this->entry_email( $this->form_fields, $entry, $this->form_data, $entry_id, 'entry' );
791 $logger->notice( sprintf( 'Successfully Send the email' ) );
792
793 // @todo remove this way of printing notices.
794 add_filter( 'everest_forms_success', array( $this, 'check_success_message' ), 10, 2 );
795
796 // Pass completed and formatted fields in POST.
797 $_POST['everest-forms']['complete'] = $this->form_fields;
798
799 // Pass entry ID in POST.
800 $_POST['everest-forms']['entry_id'] = $entry_id;
801
802 // Post-process hooks.
803 $logger->info(
804 __( 'Everest Forms Process Completed.', 'everest-forms' ),
805 array( 'source' => 'form-submission' )
806 );
807
808 if ( ! empty( $_POST[ 'applied_coupons_data' ] ) ) {
809 $applied_coupons_data = json_decode( wp_unslash( $_POST[ 'applied_coupons_data' ] ), true );
810
811 $this->form_data['applied_coupons_data'] = $applied_coupons_data;
812 }
813
814 do_action( 'everest_forms_process_complete', $this->form_fields, $entry, $this->form_data, $entry_id );
815 $logger->info(
816 "Everest Forms Process Completed {$form_id}.",
817 array( 'source' => 'form-submission' )
818 );
819 do_action( "everest_forms_process_complete_{$form_id}", $this->form_fields, $entry, $this->form_data, $entry_id );
820 do_action( 'everest_forms_process_complete_send_data_to_zapier_app', $this->form_fields, $entry, $this->form_data, $entry_id );
821
822 // Payment gateways update entry meta during process_complete; do not show success when payment failed.
823 if ( ! empty( $entry_id ) ) {
824 $payment_fail = $this->get_failed_payment_submission_result( absint( $entry_id ) );
825 if ( is_array( $payment_fail ) ) {
826 if ( '1' === $ajax_form_submission ) {
827 return $payment_fail;
828 }
829
830 if ( function_exists( 'evf_notice_count' ) && 0 === evf_notice_count( 'error' ) ) {
831 evf_add_notice( $payment_fail['message'], 'error' );
832 }
833
834 delete_option( 'everest_forms_overall_feedback_is_called' );
835 return $response_data;
836 }
837 }
838 } catch ( Exception $e ) {
839 $raw_message = $e->getMessage();
840 $decoded_error = json_decode( $raw_message, true );
841
842 // Detect Google OAuth / API errors (UNAUTHENTICATED 401).
843 $is_google_auth_error = (
844 JSON_ERROR_NONE === json_last_error() &&
845 isset( $decoded_error['error']['status'] ) &&
846 'UNAUTHENTICATED' === $decoded_error['error']['status']
847 ) || false !== strpos( $raw_message, 'UNAUTHENTICATED' );
848
849 if ( $is_google_auth_error ) {
850 $display_message = class_exists( '\EverestForms\AuthorizeNet\Helpers' )
851 ? \EverestForms\AuthorizeNet\Helpers::pgw_selector_subscription_mapping_error_message()
852 : esc_html__( 'Something error occur', 'everest-forms' );
853 } elseif ( JSON_ERROR_NONE === json_last_error() && ! empty( $decoded_error['error']['message'] ) ) {
854 $display_message = $decoded_error['error']['message'];
855 } else {
856 $display_message = $raw_message;
857 }
858
859 evf_add_notice( $display_message, 'error' );
860 $logger->error(
861 $raw_message,
862 array( 'source' => 'form-submission' )
863 );
864 if ( '1' === $ajax_form_submission ) {
865 $response_data['response'] = 'error';
866 $response_data['message'] = wp_strip_all_tags( $display_message );
867 $response_data['error'] = array();
868 $response_data['form_id'] = $form_id;
869 return $response_data;
870 }
871 // Non-AJAX: return early so the success message is not shown.
872 return $response_data;
873 }
874 // For form confirmation backward compatilibity.
875 $this->form_data = evf_form_confirmation_backward_compatibility( $this->form_data );
876 $settings = $this->form_data['settings'];
877 $message = isset( $settings['successful_form_submission_message'] ) ? $settings['successful_form_submission_message'] : __( 'Thanks for contacting us! We will be in touch with you shortly.', 'everest-forms' );
878 $form_state_type = isset( $settings['form_state_type'] ) ? $settings['form_state_type'] : 'hide';
879
880 if ( 'hide' === $form_state_type ) {
881
882 $message_display_location = isset( $settings['message_display_location_of_hide'] ) ? $settings['message_display_location_of_hide'] : 'hide';
883 } else {
884 $message_display_location = isset( $settings['message_display_location_of_reset'] ) ? $settings['message_display_location_of_reset'] : 'top';
885 }
886
887 // $message_display_location = isset( $settings['successful_form_submission_message_display_location'] ) ? $settings['successful_form_submission_message_display_location'] : 'hide';
888 $is_pdf_submission_enabled = isset( $settings['pdf_submission']['enable_pdf_submission'] ) && ( 'yes' === $settings['pdf_submission']['enable_pdf_submission'] || '1' === $settings['pdf_submission']['enable_pdf_submission'] );
889 $pdf_submission = $is_pdf_submission_enabled ? $settings['pdf_submission'] : '';
890
891 $is_pdf_download_after_submit = isset( $pdf_submission['everest_forms_pdf_download_after_submit'] ) && ( 'yes' === $pdf_submission['everest_forms_pdf_download_after_submit'] || '1' === $pdf_submission['everest_forms_pdf_download_after_submit'] );
892 $is_global_pdf_download_enabled = 'yes' === get_option( 'everest_forms_pdf_download_after_submit', 'no' ) || '1' === get_option( 'everest_forms_pdf_download_after_submit', 'no' );
893 $should_allow_pdf_download = $is_pdf_submission_enabled ? $is_pdf_download_after_submit : $is_global_pdf_download_enabled;
894
895 // Check Conditional Logic and get the redirection URL.
896 $submission_redirection_process = apply_filters( 'everest_forms_submission_redirection_process', array(), $this->form_fields, $this->form_data );
897
898 $is_preview_confirmation = isset( $this->form_data['settings']['preview_confirmation'] ) ? $this->form_data['settings']['preview_confirmation'] : 0;
899
900 if ( ! empty( $submission_redirection_process ) && 'same' == $submission_redirection_process['redirect_to'] ) {
901 $is_preview_confirmation = $submission_redirection_process['settings']['preview_confirmation'];
902 }
903 $form_state_type = isset( $this->form_data['settings']['form_state_type'] ) ? $this->form_data['settings']['form_state_type'] : 'hide';
904 // show preview of form after submission.
905 if ( '1' === $is_preview_confirmation && 'hide' === $form_state_type ) {
906 $preview_style = isset( $this->form_data['settings']['preview_confirmation_select'] ) ? $this->form_data['settings']['preview_confirmation_select'] : 'basic';
907
908 if ( ! empty( $submission_redirection_process ) && 'same' == $submission_redirection_process['redirect_to'] ) {
909 $preview_style = $submission_redirection_process['settings']['preview_confirmation_select'];
910 }
911 if ( '1' === $ajax_form_submission ) {
912 $preview_form_data = $this->form_data;
913 $preview_form_data['settings']['ajax_form_submission'] = '1';
914
915 $response_data['is_preview_confirmation'] = $is_preview_confirmation;
916 $response_data['preview_confirmation'] = apply_filters( 'everest_forms_preview_confirmation', $preview_form_data, $this->form_fields, $preview_style );
917 } else {
918 do_action( 'everest_forms_preview_confirmation', $this->form_data, $this->form_fields, $preview_style );
919 }
920 }
921
922 if ( defined( 'EVF_PDF_SUBMISSION_VERSION' ) && $should_allow_pdf_download ) {
923 global $__everest_form_id;
924 global $__everest_form_entry_id;
925 $__everest_form_id = $form_id;
926 $__everest_form_entry_id = $entry_id;
927 }
928
929 // Backward compatibility for evf form templates.
930 $this->form_data['settings']['redirect_to'] = '0' === $this->form_data['settings']['redirect_to'] ? 'same' : $this->form_data['settings']['redirect_to'];
931
932 if ( '1' === $ajax_form_submission ) {
933 $response_data['message'] = $message;
934 $response_data['message_display_location'] = $message_display_location;
935 $response_data['form_state_type'] = $form_state_type;
936 $response_data['response'] = 'success';
937 $response_data['form_id'] = $form_id;
938 $response_data['entry_id'] = $entry_id;
939 $response_data['submission_message_scroll'] = isset( $settings['submission_message_scroll'] ) ? $settings['submission_message_scroll'] : false;
940 if ( defined( 'EVF_PDF_SUBMISSION_VERSION' ) && ( 'yes' === get_option( 'everest_forms_pdf_download_after_submit', 'no' ) || ( isset( $pdf_submission['everest_forms_pdf_download_after_submit'] ) && 'yes' === $pdf_submission['everest_forms_pdf_download_after_submit'] ) ) ) {
941 $response_data['pdf_download'] = true;
942 $pdf_download_message = get_option( 'everest_forms_pdf_custom_download_text', '' );
943
944 if ( isset( $pdf_submission['everest_forms_pdf_custom_download_text'] ) ) {
945 $pdf_download_message = $pdf_submission['everest_forms_pdf_custom_download_text'];
946 }
947
948 if ( empty( $pdf_download_message ) ) {
949 $pdf_download_message = __( 'Download your form submission in PDF format', 'everest-forms' );
950 }
951 $response_data['pdf_download_message'] = $pdf_download_message;
952 }
953
954 // Backward Compatibility Check.
955 switch ( $settings['redirect_to'] ) {
956 case '0':
957 $settings['redirect_to'] = 'same';
958 break;
959
960 case '1':
961 $settings['redirect_to'] = 'custom_page';
962 break;
963
964 case '2':
965 $settings['redirect_to'] = 'external_url';
966 break;
967 }
968
969 // Check for Submission Redirection in Ajax Submission.
970 if ( empty( $submission_redirection_process ) ) {
971 if ( isset( $settings['redirect_to'] ) && 'external_url' === $settings['redirect_to'] ) {
972 if ( isset( $settings['enable_redirect_query_string'] ) && '1' === $settings['enable_redirect_query_string'] ) {
973 parse_str( $settings['query_string'], $output );
974 $query_redirect_url = array();
975 foreach ( $output as $key => $value ) {
976 $query_redirect_url[ $key ] = rawurlencode( apply_filters( 'everest_forms_process_smart_tags', $value, $this->form_data, $this->form_fields ) );
977 }
978 $redirect_url = add_query_arg( $query_redirect_url, $settings['external_url'] );
979 } else {
980 $redirect_url = $settings['external_url'];
981 }
982 $response_data['redirect_url'] = ! empty( $redirect_url ) ? esc_url( $redirect_url ) : 'undefined';
983 $response_data['enable_redirect_in_new_tab'] = isset( $settings['enable_redirect_in_new_tab'] ) ? $settings['enable_redirect_in_new_tab'] : false;
984
985 } elseif ( isset( $settings['redirect_to'] ) && 'custom_page' === $settings['redirect_to'] ) {
986 if ( isset( $settings['enable_redirect_query_string'] ) && '1' === $settings['enable_redirect_query_string'] ) {
987 parse_str( $settings['query_string'], $output );
988 $query_redirect_url = array();
989 foreach ( $output as $key => $value ) {
990 $query_redirect_url[ $key ] = apply_filters( 'everest_forms_process_smart_tags', $value, $this->form_data, $this->form_fields );
991 }
992 $redirect_url = add_query_arg( $query_redirect_url, esc_url( get_page_link( $settings['custom_page'] ) ) );
993 } else {
994 $redirect_url = get_page_link( $settings['custom_page'] );
995 }
996 $response_data['redirect_url'] = ! empty( $redirect_url ) ? esc_url( $redirect_url ) : 'undefined';
997
998 }
999 } else {
1000 // Overiding the default setting message
1001 if ( 'same' === $submission_redirection_process['redirect_to'] ) {
1002 $form_state_type = $submission_redirection_process['settings']['form_state_type'];
1003 if ( 'hide' === $form_state_type ) {
1004
1005 $response_data['message_display_location'] = $submission_redirection_process['settings']['message_display_location_of_hide'];
1006 } else {
1007 $response_data['message_display_location'] = $submission_redirection_process['settings']['message_display_location_of_reset'];
1008 }
1009
1010 $response_data['message'] = $submission_redirection_process['settings']['successful_form_submission_message'];
1011
1012 } else {
1013 $response_data['redirect_url'] = esc_url( $submission_redirection_process['external_url'] );
1014 $response_data['enable_redirect_in_new_tab'] = isset( $settings['enable_redirect_in_new_tab'] ) ? $settings['enable_redirect_in_new_tab'] : false;
1015 }
1016 }
1017
1018 // Add notice only if credit card is populated in form fields.
1019 if ( isset( $this->evf_notice_print ) && $this->evf_notice_print ) {
1020 evf_add_notice( $message, 'success' );
1021 }
1022 // $this->entry_confirmation_redirect( $this->form_data );
1023 $response_data = apply_filters( 'everest_forms_after_success_ajax_message', $response_data, $this->form_data, $entry );
1024 delete_option( 'everest_forms_overall_feedback_is_called' );
1025 return $response_data;
1026 } elseif ( ( 'same' === $this->form_data['settings']['redirect_to'] && empty( $submission_redirection_process ) ) ) {
1027 if ( 'hide' === $message_display_location ) {
1028 evf_add_notice( $message, 'success' );
1029 }
1030
1031 $form_state_type = isset( $this->form_data['settings']['form_state_type'] ) ? $this->form_data['settings']['form_state_type'] : 'hide';
1032 $_REQUEST['evf_form_state_type'] = sanitize_text_field( $form_state_type );
1033
1034 } elseif ( ! empty( $submission_redirection_process ) && 'same' == $submission_redirection_process['redirect_to'] ) {
1035 $form_state_type = $submission_redirection_process['settings']['form_state_type'];
1036 $message = $submission_redirection_process['settings']['successful_form_submission_message'];
1037 if ( 'hide' === $form_state_type ) {
1038
1039 $message_display_location = isset( $submission_redirection_process['settings']['message_display_location_of_hide'] ) ? $submission_redirection_process['settings']['message_display_location_of_hide'] : 'hide';
1040 } else {
1041 $message_display_location = isset( $submission_redirection_process['settings']['message_display_location_of_reset'] ) ? $submission_redirection_process['settings']['message_display_location_of_reset'] : 'top';
1042 }
1043 if ( 'hide' === $message_display_location ) {
1044 evf_add_notice( $message, 'success' );
1045 }
1046 // Setting message to reflect back after page refresh.
1047 $_REQUEST['evf_message_display_location'] = sanitize_text_field( $message_display_location );
1048 $_REQUEST['evf_form_state_type'] = sanitize_text_field( $form_state_type );
1049 $_REQUEST['evf_popup_message'] = wp_kses_post( $message );
1050 }
1051 $logger->info(
1052 'Everest Forms After success Message.',
1053 array( 'source' => 'form-submission' )
1054 );
1055
1056 do_action( 'everest_forms_after_success_message', $this->form_data, $entry );
1057 delete_option( 'everest_forms_overall_feedback_is_called' );
1058 $this->entry_confirmation_redirect( $this->form_data );
1059 }
1060
1061 /**
1062 * Process AJAX form submission.
1063 *
1064 * @since 1.6.0
1065 *
1066 * @param mixed $posted_data Posted data.
1067 */
1068 public function ajax_form_submission( $posted_data ) {
1069 add_filter( 'wp_redirect', array( $this, 'ajax_process_redirect' ), 999 );
1070 $process = $this->do_task( $posted_data );
1071 return $process;
1072 }
1073
1074 /**
1075 * Process AJAX redirect.
1076 *
1077 * @since 1.6.0
1078 *
1079 * @param string $url Redirect URL.
1080 */
1081 public function ajax_process_redirect( $url ) {
1082 $form_id = isset( $_POST['everest_forms']['id'] ) ? absint( $_POST['everest_forms']['id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1083
1084 if ( empty( $form_id ) ) {
1085 wp_send_json_error();
1086 }
1087
1088 $response = array(
1089 'form_id' => $form_id,
1090 'redirect_url' => $url,
1091 );
1092
1093 $response = apply_filters( 'everest_forms_ajax_submit_redirect', $response, $form_id, $url );
1094
1095 do_action( 'everest_forms_ajax_submit_completed', $form_id, $response );
1096 wp_send_json_success( $response );
1097 }
1098
1099 /**
1100 * Build an error submission result when the entry was recorded as a failed payment.
1101 *
1102 * Gateways hook `everest_forms_process_complete` and call `evf_payment_entries()` after the entry is saved,
1103 * so payment meta is only reliable after those hooks run.
1104 *
1105 * @param int $entry_id Entry ID.
1106 * @return array|null Error payload (response => error), or null if not a failed payment entry.
1107 */
1108 private function get_failed_payment_submission_result( $entry_id ) {
1109 if ( $entry_id <= 0 || ! function_exists( 'evf_get_entry' ) ) {
1110 return null;
1111 }
1112
1113 wp_cache_delete( $entry_id, 'evf-entry' );
1114 wp_cache_delete( $entry_id, 'evf-entrymeta' );
1115
1116 $entry_obj = evf_get_entry( $entry_id );
1117 if ( ! $entry_obj || empty( $entry_obj->meta ) || ! is_array( $entry_obj->meta ) ) {
1118 return null;
1119 }
1120
1121 $pay_type = isset( $entry_obj->meta['type'] ) ? (string) $entry_obj->meta['type'] : '';
1122 $status = isset( $entry_obj->meta['status'] ) ? (string) $entry_obj->meta['status'] : '';
1123
1124 if ( 'payment' !== $pay_type || 0 !== strcasecmp( 'failed', $status ) ) {
1125 return null;
1126 }
1127
1128 $message = apply_filters(
1129 'everest_forms_payment_failed_submission_message',
1130 __( 'Payment could not be completed. Please try again or use a different payment method.', 'everest-forms' ),
1131 $entry_obj,
1132 $this->form_data
1133 );
1134
1135 return array(
1136 'response' => 'error',
1137 'message' => $message,
1138 'error' => array(),
1139 'form_id' => isset( $this->form_data['id'] ) ? absint( $this->form_data['id'] ) : 0,
1140 );
1141 }
1142
1143 /**
1144 * Check the sucessful message.
1145 *
1146 * @param bool $status Message status.
1147 * @param int $form_id Form ID.
1148 */
1149 public function check_success_message( $status, $form_id ) {
1150 if ( isset( $this->form_data['id'] ) && absint( $this->form_data['id'] ) === $form_id ) {
1151 return true;
1152 }
1153 return false;
1154 }
1155
1156 /**
1157 * Validate the form return hash.
1158 *
1159 * @since 1.0.0
1160 *
1161 * @param string $hash Base64-encoded hash of form and entry IDs.
1162 * @return array|false False for invalid or form id.
1163 */
1164 public function validate_return_hash( $hash = '' ) {
1165 $query_args = base64_decode( $hash );
1166
1167 parse_str( $query_args, $output );
1168
1169 // Verify hash matches.
1170 if ( wp_hash( $output['form_id'] . ',' . $output['entry_id'] ) !== $output['hash'] ) {
1171 return false;
1172 }
1173
1174 // Get lead and verify it is attached to the form we received with it.
1175 $entry = evf_get_entry( $output['entry_id'] );
1176
1177 if ( empty( $entry->form_id ) ) {
1178 return false;
1179 }
1180
1181 if ( $output['form_id'] !== $entry->form_id ) {
1182 return false;
1183 }
1184
1185 return array(
1186 'form_id' => absint( $output['form_id'] ),
1187 'entry_id' => absint( $output['form_id'] ),
1188 'fields' => null !== $entry && isset( $entry->fields ) ? $entry->fields : array(),
1189 );
1190 }
1191
1192 /**
1193 * Redirects user to a page or URL specified in the form confirmation settings.
1194 *
1195 * @since 1.0.0
1196 *
1197 * @param array $form_data Form data and settings.
1198 * @param string $hash Base64-encoded hash of form and entry IDs.
1199 */
1200 public function entry_confirmation_redirect( $form_data = '', $hash = '' ) {
1201 $_POST = array(); // Clear fields after successful form submission.
1202
1203 // Process return hash.
1204 if ( ! empty( $hash ) ) {
1205 $hash_data = $this->validate_return_hash( $hash );
1206
1207 if ( ! $hash_data || ! is_array( $hash_data ) ) {
1208 return;
1209 }
1210
1211 $this->is_valid_hash = true;
1212 $this->entry_id = absint( $hash_data['entry_id'] );
1213 $this->form_fields = json_decode( $hash_data['fields'], true );
1214 $this->form_data = evf()->form->get(
1215 absint( $hash_data['form_id'] ),
1216 array(
1217 'content_only' => true,
1218 )
1219 );
1220 } else {
1221 $this->form_data = $form_data;
1222 }
1223
1224 $settings = $this->form_data['settings'];
1225
1226 // Backward Compatibility Check.
1227 switch ( $settings['redirect_to'] ) {
1228 case '0':
1229 $settings['redirect_to'] = 'same';
1230 break;
1231
1232 case '1':
1233 $settings['redirect_to'] = 'custom_page';
1234 break;
1235
1236 case '2':
1237 $settings['redirect_to'] = 'external_url';
1238 break;
1239 }
1240
1241 $submission_redirect_process = apply_filters( 'everest_forms_submission_redirection_process', array(), $this->form_fields, $this->form_data );
1242
1243 if ( ! empty( $submission_redirect_process ) ) {
1244 $settings['redirect_to'] = $submission_redirect_process['redirect_to'];
1245 $settings['external_url'] = $submission_redirect_process['external_url'];
1246 $settings['custom_page'] = $submission_redirect_process['custom_page'];
1247 }
1248
1249 if ( isset( $settings['redirect_to'] ) && 'custom_page' === $settings['redirect_to'] ) {
1250 if ( isset( $settings['enable_redirect_query_string'] ) && '1' === $settings['enable_redirect_query_string'] ) {
1251 parse_str( $settings['query_string'], $output );
1252 $query_redirect_url = array();
1253 foreach ( $output as $key => $value ) {
1254 $query_redirect_url[ $key ] = apply_filters( 'everest_forms_process_smart_tags', $value, $this->form_data, $this->form_fields );
1255 }
1256 $redirect_url = add_query_arg( $query_redirect_url, esc_url( get_page_link( $settings['custom_page'] ) ) );
1257 } else {
1258 $redirect_url = get_page_link( $settings['custom_page'] );
1259 }
1260
1261 ?>
1262 <script>
1263 var redirect = '<?php echo esc_url_raw( $redirect_url ); ?>';
1264 window.setTimeout( function () {
1265 window.location.href = redirect;
1266 })
1267 </script>
1268 <?php
1269 } elseif ( isset( $settings['redirect_to'] ) && 'external_url' === $settings['redirect_to'] ) {
1270 $new_tab = ! empty( $settings['enable_redirect_in_new_tab'] ); // More reliable check
1271
1272 if ( isset( $settings['enable_redirect_query_string'] ) && '1' === $settings['enable_redirect_query_string'] ) {
1273 parse_str( $settings['query_string'], $output );
1274 $query_redirect_url = array();
1275 foreach ( $output as $key => $value ) {
1276 $query_redirect_url[ $key ] = rawurlencode( apply_filters( 'everest_forms_process_smart_tags', $value, $this->form_data, $this->form_fields ) );
1277 }
1278 $redirect_url = add_query_arg( $query_redirect_url, $settings['external_url'] );
1279 } else {
1280 $redirect_url = $settings['external_url'];
1281 }
1282
1283 // Only proceed if we have a valid URL
1284 if ( $redirect_url && filter_var( $redirect_url, FILTER_VALIDATE_URL ) ) {
1285 if ( $new_tab ) {
1286 ?>
1287 <script type="text/javascript">
1288 document.addEventListener('DOMContentLoaded', function() {
1289 var a = document.createElement('a');
1290 a.href = '<?php echo esc_url( $redirect_url ); ?>';
1291 a.target = '_blank';
1292 a.rel = 'noopener noreferrer';
1293 a.style.display = 'none';
1294
1295 document.body.appendChild(a);
1296
1297 a.click();
1298
1299 // Fallback if blocked
1300 setTimeout(function() {
1301 window.location.href = '<?php echo esc_url( $redirect_url ); ?>';
1302 }, 100);
1303 });
1304 </script>
1305 <?php
1306 } else {
1307 ?>
1308 <script type="text/javascript">
1309 setTimeout(function() {
1310 window.location.replace('<?php echo esc_url( $redirect_url ); ?>');
1311 }, 100);
1312 </script>
1313 <?php
1314 }
1315 }
1316 }
1317
1318 // Redirect if needed, to either a page or URL, after form processing.
1319 if ( ! empty( $this->form_data['settings']['confirmation_type'] ) && 'message' !== $this->form_data['settings']['confirmation_type'] ) {
1320 if ( 'redirect' === $this->form_data['settings']['confirmation_type'] ) {
1321 $url = apply_filters( 'everest_forms_process_smart_tags', $this->form_data['settings']['confirmation_redirect'], $this->form_data, $this->form_fields, $this->entry_id );
1322 }
1323
1324 if ( 'page' === $this->form_data['settings']['confirmation_type'] ) {
1325 $url = get_permalink( (int) $this->form_data['settings']['confirmation_page'] );
1326 }
1327 }
1328
1329 if ( ! empty( $this->form_data['id'] ) ) {
1330 $form_id = $this->form_data['id'];
1331 } else {
1332 return;
1333 }
1334 if ( isset( $settings['submission_message_scroll'] ) && $settings['submission_message_scroll'] ) {
1335 add_filter( 'everest_forms_success_notice_class', array( $this, 'add_scroll_notice_class' ) );
1336 }
1337
1338 if ( ! empty( $url ) ) {
1339 $url = apply_filters( 'everest_forms_process_redirect_url', $url, $form_id, $this->form_fields );
1340 wp_safe_redirect( esc_url_raw( $url ) );
1341 do_action( 'everest_forms_process_redirect', $form_id );
1342 do_action( "everest_forms_process_redirect_{$form_id}", $form_id );
1343 exit;
1344 }
1345 }
1346
1347 /**
1348 * Add scroll notice class.
1349 *
1350 * @param array $classes Notice Classes.
1351 * @return array of notice classes.
1352 */
1353 public function add_scroll_notice_class( $classes ) {
1354 $classes[] = 'everest-forms-submission-scroll';
1355
1356 return $classes;
1357 }
1358
1359 /**
1360 * Sends entry email notifications.
1361 *
1362 * @param array $fields List of fields.
1363 * @param array $entry Submitted form entry.
1364 * @param array $form_data Form data and settings.
1365 * @param int $entry_id Saved entry id.
1366 * @param string $context In which context this email is sent.
1367 */
1368 public function entry_email( $fields, $entry, $form_data, $entry_id, $context = '' ) {
1369 // Provide the opportunity to override via a filter.
1370 if ( ! apply_filters( 'everest_forms_entry_email', true, $fields, $entry, $form_data ) ) {
1371 return;
1372 }
1373
1374 // Make sure we have an entry id.
1375 if ( empty( $this->entry_id ) ) {
1376 $this->entry_id = (int) $entry_id;
1377 }
1378
1379 $fields = apply_filters( 'everest_forms_entry_email_data', $fields, $entry, $form_data );
1380
1381 if ( ! isset( $form_data['settings']['email']['connection_1'] ) ) {
1382 $old_email_data = $form_data['settings']['email'];
1383 $form_data['settings']['email'] = array();
1384 $form_data['settings']['email']['connection_1'] = array( 'connection_name' => __( 'Admin Notification', 'everest-forms' ) );
1385
1386 $email_settings = array( 'evf_to_email', 'evf_from_name', 'evf_from_email', 'evf_reply_to', 'evf_email_subject', 'enable-ai-email-prompt', 'evf_email_message_prompt', 'evf_email_message', 'attach_pdf_to_admin_email', 'show_header_in_attachment_pdf_file', 'conditional_logic_status', 'conditional_option', 'conditionals' );
1387 foreach ( $email_settings as $email_setting ) {
1388 $form_data['settings']['email']['connection_1'][ $email_setting ] = isset( $old_email_data[ $email_setting ] ) ? $old_email_data[ $email_setting ] : '';
1389 }
1390 }
1391
1392 $notifications = isset( $form_data['settings']['email'] ) ? $form_data['settings']['email'] : array();
1393
1394 foreach ( $notifications as $connection_id => $notification ) :
1395
1396 // Don't proceed if email notification is not enabled.
1397 if ( isset( $notification['enable_email_notification'] ) && '1' !== $notification['enable_email_notification'] ) {
1398 continue;
1399 }
1400
1401 $process_email = apply_filters( 'everest_forms_entry_email_process', true, $fields, $form_data, $context, $connection_id );
1402
1403 if ( ! $process_email ) {
1404 continue;
1405 }
1406
1407 $email = array();
1408 $evf_to_email = isset( $notification['evf_to_email'] ) ? $notification['evf_to_email'] : '';
1409
1410 // Setup email properties.
1411 /* translators: %s - form name. */
1412 $email['subject'] = ! empty( $notification['evf_email_subject'] ) ? $notification['evf_email_subject'] : sprintf( esc_html__( 'New %s Entry', 'everest-forms' ), $form_data['settings']['form_title'] );
1413 $email['address'] = explode( ',', apply_filters( 'everest_forms_process_smart_tags', $evf_to_email, $form_data, $fields, $this->entry_id ) );
1414 $email['address'] = array_map( 'sanitize_email', $email['address'] );
1415 $email['sender_name'] = ! empty( $notification['evf_from_name'] ) ? $notification['evf_from_name'] : get_bloginfo( 'name' );
1416 $email['sender_address'] = ! empty( $notification['evf_from_email'] ) ? $notification['evf_from_email'] : get_option( 'admin_email' );
1417 $email['reply_to'] = ! empty( $notification['evf_reply_to'] ) ? $notification['evf_reply_to'] : $email['sender_address'];
1418 if ( ! empty( get_option( 'everest_forms_ai_api_key' ) ) ) { // phpcs:ignore
1419 $email['message_ai_prompt'] = ! empty( $notification['evf_email_message_prompt'] ) ? $notification['evf_email_message_prompt'] : '';
1420 $email['enable_ai_prompt'] = ! empty( $notification['enable_ai_email_prompt'] ) ? $notification['enable_ai_email_prompt'] : 0;
1421 }
1422 $email['message'] = ! empty( $notification['evf_email_message'] ) ? evf_string_translation( $form_data['id'], 'evf_email_message', $notification['evf_email_message'] ) : '{all_fields}';
1423 $email = apply_filters( 'everest_forms_entry_email_atts', $email, $fields, $entry, $form_data );
1424 $attachment = '';
1425
1426 // Create new email.
1427 $emails = new EVF_Emails();
1428 $emails->__set( 'form_data', $form_data );
1429 $emails->__set( 'fields', $fields );
1430 $emails->__set( 'entry_id', $entry_id );
1431 $emails->__set( 'from_name', $email['sender_name'] );
1432 $emails->__set( 'from_address', $email['sender_address'] );
1433 $emails->__set( 'reply_to', $email['reply_to'] );
1434
1435 /**
1436 * This filter relies on consistent data being passed for the resultant filters to function.
1437 * The third param passed for the filter, $fields, is derived from validation routine, not the DB.
1438 */
1439 $emails->__set( 'attachments', apply_filters( 'everest_forms_email_file_attachments', $attachment, $fields, $form_data, 'entry-email', $connection_id, $entry_id ) );
1440
1441 // Maybe include Cc and Bcc email addresses.
1442 if ( 'yes' === get_option( 'everest_forms_enable_email_copies' ) ) {
1443 if ( ! empty( $notification['evf_carboncopy'] ) ) {
1444 $emails->__set( 'cc', $notification['evf_carboncopy'] );
1445 }
1446 if ( ! empty( $notification['evf_blindcarboncopy'] ) ) {
1447 $emails->__set( 'bcc', $notification['evf_blindcarboncopy'] );
1448 }
1449 }
1450
1451 $emails = apply_filters( 'everest_forms_entry_email_before_send', $emails );
1452
1453 // Send entry email.
1454 foreach ( $email['address'] as $address ) {
1455 $emails->send( trim( $address ), $email['subject'], $email['message'], '', $connection_id );
1456 }
1457
1458 if ( isset( $attachment ) ) {
1459 do_action( 'everest_forms_remove_attachments_after_send_email', $attachment, $fields, $form_data, 'entry-email', $connection_id, $entry_id );
1460 }
1461 endforeach;
1462 }
1463
1464 /**
1465 * Saves entry to database.
1466 *
1467 * @param array $fields List of form fields.
1468 * @param array $entry User submitted data.
1469 * @param int $form_id Form ID.
1470 * @param array $form_data Prepared form settings.
1471 * @return int
1472 */
1473 public function entry_save( $fields, $entry, $form_id, $form_data = array() ) {
1474 global $wpdb;
1475
1476 // Check if form has entries disabled.
1477 if ( isset( $form_data['settings']['disabled_entries'] ) && '1' === $form_data['settings']['disabled_entries'] ) {
1478 return;
1479 }
1480
1481 // Provide the opportunity to override via a filter.
1482 if ( ! apply_filters( 'everest_forms_entry_save', true, $fields, $entry, $form_data ) ) {
1483 return;
1484 }
1485
1486 do_action( 'everest_forms_process_entry_save', $fields, $entry, $form_id, $form_data );
1487
1488 $fields = apply_filters( 'everest_forms_entry_save_data', $fields, $entry, $form_data );
1489 $browser = evf_get_browser();
1490 $user_ip = evf_get_ip_address();
1491 $user_device = evf_get_user_device();
1492 $user_agent = $browser['name'] . '/' . $browser['platform'] . '/' . $user_device;
1493 $referer = ! empty( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
1494 $entry_id = false;
1495 $status = isset( $entry['evf_spam_status'] ) ? $entry['evf_spam_status'] : 'publish';
1496 $admin_approval_entries = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
1497 $settings = isset( $form_data['settings'] ) ? $form_data['settings'] : array();
1498 $evf_form_admin_approval_entries = isset( $settings['enable_admin_approval_entries'] ) ? $settings['enable_admin_approval_entries'] : '0';
1499
1500 if ( 'yes' === $admin_approval_entries && '1' === $evf_form_admin_approval_entries ) {
1501 $status = 'pending';
1502 }
1503
1504 // GDPR enhancements - If user details are disabled globally discard the IP and UA.
1505 if ( 'yes' === get_option( 'everest_forms_disable_user_details' ) ) {
1506 $user_agent = '';
1507 $user_ip = '';
1508 }
1509
1510 $entry_data = apply_filters(
1511 'everest_forms_entry_data',
1512 array(
1513 'form_id' => $form_id,
1514 'user_id' => get_current_user_id(),
1515 'user_device' => sanitize_text_field( $user_agent ),
1516 'user_ip_address' => sanitize_text_field( $user_ip ),
1517 'status' => $status,
1518 'referer' => $referer,
1519 'fields' => wp_json_encode( $fields ),
1520 'date_created' => current_time( 'mysql', true ),
1521 ),
1522 $entry
1523 );
1524
1525 if ( ! $entry_data['form_id'] ) {
1526 return new WP_Error( 'no-form-id', __( 'No form ID was found.', 'everest-forms' ) );
1527 }
1528
1529 // Create entry.
1530 $success = $wpdb->insert( $wpdb->prefix . 'evf_entries', $entry_data );
1531
1532 if ( is_wp_error( $success ) || ! $success ) {
1533 return new WP_Error( 'could-not-create', __( 'Could not create an entry', 'everest-forms' ) );
1534 }
1535
1536 $entry_id = $wpdb->insert_id;
1537
1538 // Create meta data.
1539 if ( $entry_id ) {
1540 foreach ( $fields as $field ) {
1541 $field = apply_filters( 'everest_forms_entry_save_fields', $field, $form_data, $entry_id );
1542 // Add only whitelisted fields to entry meta.
1543 if ( in_array( $field['type'], array( 'html', 'title' ), true ) ) {
1544 continue;
1545 }
1546
1547 // If empty file is supplied, don't store their data nor send email.
1548 if ( in_array( $field['type'], array( 'image-upload', 'file-upload' ), true ) ) {
1549
1550 // BW compatibility for previous file uploader.
1551 if ( isset( $field['value']['file_url'] ) && '' === $field['value']['file_url'] ) {
1552 continue;
1553 }
1554 }
1555
1556 // If empty label is provided for choice field, don't store their data nor send email.
1557 if ( in_array( $field['type'], array( 'radio', 'payment-multiple' ), true ) ) {
1558 if ( isset( $field['value']['label'] ) && '' === $field['value']['label'] ) {
1559 continue;
1560 }
1561 } elseif ( in_array( $field['type'], array( 'checkbox', 'payment-checkbox' ), true ) ) {
1562 if ( isset( $field['value']['label'] ) && ( empty( $field['value']['label'] ) || '' === current( $field['value']['label'] ) ) ) {
1563 continue;
1564 }
1565 }
1566
1567 if ( isset( $field['meta_key'], $field['value'] ) && '' !== $field['value'] ) {
1568 if ( ! empty( $field['value'] ) && is_string( $field['value'] ) && strpos( $field['value'], '{' ) !== false ) {
1569 $field['value'] = apply_filters( 'everest_forms_process_smart_tags', $field['value'], $form_data, $fields, $entry_id );
1570 }
1571 $entry_metadata = array(
1572 'entry_id' => $entry_id,
1573 'meta_key' => sanitize_key( $field['meta_key'] ),
1574 'meta_value' => maybe_serialize( $field['value'] ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
1575 );
1576
1577 // Insert entry meta.
1578 $wpdb->insert( $wpdb->prefix . 'evf_entrymeta', $entry_metadata );
1579 }
1580 }
1581 }
1582
1583 $this->entry_id = $entry_id;
1584
1585 // Removing Entries Cache.
1586 wp_cache_delete( $entry_id, 'evf-entry' );
1587 wp_cache_delete( $entry_id, 'evf-entrymeta' );
1588 wp_cache_delete( $form_id, 'evf-entries-ids' );
1589 wp_cache_delete( $form_id, 'evf-last-entries-count' );
1590 wp_cache_delete( $form_id, 'evf-search-entries' );
1591 wp_cache_delete( EVF_Cache_Helper::get_cache_prefix( 'entries' ) . '_unread_count', 'entries' );
1592
1593 do_action( 'everest_forms_complete_entry_save', $entry_id, $fields, $entry, $form_id, $form_data );
1594
1595 return $this->entry_id;
1596 }
1597
1598 /**
1599 * Insert or update the slot booking data.
1600 *
1601 * @param int $entry_id Entry id.
1602 * @param array $fields List of form fields.
1603 * @param array $entry User submitted data.
1604 * @param int $form_id Form ID.
1605 * @param array $form_data Prepared form settings.
1606 */
1607 public function update_slot_booking_value( $entry_id, $fields, $entry, $form_id, $form_data ) {
1608 $new_slot_booking_field_meta_key_list = array();
1609 $time_interval = 0;
1610 foreach ( $form_data['form_fields'] as $field ) {
1611 if ( ( 'date-time' === $field['type'] ) && isset( $field['slot_booking_advanced'] ) && evf_string_to_bool( $field['slot_booking_advanced'] ) ) {
1612 $new_slot_booking_field_meta_key_list[ $field['meta-key'] ] = array(
1613 $field['datetime_format'],
1614 $field['date_format'],
1615 $field['date_mode'],
1616 );
1617 $time_interval = $field['time_interval'];
1618 }
1619 }
1620
1621 foreach ( $fields as $key => $value ) {
1622 if ( array_key_exists( $value['meta_key'], $new_slot_booking_field_meta_key_list ) ) {
1623 $new_value = $value['value'];
1624 $datetime_format = $new_slot_booking_field_meta_key_list[ $value['meta_key'] ][0];
1625 $date_format = $new_slot_booking_field_meta_key_list[ $value['meta_key'] ][1];
1626 $mode = $new_slot_booking_field_meta_key_list[ $value['meta_key'] ][2];
1627 $datetime_arr = parse_datetime_values( $new_value, $datetime_format, $date_format, $mode, $time_interval, $entry_id );
1628 }
1629 }
1630 if ( ! empty( $datetime_arr ) ) {
1631 $get_booked_slot = get_option( 'evf_booked_slot', array() );
1632 $new_booked_slot = array( $form_id => $datetime_arr );
1633
1634 if ( empty( $get_booked_slot ) ) {
1635 $all_booked_slot = maybe_serialize( $new_booked_slot );
1636 } else {
1637 $unserialized_booked_slot = evf_maybe_unserialize( $get_booked_slot );
1638
1639 if ( array_key_exists( $form_id, $unserialized_booked_slot ) ) {
1640 $booked_slot = $unserialized_booked_slot[ $form_id ];
1641 $booked_slot = (array) $booked_slot + $datetime_arr;
1642 $new_booked_slot = array( $form_id => $booked_slot );
1643 }
1644
1645 $all_booked_slot = maybe_serialize( array_replace( $unserialized_booked_slot, $new_booked_slot ) );
1646 }
1647
1648 update_option( 'evf_booked_slot', $all_booked_slot );
1649 }
1650 }
1651
1652 /**
1653 * Load Previous Field Value.
1654 *
1655 * @param string $properties Value.
1656 * @param mixed $field Field.
1657 * @param mixed $form_data Form Data.
1658 * @return $properties Properties.
1659 */
1660 public function load_previous_field_value( $properties, $field, $form_data ) {
1661
1662 if ( ! isset( $_POST['everest_forms'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1663 return $properties;
1664 }
1665 $data = ! empty( $_POST['everest_forms']['form_fields'][ $field['id'] ] ) ? wp_unslash( $_POST['everest_forms']['form_fields'][ $field['id'] ] ) : array(); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1666
1667 if ( 'checkbox' === $field['type'] ) {
1668 foreach ( $field['choices'] as $key => $option_value ) {
1669 $selected = ! empty( $option_value['default'] ) ? $option_value['default'] : '';
1670 foreach ( $data as $value ) {
1671 if ( $value === $option_value['label'] ) {
1672 $selected = 1;
1673 $properties['inputs'][ $key ]['default'] = $selected;
1674 }
1675 }
1676 }
1677 } elseif ( 'radio' === $field['type'] || 'select' === $field['type'] ) {
1678 foreach ( $field['choices'] as $key => $option_value ) {
1679 if ( $data === $option_value['label'] ) { // phpcs:ignore WordPress.Security.NonceVerification
1680 $selected = 1;
1681 $properties['inputs'][ $key ]['default'] = $selected;
1682 }
1683 }
1684 } elseif ( 'likert' === $field['type'] ) {
1685 if ( count( $data ) ) {
1686 foreach ( $data as $row => $col ) {
1687 foreach ( (array) $col as $col_selected ) {
1688 $index = sprintf( 'rows%d_columns%d', (int) $row, (int) $col_selected );
1689 $properties['inputs'][ $index ]['attr']['checked'] = true;
1690 }
1691 }
1692 }
1693 } elseif ( ! is_array( $data ) ) {
1694 $properties['inputs']['primary']['attr']['value'] = esc_attr( $data );
1695 }
1696 return $properties;
1697 }
1698
1699 /**
1700 * Check if a form entry should be validated by Akismet for potential spam.
1701 *
1702 * This function checks whether the Akismet plugin is installed and configured, and if the Akismet
1703 * validation option is enabled for a specific form. If validation is enabled, it prepares the
1704 * necessary data for the validation request and sends it to Akismet's 'comment-check' endpoint.
1705 *
1706 * @param array $entry The form entry data to validate.
1707 * @param string $form_id (Optional) The identifier of the form.
1708 *
1709 * @return bool
1710 * - true if the form entry is potentially spam according to Akismet.
1711 * - false if Akismet validation is not enabled, the plugin is not properly configured, or the entry is not considered spam.
1712 */
1713 public function get_akismet_validate( $entry, $form_id = '' ) {
1714
1715 if ( ! file_exists( WP_PLUGIN_DIR . '/akismet/akismet.php' ) ) {
1716 return false;
1717 }
1718
1719 if ( ! evf_is_akismet_configured() ) {
1720 return false;
1721 }
1722
1723 if ( isset( $this->form_data['settings']['akismet'] ) && '1' === $this->form_data['settings']['akismet'] ) {
1724 $entry_data = $this->get_entry_data_for_akismet( $this->form_data['form_fields'], $entry );
1725
1726 $entry_data = apply_filters( 'evf_entry_akismet_entry_data', $entry_data, $entry, $this->form_data );
1727
1728 $request = array(
1729 'blog' => get_option( 'home' ),
1730 'user_ip' => evf_get_ip_address(),
1731 'user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) : null, // phpcs:ignore
1732 'referrer' => wp_get_referer() ? wp_get_referer() : null,
1733 'permalink' => evf_current_url(),
1734 'comment_type' => 'contact-form',
1735 'comment_author' => isset( $entry_data['name'] ) ? $entry_data['name'] : '',
1736 'comment_author_email' => isset( $entry_data['email'] ) ? $entry_data['email'] : '',
1737 'comment_author_url' => isset( $entry_data['url'] ) ? $entry_data['url'] : '',
1738 'comment_content' => isset( $entry_data['content'] ) ? $entry_data['content'] : '',
1739 'blog_lang' => get_locale(),
1740 'blog_charset' => get_bloginfo( 'charset' ),
1741 'honypot_field_name' => 'everest_forms[hp]',
1742 );
1743
1744 $request = apply_filters( 'evf_akismet_request_data', $request, $this->form_data, $entry, $form_id );
1745
1746 $response = Akismet::http_post( build_query( $request ), 'comment-check' );
1747
1748 return ! empty( $response ) && isset( $response[1] ) && 'true' === trim( $response[1] );
1749 }
1750
1751 return false;
1752 }
1753
1754 /**
1755 * Check if a form entry should be validated by CleanTalk for potential spam.
1756 *
1757 * @since 3.2.2
1758 *
1759 * @param [type] $entry The form entry data to validate.
1760 * @param string $form_id (Optional) The identifier of the form.
1761 */
1762 public function get_clean_talk_validate( $entry, $form_id = '' ) {
1763
1764 $is_cleantalk_activated = isset( $this->form_data['settings']['cleantalk'] ) ? $this->form_data['settings']['cleantalk'] : false;
1765
1766 if ( ! $is_cleantalk_activated ) {
1767 return false;
1768 }
1769
1770 $mark_as_spam = false;
1771 $logger = evf_get_logger();
1772
1773 $access_key = get_option( 'everest_forms_recaptcha_cleantalk_access_key', '' );
1774
1775 if ( empty( $access_key ) ) {
1776 $logger->notice( 'Missing the CleanTalk Access Key', array( 'source' => 'cleantalk' ) );
1777
1778 return false;
1779 }
1780
1781 return $this->evf_is_spam_submission_clean_talk_rest_api( $entry, $access_key );
1782 }
1783
1784 /**
1785 * Get the list of field types that are allowed to be sent to Akismet.
1786 *
1787 * @since 1.7.6
1788 *
1789 * @return array List of field types that are allowed to be sent to Akismet
1790 */
1791 private function get_field_type_allowlist_for_akisment() {
1792
1793 $field_type_allowlist = array(
1794 'first-name',
1795 'last-name',
1796 'text',
1797 'textarea',
1798 'email',
1799 'phone',
1800 'address',
1801 'url',
1802 'wysiwyg',
1803 );
1804
1805 /**
1806 * Filters the field types that are allowed to be sent to Akismet.
1807 *
1808 * @since 2.4.0
1809 *
1810 * @param array $field_type_allowlist Field types allowed to be sent to Akismet.
1811 */
1812 return (array) apply_filters( 'evf_forms_akismet_get_field_type_allowlist', $field_type_allowlist );
1813 }
1814
1815 /**
1816 * Get the entry data to be sent to Akismet.
1817 *
1818 * @since 2.4.0
1819 *
1820 * @param array $fields Field data for the current form.
1821 * @param array $entry Entry data for the current entry.
1822 *
1823 * @return array $entry_data Entry data to be sent to Akismet.
1824 */
1825 private function get_entry_data_for_akismet( $fields, $entry ) {
1826 $field_type_allowlist = $this->get_field_type_allowlist_for_akisment();
1827 $entry_data = array();
1828 $entry_content = array();
1829
1830 foreach ( $fields as $key => $field ) {
1831 $field_type = $field['type'];
1832
1833 if ( ! in_array( $field_type, $field_type_allowlist, true ) ) {
1834 continue;
1835 }
1836 if ( ! isset( $entry['form_fields'][ $key ] ) ) {
1837 continue;
1838 }
1839 $field_content = is_array( $entry['form_fields'][ $key ] ) ? implode( ' ', $entry['form_fields'][ $key ] ) : $entry['form_fields'][ $key ];
1840
1841 if ( ! isset( $entry_data[ $field_type ] ) && in_array( $field_type, array( 'first-name', 'last-name', 'email', 'url' ), true ) ) {
1842 if ( 'first-name' === $field_type ) {
1843 $entry_data['name'] = isset( $entry_data['name'] ) ? "$field_content " . $entry_data['name'] : $field_content;
1844 continue;
1845 } elseif ( 'last-name' === $field_type ) {
1846 $entry_data['name'] = isset( $entry_data['name'] ) ? $entry_data['name'] . " $field_content" : $field_content;
1847 continue;
1848 }
1849 $entry_data[ $field_type ] = $field_content;
1850 continue;
1851 }
1852
1853 $entry_content[] = $field_content;
1854 }
1855
1856 $entry_data['content'] = implode( ' ', $entry_content );
1857
1858 return $entry_data;
1859 }
1860
1861 /**
1862 * Verify the token and approve the entry if the token matches.
1863 *
1864 * @since 2.0.9
1865 */
1866 public static function evf_admin_approve_entry() {
1867 if ( ! isset( $_GET['evf_admin_approval_entry_token'] ) || empty( $_GET['evf_admin_approval_entry_token'] ) ) {
1868 return;
1869 }
1870
1871 if ( current_user_can( 'edit_users' ) ) {
1872 global $wpdb;
1873 $evf_admin_approve_entry_token_raw = sanitize_text_field( wp_unslash( $_GET['evf_admin_approval_entry_token'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1874
1875 $evf_admin_approval_entry_enable = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
1876 $evf_admin_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1877 $evf_admin_entry_id = isset( $_GET['entry_id'] ) ? absint( $_GET['entry_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1878 $evf_entry_redirect_url = admin_url() . 'admin.php?page=evf-entries&form_id=' . $evf_admin_form_id . '&view-entry=' . $evf_admin_entry_id;
1879 $evf_admin_entry_saved_token = get_option( 'everest_forms_admin_entry_approval_token', array() );
1880 $site_name = get_option( 'blogname' );
1881
1882 if ( 'yes' === $evf_admin_approval_entry_enable ) {
1883 $evf_admin_approval_entry_token = isset( $_GET['evf_admin_approval_entry_token'] ) ? sanitize_text_field( wp_unslash( $_GET['evf_admin_approval_entry_token'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
1884 if ( in_array( $evf_admin_approve_entry_token_raw, $evf_admin_entry_saved_token ) ) {
1885 $evf_admin_approval_approved = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}evf_entries SET status = %s WHERE entry_id = %s ", 'publish', $evf_admin_entry_id ) );
1886 $entry = evf_get_entry( $evf_admin_entry_id );
1887 $entry_meta = $entry->meta;
1888 $first_name = '';
1889 $last_name = '';
1890 $email = '';
1891 $entry_date = $entry->date_created;
1892 $name = '';
1893
1894 foreach ( $entry_meta as $key => $value ) {
1895 if ( preg_match( '/^name/', $key ) ) {
1896 $name = $value;
1897 }
1898
1899 if ( preg_match( '/^first_name_/', $key ) ) {
1900 $first_name = $value;
1901 }
1902
1903 if ( preg_match( '/^last_name_/', $key ) ) {
1904 $last_name = $value;
1905 }
1906
1907 if ( preg_match( '/^email/', $key ) ) {
1908 $email = $value;
1909 }
1910
1911 if ( '' === $name ) {
1912 if ( ! empty( $first_name ) && ! empty( $last_name ) ) {
1913 $name = $first_name . ' ' . $last_name;
1914 } elseif ( ! empty( $first_name ) ) {
1915 $name = $first_name;
1916 } else {
1917 $name = $last_name;
1918 }
1919 }
1920
1921 $subject = apply_filters( 'everest_forms_entry_submission_approval_subject', esc_html__( 'Form Entry Approved', 'everest-forms' ) );
1922 // translators: %s is the name of the user
1923 $message = sprintf( __( 'Hey, %s', 'everest-forms' ), $name ) . '<br/>';
1924 // translators: %s is the entry_date.
1925 $message .= '<br/>' . sprintf( __( 'We’re pleased to inform you that your form entry submitted on %s has been successfully approved.', 'everest-forms' ), $entry_date ) . '<br/>';
1926 $message .= '<br/>' . __( 'Thank you for giving us your precious time.', 'everest-forms' ) . '<br/>';
1927 // translators: %s is the site_name.
1928 $message .= '<br/>' . sprintf( __( 'From %s', 'everest-forms' ), $site_name );
1929 // translators: %s is the message.
1930 $message = apply_filters( 'everest_forms_entry_approval_message', $message, $name, $entry_date, $site_name );
1931 }
1932
1933 $email_obj = new EVF_Emails();
1934 $test = $email_obj->send( $email, $subject, $message );
1935 wp_redirect( $evf_entry_redirect_url );
1936 }
1937 }
1938 }
1939 }
1940
1941 /**
1942 * Verify the token and deny the entry if the token matches.
1943 *
1944 * @since 2.0.9
1945 */
1946 public static function evf_admin_deny_entry() {
1947 if ( ! isset( $_GET['evf_admin_denial_entry_token'] ) || empty( $_GET['evf_admin_denial_entry_token'] ) ) {
1948 return;
1949 }
1950
1951 if ( current_user_can( 'edit_users' ) ) {
1952 global $wpdb;
1953
1954 $evf_admin_approve_entry_token_raw = isset( $_GET['evf_admin_denial_entry_token'] ) ? sanitize_text_field( wp_unslash( $_GET['evf_admin_denial_entry_token'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
1955 $evf_admin_approval_entry_enable = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
1956 $evf_admin_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1957 $evf_admin_entry_id = isset( $_GET['entry_id'] ) ? absint( $_GET['entry_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1958 $evf_entry_redirect_url = admin_url() . 'admin.php?page=evf-entries&form_id=' . $evf_admin_form_id . '&view-entry=' . $evf_admin_entry_id;
1959 $evf_admin_entry_saved_token = get_option( 'everest_forms_admin_entry_approval_token', array() );
1960 $site_name = get_option( 'blogname' );
1961
1962 if ( 'yes' === $evf_admin_approval_entry_enable ) {
1963
1964 $evf_admin_denial_entry_token = isset( $_GET['evf_admin_denial_entry_token'] ) ? sanitize_text_field( wp_unslash( $_GET['evf_admin_denial_entry_token'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
1965 if ( in_array( $evf_admin_approve_entry_token_raw, $evf_admin_entry_saved_token ) ) {
1966 $evf_admin_approval_denied = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}evf_entries SET status = %s WHERE entry_id = %s ", 'denied', $evf_admin_entry_id ) );
1967 $entry = evf_get_entry( $evf_admin_entry_id );
1968 $entry_meta = $entry->meta;
1969 $entry_date = $entry->date_created;
1970 $first_name = '';
1971 $last_name = '';
1972 $email = '';
1973 $name = '';
1974
1975 foreach ( $entry_meta as $key => $value ) {
1976 if ( preg_match( '/^name/', $key ) ) {
1977 $name = $value;
1978 }
1979
1980 if ( preg_match( '/^first_name_/', $key ) ) {
1981 $first_name = $value;
1982 }
1983
1984 if ( preg_match( '/^last_name_/', $key ) ) {
1985 $last_name = $value;
1986 }
1987
1988 if ( preg_match( '/^email/', $key ) ) {
1989 $email = $value;
1990 }
1991
1992 if ( '' === $name ) {
1993 if ( ! empty( $first_name ) && ! empty( $last_name ) ) {
1994 $name = $first_name . ' ' . $last_name;
1995 } elseif ( ! empty( $first_name ) ) {
1996 $name = $first_name;
1997 } else {
1998 $name = $last_name;
1999 }
2000 }
2001
2002 $subject = apply_filters( 'everest_forms_entry_submission_approval_subject', esc_html__( 'Entry Submission Denied', 'everest-forms' ) );
2003 // translators: %s is the name of the user
2004 $message = sprintf( __( 'Hey, %s', 'everest-forms' ), $name ) . '<br/>';
2005 // translators: %s is the entry_date.
2006 $message .= '<br/>' . sprintf( __( 'We’re sorry to inform you that your form entry submitted on %s has been denied.', 'everest-forms' ), $entry_date ) . '<br/>';
2007 $message .= '<br/>' . __( 'Thank you for giving us your precious time.', 'everest-forms' ) . '<br/>';
2008 // translators: %s is the site_name.
2009 $message .= '<br/>' . sprintf( __( 'From %s', 'everest-forms' ), $site_name );
2010 // translators: %s is the message.
2011 $message = apply_filters( 'everest_forms_entry_denial_message', $message, $name, $entry_date, $site_name );
2012
2013 }
2014 $email_obj = new EVF_Emails();
2015 $email_obj->send( $email, $subject, $message );
2016 wp_redirect( $evf_entry_redirect_url );
2017 }
2018 }
2019 }
2020 }
2021
2022 /**
2023 * Set the entry approval token of the entry and update it to the options table in database.
2024 *
2025 * @param int $entry_id Entry ID.
2026 * @param array $form_data Form field data.
2027 *
2028 * @since 2.0.9
2029 */
2030 public function evf_set_approval_status( $entry_id, $form_data ) {
2031 $evf_admin_approval_token_list = array();
2032 $form_id = isset( $form_data['id'] ) ? $form_id['id'] : '';
2033 $evf_admin_entry_enable = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
2034 $evf_admin_entry_approval_token = get_option( 'everest_forms_admin_entry_approval_token', array() );
2035 $evf_approval_key = 'approval_token_' . $entry_id;
2036
2037 // Checks if admin approval entry is enabled.
2038 if ( ! isset( $evf_admin_entry_enable ) ) {
2039 return;
2040 } else {
2041 $token = evf_get_random_string( 20 );
2042 $evf_approval_token = array(
2043 $evf_approval_key => $token,
2044 );
2045 $evf_new_token = array_merge( $evf_admin_entry_approval_token, $evf_approval_token );
2046 update_option( 'everest_forms_admin_entry_approval_token', $evf_new_token );
2047 }
2048 }
2049
2050 /**
2051 * Prevents form submission before the specified duration.
2052 *
2053 * @param array $errors Form submit errors.
2054 * @param object $form_data An object containing settings for the form.
2055 */
2056 public function form_submission_waiting_time( $errors, $form_data ) {
2057 $form_submission_waiting_time_enable = isset( $form_data['settings']['form_submission_min_waiting_time'] ) ? $form_data['settings']['form_submission_min_waiting_time'] : '';
2058 $submission_duration = isset( $form_data['settings']['form_submission_min_waiting_time_input'] ) ? $form_data['settings']['form_submission_min_waiting_time_input'] : '';
2059
2060 if ( isset( $form_submission_waiting_time_enable ) && '1' === $form_submission_waiting_time_enable && 0 <= absint( $submission_duration ) ) {
2061 $evf_submission_start_time = isset( $_POST['evf_submission_start_time'] ) ? sanitize_text_field( wp_unslash( $_POST['evf_submission_start_time'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification
2062 $atts = $form_data['id'];
2063 $submission_time = time() * 1000;
2064
2065 if ( $submission_duration <= 0 ) {
2066 $submission_duration = 1;
2067 }
2068 $waiting_time = absint( $submission_time ) - absint( $evf_submission_start_time );
2069 $form_id = ! empty( $form_data['id'] ) ? $form_data['id'] : 0;
2070
2071 if ( absint( $submission_time ) - absint( $evf_submission_start_time ) <= absint( $submission_duration ) * 1000 ) {
2072 /**
2073 * Filter to modify the waiting time message content.
2074 *
2075 * @since 3.0.2
2076 */
2077 $form_submission_err_msg = apply_filters(
2078 'everest_forms_minimum_waiting_time_form_submission',
2079 sprintf(
2080 "%s <span id='evf_submission_duration' data-duration='%s'>%s</span> %s",
2081 esc_html__( 'Please wait', 'everest-forms' ),
2082 $submission_duration,
2083 $submission_duration,
2084 esc_html__( 'seconds, security checkup is being executed.', 'everest-forms' )
2085 )
2086 );
2087
2088 $errors[ $form_id ]['header'] = $form_submission_err_msg;
2089 }
2090
2091 return $errors;
2092 }
2093 }
2094
2095 /**
2096 * Marks the entry as spam.
2097 *
2098 * @since 3.0.9
2099 */
2100 public function evf_mark_entry_spam() {
2101 if ( ! isset( $_GET['spam-entry'] ) ) {
2102 return;
2103 }
2104
2105 // Verify nonce for security
2106 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'spam-entry' ) ) {
2107 wp_die( esc_html__( 'Security check failed. Please try again.', 'everest-forms' ) );
2108 }
2109
2110 if ( current_user_can( 'edit_users' ) ) {
2111 global $wpdb;
2112
2113 $evf_admin_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0;
2114 $evf_admin_entry_id = isset( $_GET['spam-entry'] ) ? absint( $_GET['spam-entry'] ) : 0;
2115 $evf_entry_redirect_url = admin_url() . 'admin.php?page=evf-entries&form_id=' . $evf_admin_form_id . '&view-entry=' . $evf_admin_entry_id;
2116
2117 $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}evf_entries SET status = %s WHERE entry_id = %s ", 'spam', $evf_admin_entry_id ) );
2118 wp_redirect( $evf_entry_redirect_url );
2119 }
2120 }
2121
2122 /**
2123 * Marks the entry as spam.
2124 *
2125 * @since 3.0.9
2126 */
2127 public function evf_remove_entry_from_spam() {
2128 if ( ! isset( $_GET['unspam-entry'] ) ) {
2129 return;
2130 }
2131
2132 // Verify nonce for security
2133 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'unspam-entry' ) ) {
2134 wp_die( esc_html__( 'Security check failed. Please try again.', 'everest-forms' ) );
2135 }
2136
2137 if ( current_user_can( 'edit_users' ) ) {
2138 global $wpdb;
2139
2140 $evf_admin_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0;
2141 $evf_admin_entry_id = isset( $_GET['unspam-entry'] ) ? absint( $_GET['unspam-entry'] ) : 0;
2142 $evf_entry_redirect_url = admin_url() . 'admin.php?page=evf-entries&form_id=' . $evf_admin_form_id . '&view-entry=' . $evf_admin_entry_id;
2143
2144 $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}evf_entries SET status = %s WHERE entry_id = %s ", 'publish', $evf_admin_entry_id ) );
2145 wp_redirect( $evf_entry_redirect_url );
2146 }
2147 }
2148
2149 /**
2150 * Check if the submission is spam using CleanTalk REST API.
2151 *
2152 * @since 3.2.2
2153 */
2154 public function evf_is_spam_submission_clean_talk_rest_api( $entry, $access_key ) {
2155 $marked_as_spam = false;
2156
2157 $submit_time = isset( $this->form_data['entry']['evf_form_load_time'] ) ? time() - (int) $this->form_data['entry']['evf_form_load_time'] : null;
2158 $event_token = isset( $this->form_data['entry']['evf_event_token'] ) ? $this->form_data['entry']['evf_event_token'] : null;
2159
2160 $entry_data = $this->evf_get_entry_data_for_cleantalk( $this->form_data['form_fields'], $entry );
2161
2162 $all_headers = null;
2163
2164 if ( function_exists( 'apache_request_headers' ) ) {
2165 $all_headers = array_filter(
2166 apache_request_headers(),
2167 function ( $value, $key ) {
2168 return strtolower( $key ) !== 'cookie';
2169 },
2170 ARRAY_FILTER_USE_BOTH
2171 );
2172 $all_headers = json_encode( $all_headers );
2173 $all_headers = false !== $all_headers ? $all_headers : null;
2174 }
2175
2176 $clean_talk_request = array(
2177 'method_name' => 'check_message',
2178 'all_headers' => $all_headers,
2179 'auth_key' => $access_key,
2180 'sender_ip' => $_SERVER['REMOTE_ADDR'],
2181 'sender_info' => json_encode(
2182 array(
2183 'REFERRER' => $_SERVER['HTTP_REFERER'],
2184 'USER_AGENT' => htmlspecialchars( @$_SERVER['HTTP_USER_AGENT'] ),
2185 )
2186 ),
2187 'js_on' => 1,
2188 'submit_time' => $submit_time,
2189 'event_token' => $event_token,
2190 'sender_nickname' => isset( $entry_data['sender_nickname'] ) ? $entry_data['sender_nickname'] : '',
2191 'sender_email' => isset( $entry_data['sender_email'] ) ? $entry_data['sender_email'] : '',
2192 'message' => isset( $entry_data['message'] ) ? $entry_data['message'] : '',
2193 'agent' => 'wordpress-everest-forms-' . EVF_VERSION,
2194 'post_info' => array(
2195 'comment_type' => 'everest_forms_vendor_integration__use_api',
2196 'post_url' => $_SERVER['HTTP_REFERER'],
2197 ),
2198 );
2199
2200 $raw_response = wp_remote_post(
2201 'https://moderate.cleantalk.org/api2.0',
2202 array(
2203 'body' => json_encode( $clean_talk_request ),
2204 'headers' => array(
2205 'Content-Type' => 'application/json',
2206 ),
2207 )
2208 );
2209 $response = json_decode( wp_remote_retrieve_body( $raw_response ) );
2210
2211 if ( empty( $response ) ) {
2212 return true;
2213 }
2214
2215 $clean_talk_passed = $response->allow == 1 && $response->spam == 0 && $response->account_status == 1;
2216
2217 if ( ! $clean_talk_passed ) {
2218 $marked_as_spam = true;
2219 }
2220
2221 return $marked_as_spam;
2222 }
2223
2224 /**
2225 * Remove Files Attached to the Entry of the Form.
2226 *
2227 * @param int $form_id Form ID to get required form data and remove files.
2228 */
2229 public function delete_entry_files_before_form_delete( $form_id ) {
2230 $entries = evf_get_entries_ids( $form_id );
2231 if ( ! empty( $entries ) ) {
2232 foreach ( $entries as $entry_id ) {
2233 $this->delete_entry_files( $entry_id );
2234 }
2235 }
2236 }
2237
2238 /**
2239 * Delete Attachment after removing Entry.
2240 *
2241 * @param int $entry_id Entry ID for which file should be removed.
2242 */
2243 public function delete_entry_files( $entry_id ) {
2244 $get_entry = evf_get_entry( $entry_id, 'meta' );
2245 if ( empty( $get_entry->meta ) ) {
2246 return;
2247 }
2248
2249 // Get form configuration
2250 $form_id = $get_entry->form_id;
2251 $form = evf()->form->get( $form_id, array( 'content_only' => true ) );
2252 $form_fields = isset( $form['form_fields'] ) ? $form['form_fields'] : array();
2253
2254 // Build field type lookup by meta-key
2255 $field_types = array();
2256 foreach ( $form_fields as $field_id => $field_config ) {
2257 if ( isset( $field_config['meta-key'] ) && ! empty( $field_config['meta-key'] ) ) {
2258 $field_types[ $field_config['meta-key'] ] = $field_config['type'];
2259 }
2260 }
2261
2262 $uploads = wp_upload_dir();
2263 $base_dir = realpath( $uploads['basedir'] );
2264 $everest_forms_dir = $base_dir ? realpath( $base_dir . '/everest_forms_uploads' ) : false;
2265
2266 foreach ( $get_entry->meta as $meta_key => $meta_value ) {
2267 if ( empty( $meta_value ) ) {
2268 continue;
2269 }
2270
2271 $field_type = isset( $field_types[ $meta_key ] ) ? $field_types[ $meta_key ] : '';
2272
2273 if ( preg_match( '/signature_/', $meta_key ) || $field_type === 'signature' ) {
2274 $this->safe_delete_file( $meta_value, $base_dir );
2275 } elseif ( 'file-upload' === $field_type || 'image-upload' === $field_type ) {
2276 $files = explode( "\n", $meta_value );
2277 foreach ( $files as $file ) {
2278 $path_from_url = wp_parse_url( $file, PHP_URL_PATH );
2279 if ( ! $path_from_url ) {
2280 continue;
2281 }
2282
2283 $uploaded_file = $uploads['basedir'] . preg_replace(
2284 '/.*uploads/',
2285 '/everest_forms_uploads',
2286 $path_from_url
2287 );
2288
2289 $this->safe_delete_file( $uploaded_file, $base_dir );
2290 }
2291 }
2292 }
2293 }
2294
2295 /**
2296 * Securely delete a file with path validation
2297 *
2298 * @param string $path File path to delete
2299 * @param string $allowed_base Base directory path (must be realpath result)
2300 */
2301 private function safe_delete_file( $path, $allowed_base ) {
2302 if ( ! $allowed_base || empty( $path ) ) {
2303 return;
2304 }
2305 $normalized_path = wp_normalize_path( $path );
2306 $resolved_path = realpath( $normalized_path );
2307 // Validate path is within allowed directory
2308 if ( $resolved_path && strpos( $resolved_path, $allowed_base ) === 0 ) {
2309 if ( is_file( $resolved_path ) ) {
2310 wp_delete_file( $resolved_path );
2311 }
2312 }
2313 }
2314
2315 /**
2316 * @param array $maybe_form_fields
2317 * @param array $post_entry
2318 *
2319 * @since 3.3.0
2320 *
2321 * @return array
2322 */
2323 private function evf_get_entry_data_for_cleantalk( $maybe_form_fields, $post_entry ) {
2324 $entry_data = array(
2325 'sender_nickname' => array(),
2326 'sender_email' => '',
2327 'message' => array(),
2328 );
2329 $list_of_ct_expected_fields = array(
2330 'fullname',
2331 'first-name',
2332 'last-name',
2333 'email',
2334 'text',
2335 'textarea',
2336 );
2337 $list_of_ct_expected_fields = apply_filters( 'evf_cleantalk_expected_fields', $list_of_ct_expected_fields, $maybe_form_fields );
2338 foreach ( $post_entry['form_fields'] as $key => $value ) {
2339 if ( isset( $maybe_form_fields[ $key ]['type'] ) ) {
2340 switch ( $maybe_form_fields[ $key ]['type'] ) {
2341 case 'first-name':
2342 case 'last-name':
2343 case 'fullname':
2344 $entry_data['sender_nickname'][] = isset( $value ) ? $value : '';
2345 break;
2346 case 'email':
2347 empty( $entry_data['sender_email'] ) && $entry_data['sender_email'] = isset( $value ) ? $value : '';
2348 break;
2349 case 'text':
2350 case 'textarea':
2351 $entry_data['message'][] = isset( $value ) ? $value : '';
2352 break;
2353 default:
2354 if ( in_array( $maybe_form_fields[ $key ]['type'], $list_of_ct_expected_fields, true ) ) {
2355 $entry_data['message'][] = isset( $value ) ? $value : '';
2356 }
2357 }
2358 }
2359 }
2360 $entry_data = apply_filters( 'evf_entry_cleantalk_entry_data', $entry_data, $post_entry, $maybe_form_fields );
2361 if ( isset( $entry_data['message'] ) && is_array( $entry_data['message'] ) ) {
2362 $entry_data['message'] = implode( ' ', $entry_data['message'] );
2363 }
2364 if ( isset( $entry_data['sender_nickname'] ) && is_array( $entry_data['sender_nickname'] ) ) {
2365 $entry_data['sender_nickname'] = implode( ' ', $entry_data['sender_nickname'] );
2366 }
2367 return $entry_data;
2368 }
2369 }
2370