PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.6.1
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.6.1
3.6.1 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 3 weeks ago RestApi 3 weeks ago abilities 2 months ago abstracts 1 day ago admin 1 day ago blocks 1 year ago elementor 2 years ago export 4 months ago fields 1 day ago interfaces 8 years ago libraries 3 years ago log-handlers 1 year ago shortcodes 3 weeks ago stats 7 months ago templates 5 months ago traits 2 months ago class-everest-forms.php 1 day ago class-evf-addon-upsell.php 2 months ago class-evf-ajax.php 3 weeks 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 4 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 5 months ago class-evf-emails.php 2 months ago class-evf-fields.php 2 months ago class-evf-form-handler.php 3 weeks ago class-evf-form-task.php 1 day ago class-evf-forms-features.php 2 months ago class-evf-frontend-scripts.php 3 weeks ago class-evf-install.php 4 months ago class-evf-integrations.php 5 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 4 months ago class-evf-reporting.php 4 months ago class-evf-session-handler.php 7 years ago class-evf-shortcodes.php 1 year ago class-evf-smart-tags.php 1 day ago class-evf-template-loader.php 3 weeks ago class-evf-validation.php 6 years ago evf-conditional-functions.php 6 years ago evf-core-functions.php 2 months ago evf-deprecated-functions.php 6 years ago evf-entry-functions.php 6 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
2383 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_raw( $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_raw( $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_raw( $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_raw( $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_raw( $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_raw( $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 // Connections whose attachments still need cleaning up once every notification is sent.
1395 $cleanup_connections = array();
1396
1397 foreach ( $notifications as $connection_id => $notification ) :
1398
1399 // Don't proceed if email notification is not enabled.
1400 if ( isset( $notification['enable_email_notification'] ) && '1' !== $notification['enable_email_notification'] ) {
1401 continue;
1402 }
1403
1404 $process_email = apply_filters( 'everest_forms_entry_email_process', true, $fields, $form_data, $context, $connection_id );
1405
1406 if ( ! $process_email ) {
1407 continue;
1408 }
1409
1410 $email = array();
1411 $evf_to_email = isset( $notification['evf_to_email'] ) ? $notification['evf_to_email'] : '';
1412
1413 // Setup email properties.
1414 /* translators: %s - form name. */
1415 $email['subject'] = ! empty( $notification['evf_email_subject'] ) ? $notification['evf_email_subject'] : sprintf( esc_html__( 'New %s Entry', 'everest-forms' ), $form_data['settings']['form_title'] );
1416 $email['address'] = explode( ',', apply_filters( 'everest_forms_process_smart_tags', $evf_to_email, $form_data, $fields, $this->entry_id ) );
1417 $email['address'] = array_map( 'sanitize_email', $email['address'] );
1418 $email['sender_name'] = ! empty( $notification['evf_from_name'] ) ? $notification['evf_from_name'] : get_bloginfo( 'name' );
1419 $email['sender_address'] = ! empty( $notification['evf_from_email'] ) ? $notification['evf_from_email'] : get_option( 'admin_email' );
1420 $email['reply_to'] = ! empty( $notification['evf_reply_to'] ) ? $notification['evf_reply_to'] : $email['sender_address'];
1421 if ( ! empty( get_option( 'everest_forms_ai_api_key' ) ) ) { // phpcs:ignore
1422 $email['message_ai_prompt'] = ! empty( $notification['evf_email_message_prompt'] ) ? $notification['evf_email_message_prompt'] : '';
1423 $email['enable_ai_prompt'] = ! empty( $notification['enable_ai_email_prompt'] ) ? $notification['enable_ai_email_prompt'] : 0;
1424 }
1425 $email['message'] = ! empty( $notification['evf_email_message'] ) ? evf_string_translation( $form_data['id'], 'evf_email_message', $notification['evf_email_message'] ) : '{all_fields}';
1426 $email = apply_filters( 'everest_forms_entry_email_atts', $email, $fields, $entry, $form_data );
1427 $attachment = '';
1428
1429 // Create new email.
1430 $emails = new EVF_Emails();
1431 $emails->__set( 'form_data', $form_data );
1432 $emails->__set( 'fields', $fields );
1433 $emails->__set( 'entry_id', $entry_id );
1434 $emails->__set( 'from_name', $email['sender_name'] );
1435 $emails->__set( 'from_address', $email['sender_address'] );
1436 $emails->__set( 'reply_to', $email['reply_to'] );
1437
1438 /**
1439 * This filter relies on consistent data being passed for the resultant filters to function.
1440 * The third param passed for the filter, $fields, is derived from validation routine, not the DB.
1441 */
1442 $emails->__set( 'attachments', apply_filters( 'everest_forms_email_file_attachments', $attachment, $fields, $form_data, 'entry-email', $connection_id, $entry_id ) );
1443
1444 // Maybe include Cc and Bcc email addresses.
1445 if ( 'yes' === get_option( 'everest_forms_enable_email_copies' ) ) {
1446 if ( ! empty( $notification['evf_carboncopy'] ) ) {
1447 $emails->__set( 'cc', $notification['evf_carboncopy'] );
1448 }
1449 if ( ! empty( $notification['evf_blindcarboncopy'] ) ) {
1450 $emails->__set( 'bcc', $notification['evf_blindcarboncopy'] );
1451 }
1452 }
1453
1454 $emails = apply_filters( 'everest_forms_entry_email_before_send', $emails );
1455
1456 // Send entry email.
1457 foreach ( $email['address'] as $address ) {
1458 $emails->send( trim( $address ), $email['subject'], $email['message'], '', $connection_id );
1459 }
1460
1461 $cleanup_connections[] = $connection_id;
1462 endforeach;
1463
1464 /*
1465 * Clean up the attachment files only after every notification has been sent.
1466 * Cleaning up inside the loop deletes the uploaded files (when entry storage is
1467 * disabled) and the generated CSV while later notifications are still pending,
1468 * so those notifications go out without their attachments.
1469 */
1470 if ( isset( $attachment ) ) {
1471 foreach ( $cleanup_connections as $cleanup_connection_id ) {
1472 do_action( 'everest_forms_remove_attachments_after_send_email', $attachment, $fields, $form_data, 'entry-email', $cleanup_connection_id, $entry_id );
1473 }
1474 }
1475 }
1476
1477 /**
1478 * Saves entry to database.
1479 *
1480 * @param array $fields List of form fields.
1481 * @param array $entry User submitted data.
1482 * @param int $form_id Form ID.
1483 * @param array $form_data Prepared form settings.
1484 * @return int
1485 */
1486 public function entry_save( $fields, $entry, $form_id, $form_data = array() ) {
1487 global $wpdb;
1488
1489 // Check if form has entries disabled.
1490 if ( isset( $form_data['settings']['disabled_entries'] ) && '1' === $form_data['settings']['disabled_entries'] ) {
1491 return;
1492 }
1493
1494 // Provide the opportunity to override via a filter.
1495 if ( ! apply_filters( 'everest_forms_entry_save', true, $fields, $entry, $form_data ) ) {
1496 return;
1497 }
1498
1499 do_action( 'everest_forms_process_entry_save', $fields, $entry, $form_id, $form_data );
1500
1501 $fields = apply_filters( 'everest_forms_entry_save_data', $fields, $entry, $form_data );
1502 $browser = evf_get_browser();
1503 $user_ip = evf_get_ip_address();
1504 $user_device = evf_get_user_device();
1505 $user_agent = $browser['name'] . '/' . $browser['platform'] . '/' . $user_device;
1506 $referer = ! empty( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
1507 $entry_id = false;
1508 $status = isset( $entry['evf_spam_status'] ) ? $entry['evf_spam_status'] : 'publish';
1509 $admin_approval_entries = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
1510 $settings = isset( $form_data['settings'] ) ? $form_data['settings'] : array();
1511 $evf_form_admin_approval_entries = isset( $settings['enable_admin_approval_entries'] ) ? $settings['enable_admin_approval_entries'] : '0';
1512
1513 if ( 'yes' === $admin_approval_entries && '1' === $evf_form_admin_approval_entries ) {
1514 $status = 'pending';
1515 }
1516
1517 // GDPR enhancements - If user details are disabled globally discard the IP and UA.
1518 if ( 'yes' === get_option( 'everest_forms_disable_user_details' ) ) {
1519 $user_agent = '';
1520 $user_ip = '';
1521 }
1522
1523 $entry_data = apply_filters(
1524 'everest_forms_entry_data',
1525 array(
1526 'form_id' => $form_id,
1527 'user_id' => get_current_user_id(),
1528 'user_device' => sanitize_text_field( $user_agent ),
1529 'user_ip_address' => sanitize_text_field( $user_ip ),
1530 'status' => $status,
1531 'referer' => $referer,
1532 'fields' => wp_json_encode( $fields ),
1533 'date_created' => current_time( 'mysql', true ),
1534 ),
1535 $entry
1536 );
1537
1538 if ( ! $entry_data['form_id'] ) {
1539 return new WP_Error( 'no-form-id', __( 'No form ID was found.', 'everest-forms' ) );
1540 }
1541
1542 // Create entry.
1543 $success = $wpdb->insert( $wpdb->prefix . 'evf_entries', $entry_data );
1544
1545 if ( is_wp_error( $success ) || ! $success ) {
1546 return new WP_Error( 'could-not-create', __( 'Could not create an entry', 'everest-forms' ) );
1547 }
1548
1549 $entry_id = $wpdb->insert_id;
1550
1551 // Create meta data.
1552 if ( $entry_id ) {
1553 foreach ( $fields as $field ) {
1554 $field = apply_filters( 'everest_forms_entry_save_fields', $field, $form_data, $entry_id );
1555 // Add only whitelisted fields to entry meta.
1556 if ( in_array( $field['type'], array( 'html', 'title' ), true ) ) {
1557 continue;
1558 }
1559
1560 // If empty file is supplied, don't store their data nor send email.
1561 if ( in_array( $field['type'], array( 'image-upload', 'file-upload' ), true ) ) {
1562
1563 // BW compatibility for previous file uploader.
1564 if ( isset( $field['value']['file_url'] ) && '' === $field['value']['file_url'] ) {
1565 continue;
1566 }
1567 }
1568
1569 // If empty label is provided for choice field, don't store their data nor send email.
1570 if ( in_array( $field['type'], array( 'radio', 'payment-multiple' ), true ) ) {
1571 if ( isset( $field['value']['label'] ) && '' === $field['value']['label'] ) {
1572 continue;
1573 }
1574 } elseif ( in_array( $field['type'], array( 'checkbox', 'payment-checkbox' ), true ) ) {
1575 if ( isset( $field['value']['label'] ) && ( empty( $field['value']['label'] ) || '' === current( $field['value']['label'] ) ) ) {
1576 continue;
1577 }
1578 }
1579
1580 if ( isset( $field['meta_key'], $field['value'] ) && '' !== $field['value'] ) {
1581 if ( ! empty( $field['value'] ) && is_string( $field['value'] ) && strpos( $field['value'], '{' ) !== false ) {
1582 $field['value'] = apply_filters( 'everest_forms_process_smart_tags', $field['value'], $form_data, $fields, $entry_id );
1583 }
1584 $entry_metadata = array(
1585 'entry_id' => $entry_id,
1586 'meta_key' => sanitize_key( $field['meta_key'] ),
1587 'meta_value' => maybe_serialize( $field['value'] ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
1588 );
1589
1590 // Insert entry meta.
1591 $wpdb->insert( $wpdb->prefix . 'evf_entrymeta', $entry_metadata );
1592 }
1593 }
1594 }
1595
1596 $this->entry_id = $entry_id;
1597
1598 // Removing Entries Cache.
1599 wp_cache_delete( $entry_id, 'evf-entry' );
1600 wp_cache_delete( $entry_id, 'evf-entrymeta' );
1601 wp_cache_delete( $form_id, 'evf-entries-ids' );
1602 wp_cache_delete( $form_id, 'evf-last-entries-count' );
1603 wp_cache_delete( $form_id, 'evf-search-entries' );
1604 wp_cache_delete( EVF_Cache_Helper::get_cache_prefix( 'entries' ) . '_unread_count', 'entries' );
1605
1606 do_action( 'everest_forms_complete_entry_save', $entry_id, $fields, $entry, $form_id, $form_data );
1607
1608 return $this->entry_id;
1609 }
1610
1611 /**
1612 * Insert or update the slot booking data.
1613 *
1614 * @param int $entry_id Entry id.
1615 * @param array $fields List of form fields.
1616 * @param array $entry User submitted data.
1617 * @param int $form_id Form ID.
1618 * @param array $form_data Prepared form settings.
1619 */
1620 public function update_slot_booking_value( $entry_id, $fields, $entry, $form_id, $form_data ) {
1621 $new_slot_booking_field_meta_key_list = array();
1622 $time_interval = 0;
1623 foreach ( $form_data['form_fields'] as $field ) {
1624 if ( ( 'date-time' === $field['type'] ) && isset( $field['slot_booking_advanced'] ) && evf_string_to_bool( $field['slot_booking_advanced'] ) ) {
1625 $new_slot_booking_field_meta_key_list[ $field['meta-key'] ] = array(
1626 $field['datetime_format'],
1627 $field['date_format'],
1628 $field['date_mode'],
1629 );
1630 $time_interval = $field['time_interval'];
1631 }
1632 }
1633
1634 foreach ( $fields as $key => $value ) {
1635 if ( array_key_exists( $value['meta_key'], $new_slot_booking_field_meta_key_list ) ) {
1636 $new_value = $value['value'];
1637 $datetime_format = $new_slot_booking_field_meta_key_list[ $value['meta_key'] ][0];
1638 $date_format = $new_slot_booking_field_meta_key_list[ $value['meta_key'] ][1];
1639 $mode = $new_slot_booking_field_meta_key_list[ $value['meta_key'] ][2];
1640 $datetime_arr = parse_datetime_values( $new_value, $datetime_format, $date_format, $mode, $time_interval, $entry_id );
1641 }
1642 }
1643 if ( ! empty( $datetime_arr ) ) {
1644 $get_booked_slot = get_option( 'evf_booked_slot', array() );
1645 $new_booked_slot = array( $form_id => $datetime_arr );
1646
1647 if ( empty( $get_booked_slot ) ) {
1648 $all_booked_slot = maybe_serialize( $new_booked_slot );
1649 } else {
1650 $unserialized_booked_slot = evf_maybe_unserialize( $get_booked_slot );
1651
1652 if ( array_key_exists( $form_id, $unserialized_booked_slot ) ) {
1653 $booked_slot = $unserialized_booked_slot[ $form_id ];
1654 $booked_slot = (array) $booked_slot + $datetime_arr;
1655 $new_booked_slot = array( $form_id => $booked_slot );
1656 }
1657
1658 $all_booked_slot = maybe_serialize( array_replace( $unserialized_booked_slot, $new_booked_slot ) );
1659 }
1660
1661 update_option( 'evf_booked_slot', $all_booked_slot );
1662 }
1663 }
1664
1665 /**
1666 * Load Previous Field Value.
1667 *
1668 * @param string $properties Value.
1669 * @param mixed $field Field.
1670 * @param mixed $form_data Form Data.
1671 * @return $properties Properties.
1672 */
1673 public function load_previous_field_value( $properties, $field, $form_data ) {
1674
1675 if ( ! isset( $_POST['everest_forms'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1676 return $properties;
1677 }
1678 $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
1679
1680 if ( 'checkbox' === $field['type'] ) {
1681 foreach ( $field['choices'] as $key => $option_value ) {
1682 $selected = ! empty( $option_value['default'] ) ? $option_value['default'] : '';
1683 foreach ( $data as $value ) {
1684 if ( $value === $option_value['label'] ) {
1685 $selected = 1;
1686 $properties['inputs'][ $key ]['default'] = $selected;
1687 }
1688 }
1689 }
1690 } elseif ( 'radio' === $field['type'] || 'select' === $field['type'] ) {
1691 foreach ( $field['choices'] as $key => $option_value ) {
1692 if ( $data === $option_value['label'] ) { // phpcs:ignore WordPress.Security.NonceVerification
1693 $selected = 1;
1694 $properties['inputs'][ $key ]['default'] = $selected;
1695 }
1696 }
1697 } elseif ( 'likert' === $field['type'] ) {
1698 if ( count( $data ) ) {
1699 foreach ( $data as $row => $col ) {
1700 foreach ( (array) $col as $col_selected ) {
1701 $index = sprintf( 'rows%d_columns%d', (int) $row, (int) $col_selected );
1702 $properties['inputs'][ $index ]['attr']['checked'] = true;
1703 }
1704 }
1705 }
1706 } elseif ( ! is_array( $data ) ) {
1707 $properties['inputs']['primary']['attr']['value'] = esc_attr( $data );
1708 }
1709 return $properties;
1710 }
1711
1712 /**
1713 * Check if a form entry should be validated by Akismet for potential spam.
1714 *
1715 * This function checks whether the Akismet plugin is installed and configured, and if the Akismet
1716 * validation option is enabled for a specific form. If validation is enabled, it prepares the
1717 * necessary data for the validation request and sends it to Akismet's 'comment-check' endpoint.
1718 *
1719 * @param array $entry The form entry data to validate.
1720 * @param string $form_id (Optional) The identifier of the form.
1721 *
1722 * @return bool
1723 * - true if the form entry is potentially spam according to Akismet.
1724 * - false if Akismet validation is not enabled, the plugin is not properly configured, or the entry is not considered spam.
1725 */
1726 public function get_akismet_validate( $entry, $form_id = '' ) {
1727
1728 if ( ! file_exists( WP_PLUGIN_DIR . '/akismet/akismet.php' ) ) {
1729 return false;
1730 }
1731
1732 if ( ! evf_is_akismet_configured() ) {
1733 return false;
1734 }
1735
1736 if ( isset( $this->form_data['settings']['akismet'] ) && '1' === $this->form_data['settings']['akismet'] ) {
1737 $entry_data = $this->get_entry_data_for_akismet( $this->form_data['form_fields'], $entry );
1738
1739 $entry_data = apply_filters( 'evf_entry_akismet_entry_data', $entry_data, $entry, $this->form_data );
1740
1741 $request = array(
1742 'blog' => get_option( 'home' ),
1743 'user_ip' => evf_get_ip_address(),
1744 'user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) : null, // phpcs:ignore
1745 'referrer' => wp_get_referer() ? wp_get_referer() : null,
1746 'permalink' => evf_current_url(),
1747 'comment_type' => 'contact-form',
1748 'comment_author' => isset( $entry_data['name'] ) ? $entry_data['name'] : '',
1749 'comment_author_email' => isset( $entry_data['email'] ) ? $entry_data['email'] : '',
1750 'comment_author_url' => isset( $entry_data['url'] ) ? $entry_data['url'] : '',
1751 'comment_content' => isset( $entry_data['content'] ) ? $entry_data['content'] : '',
1752 'blog_lang' => get_locale(),
1753 'blog_charset' => get_bloginfo( 'charset' ),
1754 'honypot_field_name' => 'everest_forms[hp]',
1755 );
1756
1757 $request = apply_filters( 'evf_akismet_request_data', $request, $this->form_data, $entry, $form_id );
1758
1759 $response = Akismet::http_post( build_query( $request ), 'comment-check' );
1760
1761 return ! empty( $response ) && isset( $response[1] ) && 'true' === trim( $response[1] );
1762 }
1763
1764 return false;
1765 }
1766
1767 /**
1768 * Check if a form entry should be validated by CleanTalk for potential spam.
1769 *
1770 * @since 3.2.2
1771 *
1772 * @param [type] $entry The form entry data to validate.
1773 * @param string $form_id (Optional) The identifier of the form.
1774 */
1775 public function get_clean_talk_validate( $entry, $form_id = '' ) {
1776
1777 $is_cleantalk_activated = isset( $this->form_data['settings']['cleantalk'] ) ? $this->form_data['settings']['cleantalk'] : false;
1778
1779 if ( ! $is_cleantalk_activated ) {
1780 return false;
1781 }
1782
1783 $mark_as_spam = false;
1784 $logger = evf_get_logger();
1785
1786 $access_key = get_option( 'everest_forms_recaptcha_cleantalk_access_key', '' );
1787
1788 if ( empty( $access_key ) ) {
1789 $logger->notice( 'Missing the CleanTalk Access Key', array( 'source' => 'cleantalk' ) );
1790
1791 return false;
1792 }
1793
1794 return $this->evf_is_spam_submission_clean_talk_rest_api( $entry, $access_key );
1795 }
1796
1797 /**
1798 * Get the list of field types that are allowed to be sent to Akismet.
1799 *
1800 * @since 1.7.6
1801 *
1802 * @return array List of field types that are allowed to be sent to Akismet
1803 */
1804 private function get_field_type_allowlist_for_akisment() {
1805
1806 $field_type_allowlist = array(
1807 'first-name',
1808 'last-name',
1809 'text',
1810 'textarea',
1811 'email',
1812 'phone',
1813 'address',
1814 'url',
1815 'wysiwyg',
1816 );
1817
1818 /**
1819 * Filters the field types that are allowed to be sent to Akismet.
1820 *
1821 * @since 2.4.0
1822 *
1823 * @param array $field_type_allowlist Field types allowed to be sent to Akismet.
1824 */
1825 return (array) apply_filters( 'evf_forms_akismet_get_field_type_allowlist', $field_type_allowlist );
1826 }
1827
1828 /**
1829 * Get the entry data to be sent to Akismet.
1830 *
1831 * @since 2.4.0
1832 *
1833 * @param array $fields Field data for the current form.
1834 * @param array $entry Entry data for the current entry.
1835 *
1836 * @return array $entry_data Entry data to be sent to Akismet.
1837 */
1838 private function get_entry_data_for_akismet( $fields, $entry ) {
1839 $field_type_allowlist = $this->get_field_type_allowlist_for_akisment();
1840 $entry_data = array();
1841 $entry_content = array();
1842
1843 foreach ( $fields as $key => $field ) {
1844 $field_type = $field['type'];
1845
1846 if ( ! in_array( $field_type, $field_type_allowlist, true ) ) {
1847 continue;
1848 }
1849 if ( ! isset( $entry['form_fields'][ $key ] ) ) {
1850 continue;
1851 }
1852 $field_content = is_array( $entry['form_fields'][ $key ] ) ? implode( ' ', $entry['form_fields'][ $key ] ) : $entry['form_fields'][ $key ];
1853
1854 if ( ! isset( $entry_data[ $field_type ] ) && in_array( $field_type, array( 'first-name', 'last-name', 'email', 'url' ), true ) ) {
1855 if ( 'first-name' === $field_type ) {
1856 $entry_data['name'] = isset( $entry_data['name'] ) ? "$field_content " . $entry_data['name'] : $field_content;
1857 continue;
1858 } elseif ( 'last-name' === $field_type ) {
1859 $entry_data['name'] = isset( $entry_data['name'] ) ? $entry_data['name'] . " $field_content" : $field_content;
1860 continue;
1861 }
1862 $entry_data[ $field_type ] = $field_content;
1863 continue;
1864 }
1865
1866 $entry_content[] = $field_content;
1867 }
1868
1869 $entry_data['content'] = implode( ' ', $entry_content );
1870
1871 return $entry_data;
1872 }
1873
1874 /**
1875 * Verify the token and approve the entry if the token matches.
1876 *
1877 * @since 2.0.9
1878 */
1879 public static function evf_admin_approve_entry() {
1880 if ( ! isset( $_GET['evf_admin_approval_entry_token'] ) || empty( $_GET['evf_admin_approval_entry_token'] ) ) {
1881 return;
1882 }
1883
1884 if ( current_user_can( 'edit_users' ) ) {
1885 global $wpdb;
1886 $evf_admin_approve_entry_token_raw = sanitize_text_field( wp_unslash( $_GET['evf_admin_approval_entry_token'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1887
1888 $evf_admin_approval_entry_enable = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
1889 $evf_admin_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1890 $evf_admin_entry_id = isset( $_GET['entry_id'] ) ? absint( $_GET['entry_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1891 $evf_entry_redirect_url = admin_url() . 'admin.php?page=evf-entries&form_id=' . $evf_admin_form_id . '&view-entry=' . $evf_admin_entry_id;
1892 $evf_admin_entry_saved_token = get_option( 'everest_forms_admin_entry_approval_token', array() );
1893 $site_name = get_option( 'blogname' );
1894
1895 if ( 'yes' === $evf_admin_approval_entry_enable ) {
1896 $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
1897 if ( in_array( $evf_admin_approve_entry_token_raw, $evf_admin_entry_saved_token ) ) {
1898 $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 ) );
1899 $entry = evf_get_entry( $evf_admin_entry_id );
1900 $entry_meta = $entry->meta;
1901 $first_name = '';
1902 $last_name = '';
1903 $email = '';
1904 $entry_date = $entry->date_created;
1905 $name = '';
1906
1907 foreach ( $entry_meta as $key => $value ) {
1908 if ( preg_match( '/^name/', $key ) ) {
1909 $name = $value;
1910 }
1911
1912 if ( preg_match( '/^first_name_/', $key ) ) {
1913 $first_name = $value;
1914 }
1915
1916 if ( preg_match( '/^last_name_/', $key ) ) {
1917 $last_name = $value;
1918 }
1919
1920 if ( preg_match( '/^email/', $key ) ) {
1921 $email = $value;
1922 }
1923
1924 if ( '' === $name ) {
1925 if ( ! empty( $first_name ) && ! empty( $last_name ) ) {
1926 $name = $first_name . ' ' . $last_name;
1927 } elseif ( ! empty( $first_name ) ) {
1928 $name = $first_name;
1929 } else {
1930 $name = $last_name;
1931 }
1932 }
1933
1934 $subject = apply_filters( 'everest_forms_entry_submission_approval_subject', esc_html__( 'Form Entry Approved', 'everest-forms' ) );
1935 // translators: %s is the name of the user
1936 $message = sprintf( __( 'Hey, %s', 'everest-forms' ), $name ) . '<br/>';
1937 // translators: %s is the entry_date.
1938 $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/>';
1939 $message .= '<br/>' . __( 'Thank you for giving us your precious time.', 'everest-forms' ) . '<br/>';
1940 // translators: %s is the site_name.
1941 $message .= '<br/>' . sprintf( __( 'From %s', 'everest-forms' ), $site_name );
1942 // translators: %s is the message.
1943 $message = apply_filters( 'everest_forms_entry_approval_message', $message, $name, $entry_date, $site_name );
1944 }
1945
1946 $email_obj = new EVF_Emails();
1947 $test = $email_obj->send( $email, $subject, $message );
1948 wp_redirect( $evf_entry_redirect_url );
1949 }
1950 }
1951 }
1952 }
1953
1954 /**
1955 * Verify the token and deny the entry if the token matches.
1956 *
1957 * @since 2.0.9
1958 */
1959 public static function evf_admin_deny_entry() {
1960 if ( ! isset( $_GET['evf_admin_denial_entry_token'] ) || empty( $_GET['evf_admin_denial_entry_token'] ) ) {
1961 return;
1962 }
1963
1964 if ( current_user_can( 'edit_users' ) ) {
1965 global $wpdb;
1966
1967 $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
1968 $evf_admin_approval_entry_enable = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
1969 $evf_admin_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1970 $evf_admin_entry_id = isset( $_GET['entry_id'] ) ? absint( $_GET['entry_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1971 $evf_entry_redirect_url = admin_url() . 'admin.php?page=evf-entries&form_id=' . $evf_admin_form_id . '&view-entry=' . $evf_admin_entry_id;
1972 $evf_admin_entry_saved_token = get_option( 'everest_forms_admin_entry_approval_token', array() );
1973 $site_name = get_option( 'blogname' );
1974
1975 if ( 'yes' === $evf_admin_approval_entry_enable ) {
1976
1977 $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
1978 if ( in_array( $evf_admin_approve_entry_token_raw, $evf_admin_entry_saved_token ) ) {
1979 $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 ) );
1980 $entry = evf_get_entry( $evf_admin_entry_id );
1981 $entry_meta = $entry->meta;
1982 $entry_date = $entry->date_created;
1983 $first_name = '';
1984 $last_name = '';
1985 $email = '';
1986 $name = '';
1987
1988 foreach ( $entry_meta as $key => $value ) {
1989 if ( preg_match( '/^name/', $key ) ) {
1990 $name = $value;
1991 }
1992
1993 if ( preg_match( '/^first_name_/', $key ) ) {
1994 $first_name = $value;
1995 }
1996
1997 if ( preg_match( '/^last_name_/', $key ) ) {
1998 $last_name = $value;
1999 }
2000
2001 if ( preg_match( '/^email/', $key ) ) {
2002 $email = $value;
2003 }
2004
2005 if ( '' === $name ) {
2006 if ( ! empty( $first_name ) && ! empty( $last_name ) ) {
2007 $name = $first_name . ' ' . $last_name;
2008 } elseif ( ! empty( $first_name ) ) {
2009 $name = $first_name;
2010 } else {
2011 $name = $last_name;
2012 }
2013 }
2014
2015 $subject = apply_filters( 'everest_forms_entry_submission_approval_subject', esc_html__( 'Entry Submission Denied', 'everest-forms' ) );
2016 // translators: %s is the name of the user
2017 $message = sprintf( __( 'Hey, %s', 'everest-forms' ), $name ) . '<br/>';
2018 // translators: %s is the entry_date.
2019 $message .= '<br/>' . sprintf( __( 'We’re sorry to inform you that your form entry submitted on %s has been denied.', 'everest-forms' ), $entry_date ) . '<br/>';
2020 $message .= '<br/>' . __( 'Thank you for giving us your precious time.', 'everest-forms' ) . '<br/>';
2021 // translators: %s is the site_name.
2022 $message .= '<br/>' . sprintf( __( 'From %s', 'everest-forms' ), $site_name );
2023 // translators: %s is the message.
2024 $message = apply_filters( 'everest_forms_entry_denial_message', $message, $name, $entry_date, $site_name );
2025
2026 }
2027 $email_obj = new EVF_Emails();
2028 $email_obj->send( $email, $subject, $message );
2029 wp_redirect( $evf_entry_redirect_url );
2030 }
2031 }
2032 }
2033 }
2034
2035 /**
2036 * Set the entry approval token of the entry and update it to the options table in database.
2037 *
2038 * @param int $entry_id Entry ID.
2039 * @param array $form_data Form field data.
2040 *
2041 * @since 2.0.9
2042 */
2043 public function evf_set_approval_status( $entry_id, $form_data ) {
2044 $evf_admin_approval_token_list = array();
2045 $form_id = isset( $form_data['id'] ) ? $form_id['id'] : '';
2046 $evf_admin_entry_enable = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
2047 $evf_admin_entry_approval_token = get_option( 'everest_forms_admin_entry_approval_token', array() );
2048 $evf_approval_key = 'approval_token_' . $entry_id;
2049
2050 // Checks if admin approval entry is enabled.
2051 if ( ! isset( $evf_admin_entry_enable ) ) {
2052 return;
2053 } else {
2054 $token = evf_get_random_string( 20 );
2055 $evf_approval_token = array(
2056 $evf_approval_key => $token,
2057 );
2058 $evf_new_token = array_merge( $evf_admin_entry_approval_token, $evf_approval_token );
2059 update_option( 'everest_forms_admin_entry_approval_token', $evf_new_token );
2060 }
2061 }
2062
2063 /**
2064 * Prevents form submission before the specified duration.
2065 *
2066 * @param array $errors Form submit errors.
2067 * @param object $form_data An object containing settings for the form.
2068 */
2069 public function form_submission_waiting_time( $errors, $form_data ) {
2070 $form_submission_waiting_time_enable = isset( $form_data['settings']['form_submission_min_waiting_time'] ) ? $form_data['settings']['form_submission_min_waiting_time'] : '';
2071 $submission_duration = isset( $form_data['settings']['form_submission_min_waiting_time_input'] ) ? $form_data['settings']['form_submission_min_waiting_time_input'] : '';
2072
2073 if ( isset( $form_submission_waiting_time_enable ) && '1' === $form_submission_waiting_time_enable && 0 <= absint( $submission_duration ) ) {
2074 $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
2075 $atts = $form_data['id'];
2076 $submission_time = time() * 1000;
2077
2078 if ( $submission_duration <= 0 ) {
2079 $submission_duration = 1;
2080 }
2081 $waiting_time = absint( $submission_time ) - absint( $evf_submission_start_time );
2082 $form_id = ! empty( $form_data['id'] ) ? $form_data['id'] : 0;
2083
2084 if ( absint( $submission_time ) - absint( $evf_submission_start_time ) <= absint( $submission_duration ) * 1000 ) {
2085 /**
2086 * Filter to modify the waiting time message content.
2087 *
2088 * @since 3.0.2
2089 */
2090 $form_submission_err_msg = apply_filters(
2091 'everest_forms_minimum_waiting_time_form_submission',
2092 sprintf(
2093 "%s <span id='evf_submission_duration' data-duration='%s'>%s</span> %s",
2094 esc_html__( 'Please wait', 'everest-forms' ),
2095 $submission_duration,
2096 $submission_duration,
2097 esc_html__( 'seconds, security checkup is being executed.', 'everest-forms' )
2098 )
2099 );
2100
2101 $errors[ $form_id ]['header'] = $form_submission_err_msg;
2102 }
2103
2104 return $errors;
2105 }
2106 }
2107
2108 /**
2109 * Marks the entry as spam.
2110 *
2111 * @since 3.0.9
2112 */
2113 public function evf_mark_entry_spam() {
2114 if ( ! isset( $_GET['spam-entry'] ) ) {
2115 return;
2116 }
2117
2118 // Verify nonce for security
2119 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'spam-entry' ) ) {
2120 wp_die( esc_html__( 'Security check failed. Please try again.', 'everest-forms' ) );
2121 }
2122
2123 if ( current_user_can( 'edit_users' ) ) {
2124 global $wpdb;
2125
2126 $evf_admin_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0;
2127 $evf_admin_entry_id = isset( $_GET['spam-entry'] ) ? absint( $_GET['spam-entry'] ) : 0;
2128 $evf_entry_redirect_url = admin_url() . 'admin.php?page=evf-entries&form_id=' . $evf_admin_form_id . '&view-entry=' . $evf_admin_entry_id;
2129
2130 $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}evf_entries SET status = %s WHERE entry_id = %s ", 'spam', $evf_admin_entry_id ) );
2131 wp_redirect( $evf_entry_redirect_url );
2132 }
2133 }
2134
2135 /**
2136 * Marks the entry as spam.
2137 *
2138 * @since 3.0.9
2139 */
2140 public function evf_remove_entry_from_spam() {
2141 if ( ! isset( $_GET['unspam-entry'] ) ) {
2142 return;
2143 }
2144
2145 // Verify nonce for security
2146 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'unspam-entry' ) ) {
2147 wp_die( esc_html__( 'Security check failed. Please try again.', 'everest-forms' ) );
2148 }
2149
2150 if ( current_user_can( 'edit_users' ) ) {
2151 global $wpdb;
2152
2153 $evf_admin_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0;
2154 $evf_admin_entry_id = isset( $_GET['unspam-entry'] ) ? absint( $_GET['unspam-entry'] ) : 0;
2155 $evf_entry_redirect_url = admin_url() . 'admin.php?page=evf-entries&form_id=' . $evf_admin_form_id . '&view-entry=' . $evf_admin_entry_id;
2156
2157 $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}evf_entries SET status = %s WHERE entry_id = %s ", 'publish', $evf_admin_entry_id ) );
2158 wp_redirect( $evf_entry_redirect_url );
2159 }
2160 }
2161
2162 /**
2163 * Check if the submission is spam using CleanTalk REST API.
2164 *
2165 * @since 3.2.2
2166 */
2167 public function evf_is_spam_submission_clean_talk_rest_api( $entry, $access_key ) {
2168 $marked_as_spam = false;
2169
2170 $submit_time = isset( $this->form_data['entry']['evf_form_load_time'] ) ? time() - (int) $this->form_data['entry']['evf_form_load_time'] : null;
2171 $event_token = isset( $this->form_data['entry']['evf_event_token'] ) ? $this->form_data['entry']['evf_event_token'] : null;
2172
2173 $entry_data = $this->evf_get_entry_data_for_cleantalk( $this->form_data['form_fields'], $entry );
2174
2175 $all_headers = null;
2176
2177 if ( function_exists( 'apache_request_headers' ) ) {
2178 $all_headers = array_filter(
2179 apache_request_headers(),
2180 function ( $value, $key ) {
2181 return strtolower( $key ) !== 'cookie';
2182 },
2183 ARRAY_FILTER_USE_BOTH
2184 );
2185 $all_headers = json_encode( $all_headers );
2186 $all_headers = false !== $all_headers ? $all_headers : null;
2187 }
2188
2189 $clean_talk_request = array(
2190 'method_name' => 'check_message',
2191 'all_headers' => $all_headers,
2192 'auth_key' => $access_key,
2193 'sender_ip' => $_SERVER['REMOTE_ADDR'],
2194 'sender_info' => json_encode(
2195 array(
2196 'REFERRER' => $_SERVER['HTTP_REFERER'],
2197 'USER_AGENT' => htmlspecialchars( @$_SERVER['HTTP_USER_AGENT'] ),
2198 )
2199 ),
2200 'js_on' => 1,
2201 'submit_time' => $submit_time,
2202 'event_token' => $event_token,
2203 'sender_nickname' => isset( $entry_data['sender_nickname'] ) ? $entry_data['sender_nickname'] : '',
2204 'sender_email' => isset( $entry_data['sender_email'] ) ? $entry_data['sender_email'] : '',
2205 'message' => isset( $entry_data['message'] ) ? $entry_data['message'] : '',
2206 'agent' => 'wordpress-everest-forms-' . EVF_VERSION,
2207 'post_info' => array(
2208 'comment_type' => 'everest_forms_vendor_integration__use_api',
2209 'post_url' => $_SERVER['HTTP_REFERER'],
2210 ),
2211 );
2212
2213 $raw_response = wp_remote_post(
2214 'https://moderate.cleantalk.org/api2.0',
2215 array(
2216 'body' => json_encode( $clean_talk_request ),
2217 'headers' => array(
2218 'Content-Type' => 'application/json',
2219 ),
2220 )
2221 );
2222 $response = json_decode( wp_remote_retrieve_body( $raw_response ) );
2223
2224 if ( empty( $response ) ) {
2225 return true;
2226 }
2227
2228 $clean_talk_passed = $response->allow == 1 && $response->spam == 0 && $response->account_status == 1;
2229
2230 if ( ! $clean_talk_passed ) {
2231 $marked_as_spam = true;
2232 }
2233
2234 return $marked_as_spam;
2235 }
2236
2237 /**
2238 * Remove Files Attached to the Entry of the Form.
2239 *
2240 * @param int $form_id Form ID to get required form data and remove files.
2241 */
2242 public function delete_entry_files_before_form_delete( $form_id ) {
2243 $entries = evf_get_entries_ids( $form_id );
2244 if ( ! empty( $entries ) ) {
2245 foreach ( $entries as $entry_id ) {
2246 $this->delete_entry_files( $entry_id );
2247 }
2248 }
2249 }
2250
2251 /**
2252 * Delete Attachment after removing Entry.
2253 *
2254 * @param int $entry_id Entry ID for which file should be removed.
2255 */
2256 public function delete_entry_files( $entry_id ) {
2257 $get_entry = evf_get_entry( $entry_id, 'meta' );
2258 if ( empty( $get_entry->meta ) ) {
2259 return;
2260 }
2261
2262 // Get form configuration
2263 $form_id = $get_entry->form_id;
2264 $form = evf()->form->get( $form_id, array( 'content_only' => true ) );
2265 $form_fields = isset( $form['form_fields'] ) ? $form['form_fields'] : array();
2266
2267 // Build field type lookup by meta-key
2268 $field_types = array();
2269 foreach ( $form_fields as $field_id => $field_config ) {
2270 if ( isset( $field_config['meta-key'] ) && ! empty( $field_config['meta-key'] ) ) {
2271 $field_types[ $field_config['meta-key'] ] = $field_config['type'];
2272 }
2273 }
2274
2275 $uploads = wp_upload_dir();
2276 $base_dir = realpath( $uploads['basedir'] );
2277 $everest_forms_dir = $base_dir ? realpath( $base_dir . '/everest_forms_uploads' ) : false;
2278
2279 foreach ( $get_entry->meta as $meta_key => $meta_value ) {
2280 if ( empty( $meta_value ) ) {
2281 continue;
2282 }
2283
2284 $field_type = isset( $field_types[ $meta_key ] ) ? $field_types[ $meta_key ] : '';
2285
2286 if ( preg_match( '/signature_/', $meta_key ) || $field_type === 'signature' ) {
2287 $this->safe_delete_file( $meta_value, $base_dir );
2288 } elseif ( 'file-upload' === $field_type || 'image-upload' === $field_type ) {
2289 $files = explode( "\n", $meta_value );
2290 foreach ( $files as $file ) {
2291 $path_from_url = wp_parse_url( $file, PHP_URL_PATH );
2292 if ( ! $path_from_url ) {
2293 continue;
2294 }
2295
2296 $uploaded_file = $uploads['basedir'] . preg_replace(
2297 '/.*uploads/',
2298 '/everest_forms_uploads',
2299 $path_from_url
2300 );
2301
2302 $this->safe_delete_file( $uploaded_file, $base_dir );
2303 }
2304 }
2305 }
2306 }
2307
2308 /**
2309 * Securely delete a file with path validation
2310 *
2311 * @param string $path File path to delete
2312 * @param string $allowed_base Base directory path (must be realpath result)
2313 */
2314 private function safe_delete_file( $path, $allowed_base ) {
2315 if ( ! $allowed_base || empty( $path ) ) {
2316 return;
2317 }
2318 $normalized_path = wp_normalize_path( $path );
2319 $resolved_path = realpath( $normalized_path );
2320 // Validate path is within allowed directory
2321 if ( $resolved_path && strpos( $resolved_path, $allowed_base ) === 0 ) {
2322 if ( is_file( $resolved_path ) ) {
2323 wp_delete_file( $resolved_path );
2324 }
2325 }
2326 }
2327
2328 /**
2329 * @param array $maybe_form_fields
2330 * @param array $post_entry
2331 *
2332 * @since 3.3.0
2333 *
2334 * @return array
2335 */
2336 private function evf_get_entry_data_for_cleantalk( $maybe_form_fields, $post_entry ) {
2337 $entry_data = array(
2338 'sender_nickname' => array(),
2339 'sender_email' => '',
2340 'message' => array(),
2341 );
2342 $list_of_ct_expected_fields = array(
2343 'fullname',
2344 'first-name',
2345 'last-name',
2346 'email',
2347 'text',
2348 'textarea',
2349 );
2350 $list_of_ct_expected_fields = apply_filters( 'evf_cleantalk_expected_fields', $list_of_ct_expected_fields, $maybe_form_fields );
2351 foreach ( $post_entry['form_fields'] as $key => $value ) {
2352 if ( isset( $maybe_form_fields[ $key ]['type'] ) ) {
2353 switch ( $maybe_form_fields[ $key ]['type'] ) {
2354 case 'first-name':
2355 case 'last-name':
2356 case 'fullname':
2357 $entry_data['sender_nickname'][] = isset( $value ) ? $value : '';
2358 break;
2359 case 'email':
2360 empty( $entry_data['sender_email'] ) && $entry_data['sender_email'] = isset( $value ) ? $value : '';
2361 break;
2362 case 'text':
2363 case 'textarea':
2364 $entry_data['message'][] = isset( $value ) ? $value : '';
2365 break;
2366 default:
2367 if ( in_array( $maybe_form_fields[ $key ]['type'], $list_of_ct_expected_fields, true ) ) {
2368 $entry_data['message'][] = isset( $value ) ? $value : '';
2369 }
2370 }
2371 }
2372 }
2373 $entry_data = apply_filters( 'evf_entry_cleantalk_entry_data', $entry_data, $post_entry, $maybe_form_fields );
2374 if ( isset( $entry_data['message'] ) && is_array( $entry_data['message'] ) ) {
2375 $entry_data['message'] = implode( ' ', $entry_data['message'] );
2376 }
2377 if ( isset( $entry_data['sender_nickname'] ) && is_array( $entry_data['sender_nickname'] ) ) {
2378 $entry_data['sender_nickname'] = implode( ' ', $entry_data['sender_nickname'] );
2379 }
2380 return $entry_data;
2381 }
2382 }
2383