PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.0.6
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.0.6
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
RestApi 1 year ago abstracts 1 year ago admin 1 year ago blocks 1 year ago elementor 2 years ago export 1 year ago fields 1 year ago interfaces 8 years ago libraries 3 years ago log-handlers 4 years ago shortcodes 1 year ago stats 3 years ago templates 5 years ago class-everest-forms.php 1 year ago class-evf-ajax.php 1 year 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 6 years 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-emails.php 1 year ago class-evf-fields.php 2 years ago class-evf-form-handler.php 2 years ago class-evf-form-task.php 1 year ago class-evf-forms-features.php 2 years ago class-evf-frontend-scripts.php 1 year ago class-evf-install.php 2 years ago class-evf-integrations.php 2 years ago class-evf-log-levels.php 8 years ago class-evf-logger.php 5 years ago class-evf-post-types.php 5 years ago class-evf-privacy.php 6 years ago class-evf-report-cron.php 2 years ago class-evf-reporting.php 2 years ago class-evf-session-handler.php 7 years ago class-evf-shortcodes.php 4 years ago class-evf-smart-tags.php 1 year ago class-evf-template-loader.php 2 years ago class-evf-validation.php 6 years ago evf-conditional-functions.php 6 years ago evf-core-functions.php 1 year ago evf-deprecated-functions.php 6 years ago evf-entry-functions.php 2 years 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
1494 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 /**
12 * EVF_Form_Task class.
13 */
14 class EVF_Form_Task {
15
16 /**
17 * Holds errors.
18 *
19 * @since 1.0.0
20 * @var array
21 */
22 public $errors;
23
24 /**
25 * Holds formatted fields.
26 *
27 * @since 1.0.0
28 * @var array
29 */
30 public $form_fields;
31
32 /**
33 * Holds the ID of a successful entry.
34 *
35 * @since 1.0.0
36 * @var int
37 */
38 public $entry_id = 0;
39
40 /**
41 * Form data and settings.
42 *
43 * @since 1.5.0
44 *
45 * @var array
46 */
47 public $form_data = array();
48
49 /**
50 * Is hash validation?
51 *
52 * @var 1.7.4
53 */
54 public $is_valid_hash = false;
55
56 /**
57 * Primary class constructor.
58 *
59 * @since 1.0.0
60 */
61 public function __construct() {
62 add_action( 'wp', array( $this, 'listen_task' ) );
63 add_filter( 'everest_forms_field_properties', array( $this, 'load_previous_field_value' ), 99, 3 );
64 add_action( 'everest_forms_complete_entry_save', array( $this, 'update_slot_booking_value' ), 10, 5 );
65 add_action( 'everest_forms_complete_entry_save', array( $this, 'evf_set_approval_status' ), 10, 2 );
66 add_action( 'admin_init', array( $this, 'evf_admin_approve_entry' ), 10, 2 );
67 add_action( 'admin_init', array( $this, 'evf_admin_deny_entry' ) );
68 }
69
70 /**
71 * Listen to see if this is a return callback or a posted form entry.
72 *
73 * @since 1.0.0
74 */
75 public function listen_task() {
76 if ( ! empty( $_GET['everest_forms_return'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
77 $this->entry_confirmation_redirect( '', sanitize_text_field( wp_unslash( $_GET['everest_forms_return'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
78 }
79
80 $form_id = ! empty( $_POST['everest_forms']['id'] ) ? absint( $_POST['everest_forms']['id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
81
82 if ( ! $form_id ) {
83 return;
84 }
85
86 if ( ! empty( $_POST['everest_forms']['id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
87 $this->do_task( evf_sanitize_entry( wp_unslash( $_POST['everest_forms'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
88 }
89
90 if ( ! evf_is_amp() ) {
91 return;
92 }
93
94 $settings = $this->form_data['settings'];
95 $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' );
96 // Send 400 Bad Request when there are errors.
97 if ( empty( $this->errors[ $form_id ] ) ) {
98 wp_send_json(
99 array(
100 'message' => $success_message,
101 ),
102 200
103 );
104
105 return;
106 }
107 $message = $this->errors[ $form_id ]['header'];
108
109 if ( ! empty( $this->errors[ $form_id ]['footer'] ) ) {
110 $message .= ' ' . $this->errors[ $form_id ]['footer'];
111 }
112
113 wp_send_json(
114 array(
115 'message' => $message,
116 ),
117 400
118 );
119 }
120
121 /**
122 * Do task of form entry
123 *
124 * @since 1.0.0
125 * @param array $entry $_POST object.
126 */
127 public function do_task( $entry ) {
128 $logger = evf_get_logger();
129 try {
130 $this->errors = array();
131 $this->form_fields = array();
132 $form_id = absint( $entry['id'] );
133 $form = evf()->form->get( $form_id );
134 $honeypot = false;
135 $response_data = array();
136 $this->ajax_err = array();
137 $this->evf_notice_print = false;
138 $logger = evf_get_logger();
139
140 // Check nonce for form submission.
141 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
142 $this->errors[ $form_id ]['header'] = esc_html__( 'We were unable to process your form, please try again.', 'everest-forms' );
143 $logger->error(
144 $this->errors[ $form_id ]['header'],
145 array( 'source' => 'form-submission' )
146 );
147 return $this->errors;
148 }
149
150 // Validate form is real and active (published).
151 if ( ! $form || 'publish' !== $form->post_status ) {
152 $this->errors[ $form_id ]['header'] = esc_html__( 'Invalid form. Please check again.', 'everest-forms' );
153 $logger->error(
154 $this->errors[ $form_id ]['header'],
155 array( 'source' => 'form-submission' )
156 );
157 return $this->errors;
158 }
159
160 // Check if the form is enabled or not.
161 $form_enabled = evf_decode( $form->post_content );
162 if ( isset( $form_enabled['form_enabled'] ) && ! $form_enabled['form_enabled'] ) {
163 $this->errors[ $form_id ]['header'] = esc_html__( 'This form is disabled.', 'everest-forms' );
164 $logger->error(
165 $this->errors[ $form_id ]['header'],
166 array( 'source' => 'form-submission' )
167 );
168 return $this->errors;
169 }
170
171 // Formatted form data for hooks.
172 $this->form_data = apply_filters( 'everest_forms_process_before_form_data', evf_decode( $form->post_content ), $entry );
173
174 // Pre-process/validate hooks and filter. Data is not validated or cleaned yet so use with caution.
175 $entry = apply_filters( 'everest_forms_process_before_filter', $entry, $this->form_data );
176 $this->form_data['page_id'] = array_key_exists( 'post_id', $entry ) ? $entry['post_id'] : $form_id;
177
178 $logger->info(
179 __( 'Everest Forms Process Before.', 'everest-forms' ),
180 array( 'source' => 'form-submission' )
181 );
182 do_action( 'everest_forms_process_before', $entry, $this->form_data );
183 $logger->info(
184 __( 'Everest Forms Process Before Form ID.', 'everest-forms' ),
185 array( 'source' => 'form-submission' )
186 );
187 do_action( "everest_forms_process_before_{$form_id}", $entry, $this->form_data );
188
189 $ajax_form_submission = isset( $this->form_data['settings']['ajax_form_submission'] ) ? $this->form_data['settings']['ajax_form_submission'] : 0;
190 if ( ( isset( $this->form_data['payments']['stripe']['enable_stripe'] ) && '1' === $this->form_data['payments']['stripe']['enable_stripe'] ) || ( isset( $this->form_data['payments']['square']['enable_square'] ) && '1' === $this->form_data['payments']['square']['enable_square'] ) ) {
191 $ajax_form_submission = '1';
192 }
193 if ( '1' === $ajax_form_submission ) {
194 // For the sake of validation we completely remove the validator option.
195 update_option( 'evf_validation_error', '' );
196
197 // Prepare fields for entry_save.
198 foreach ( $this->form_data['form_fields'] as $field ) {
199 if ( '' === isset( $this->form_data['form_fields']['meta-key'] ) ) {
200 continue;
201 }
202
203 $field_id = $field['id'];
204 $field_type = $field['type'];
205 $field_submit = isset( $entry['form_fields'][ $field_id ] ) ? $entry['form_fields'][ $field_id ] : '';
206
207 if ( 'signature' === $field_type ) {
208 $field_submit = isset( $field_submit['signature_image'] ) ? $field_submit['signature_image'] : '';
209 }
210
211 $exclude = array( 'title', 'html', 'captcha', 'image-upload', 'file-upload', 'divider', 'reset', 'recaptcha', 'hcaptcha', 'turnstile' );
212
213 if ( ! in_array( $field_type, $exclude, true ) ) {
214
215 $this->form_fields[ $field_id ] = array(
216 'id' => $field_id,
217 'name' => sanitize_text_field( $field['label'] ),
218 'meta_key' => $this->form_data['form_fields'][ $field_id ]['meta-key'],
219 'type' => $field_type,
220 'value' => evf_sanitize_textarea_field( $field_submit ),
221 );
222 }
223 }
224 }
225
226 $this->form_data['entry'] = $entry;
227
228 // Validate fields.
229 foreach ( $this->form_data['form_fields'] as $field ) {
230 $field_id = $field['id'];
231 $field_type = $field['type'];
232 $repeater_fields = array_key_exists( 'repeater-fields', $field ) ? $field['repeater-fields'] : 'no';
233
234 $field_submit = isset( $entry['form_fields'][ $field_id ] ) ? $entry['form_fields'][ $field_id ] : '';
235
236 if ( 'no' === $repeater_fields || 'repeater-fields' === $field_type ) {
237 $logger->info(
238 "Everest Forms Process Before validate {$field_type}.",
239 array( 'source' => 'form-submission' )
240 );
241 do_action( "everest_forms_process_validate_{$field_type}", $field_id, $field_submit, $this->form_data, $field_type );
242 }
243
244 if ( 'credit-card' === $field_type && isset( $_POST['everest_form_stripe_payment_intent_id'] ) ) {
245 $this->evf_notice_print = true;
246 }
247
248 if ( 'yes' === get_option( 'evf_validation_error' ) && $ajax_form_submission ) {
249 if ( count( $this->errors ) ) {
250 foreach ( $this->errors as $_error ) {
251 $this->ajax_err [] = $_error;
252 }
253 }
254 update_option( 'evf_validation_error', '' );
255 }
256 }
257
258 // If validation issues occur, send the results accordingly.
259 if ( $ajax_form_submission && count( $this->ajax_err ) ) {
260 $response_data['error'] = $this->ajax_err;
261 $response_data['message'] = __( 'Form has not been submitted, please see the errors below.', 'everest-forms' );
262 $response_data['response'] = 'error';
263 $logger->error(
264 __( 'Form has not been submitted.', 'everest-forms' ),
265 array( 'source' => 'form-submission' )
266 );
267 return $response_data;
268 }
269
270 // reCAPTCHA check.
271 if ( ! apply_filters( 'everest_forms_recaptcha_disabled', false ) ) {
272 $recaptcha_type = get_option( 'everest_forms_recaptcha_type', 'v2' );
273 $invisible_recaptcha = get_option( 'everest_forms_recaptcha_v2_invisible', 'no' );
274
275 if ( 'v2' === $recaptcha_type && 'no' === $invisible_recaptcha ) {
276 $site_key = get_option( 'everest_forms_recaptcha_v2_site_key' );
277 $secret_key = get_option( 'everest_forms_recaptcha_v2_secret_key' );
278 } elseif ( 'v2' === $recaptcha_type && 'yes' === $invisible_recaptcha ) {
279 $site_key = get_option( 'everest_forms_recaptcha_v2_invisible_site_key' );
280 $secret_key = get_option( 'everest_forms_recaptcha_v2_invisible_secret_key' );
281 } elseif ( 'v3' === $recaptcha_type ) {
282 $site_key = get_option( 'everest_forms_recaptcha_v3_site_key' );
283 $secret_key = get_option( 'everest_forms_recaptcha_v3_secret_key' );
284 } elseif ( 'hcaptcha' === $recaptcha_type ) {
285 $site_key = get_option( 'everest_forms_recaptcha_hcaptcha_site_key' );
286 $secret_key = get_option( 'everest_forms_recaptcha_hcaptcha_secret_key' );
287 } elseif ( 'turnstile' === $recaptcha_type ) {
288 $site_key = get_option( 'everest_forms_recaptcha_turnstile_site_key' );
289 $secret_key = get_option( 'everest_forms_recaptcha_turnstile_secret_key' );
290 $theme_mode = get_option( 'everest_forms_recaptcha_turnstile_theme' );
291 }
292 $recaptcha_verified = false;
293 foreach ( (array) $this->form_data['form_fields'] as $field ) {
294 $field_type = isset( $field['type'] ) ? $field['type'] : '';
295 $captcha = array( 'recaptcha', 'hcaptcha', 'turnstile' );
296 if ( ! empty( $site_key ) && ! empty( $secret_key ) && isset( $this->form_data['settings']['recaptcha_support'] ) && '1' === $this->form_data['settings']['recaptcha_support'] &&
297 ! isset( $_POST['__amp_form_verify'] ) && ( 'v3' === $recaptcha_type || ! evf_is_amp() ) || ( ! empty( $site_key ) && ! empty( $secret_key ) ) && in_array( $field_type, $captcha, true ) ) {
298
299 if ( 'hcaptcha' === $recaptcha_type ) {
300 $error = esc_html__( 'hCaptcha verification failed, please try again later.', 'everest-forms' );
301 } elseif ( 'turnstile' === $recaptcha_type ) {
302 $error = esc_html__( 'Cloudflare Turnstile verification failed, please try again later.', 'everest-forms' );
303 } else {
304 $error = esc_html__( 'Google reCAPTCHA verification failed, please try again later.', 'everest-forms' );
305 }
306
307 $logger->error(
308 $error,
309 array( 'source' => 'Google reCAPTCHA' )
310 );
311
312 $token = ! empty( $_POST['g-recaptcha-response'] ) ? evf_clean( wp_unslash( $_POST['g-recaptcha-response'] ) ) : false;
313
314 if ( 'v3' === $recaptcha_type ) {
315 $token = ! empty( $_POST['everest_forms']['recaptcha'] ) ? evf_clean( wp_unslash( $_POST['everest_forms']['recaptcha'] ) ) : false;
316 }
317 if ( 'hcaptcha' === $recaptcha_type ) {
318 $token = ! empty( $_POST['h-captcha-response'] ) ? evf_clean( wp_unslash( $_POST['h-captcha-response'] ) ) : false;
319 $raw_response = wp_safe_remote_get( 'https://hcaptcha.com/siteverify?secret=' . $secret_key . '&response=' . $token );
320 } elseif ( 'turnstile' === $recaptcha_type ) {
321 $token = ! empty( $_POST['cf-turnstile-response'] ) ? evf_clean( wp_unslash( $_POST['cf-turnstile-response'] ) ) : false;
322 $url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
323 $params = array(
324 'method' => 'POST',
325 'body' => array(
326 'secret' => $secret_key,
327 'response' => $token,
328 ),
329 );
330 $raw_response = wp_safe_remote_post( $url, $params );
331 } else {
332 $raw_response = wp_safe_remote_get( 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secret_key . '&response=' . $token );
333 }
334
335 if ( ! is_wp_error( $raw_response ) ) {
336 $response = json_decode( wp_remote_retrieve_body( $raw_response ) );
337 // Check reCAPTCHA response.
338 if ( empty( $response->success ) || ( 'v3' === $recaptcha_type && $response->score <= get_option( 'everest_forms_recaptcha_v3_threshold_score', apply_filters( 'everest_forms_recaptcha_v3_threshold', '0.5' ) ) ) ) {
339 if ( 'v3' === $recaptcha_type ) {
340 if ( isset( $response->score ) ) {
341 $error .= ' (' . esc_html( $response->score ) . ')';
342 }
343 }
344 $this->errors[ $form_id ]['header'] = $error;
345 $logger->error(
346 $error,
347 array( 'source' => 'Google reCAPTCHA' )
348 );
349 return $this->errors;
350 }
351 }
352
353 $recaptcha_verified = true;
354 break;
355 }
356 }
357 }
358 // Initial error check.
359 $errors = apply_filters( 'everest_forms_process_initial_errors', $this->errors, $this->form_data );
360
361 // Minimum time to submit check.
362 $min_submit_time = $this->form_submission_waiting_time( $this->errors, $this->form_data );
363 if ( isset( $min_submit_time[ $form_id ]['header'] ) && ! empty( $min_submit_time ) ) {
364 $this->errors[ $form_id ]['header'] = $min_submit_time[ $form_id ]['header'];
365 $logger->error(
366 $min_submit_time[ $form_id ]['header'],
367 array( 'source' => 'Minimum time to submit' )
368 );
369 return $this->errors;
370 }
371
372 if ( isset( $_POST['__amp_form_verify'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
373 if ( empty( $errors[ $form_id ] ) ) {
374 wp_send_json( array(), 200 );
375 } else {
376 $verify_errors = array();
377
378 foreach ( $errors[ $form_id ] as $field_id => $error_fields ) {
379 $field = $this->form_data['fields'][ $field_id ];
380 $field_properties = EVF_Shortcode_Form::get_field_properties( $field, $this->form_data );
381
382 if ( is_string( $error_fields ) ) {
383
384 if ( 'checkbox' === $field['type'] || 'radio' === $field['type'] || 'select' === $field['type'] ) {
385 $first = current( $field_properties['inputs'] );
386 $name = $first['attr']['name'];
387 } elseif ( isset( $field_properties['inputs']['primary']['attr']['name'] ) ) {
388 $name = $field_properties['inputs']['primary']['attr']['name'];
389 }
390
391 $verify_errors[] = array(
392 'name' => $name,
393 'message' => $error_fields,
394 );
395 } else {
396 foreach ( $error_fields as $error_field => $error_message ) {
397
398 if ( isset( $field_properties['inputs'][ $error_field ]['attr']['name'] ) ) {
399 $name = $field_properties['inputs'][ $error_field ]['attr']['name'];
400 }
401
402 $verify_errors[] = array(
403 'name' => $name,
404 'message' => $error_message,
405 );
406 }
407 }
408 }
409
410 wp_send_json(
411 array(
412 'verifyErrors' => $verify_errors,
413 ),
414 400
415 );
416 }
417 return;
418 }
419 if ( ! empty( $errors[ $form_id ] ) ) {
420 if ( empty( $errors[ $form_id ]['header'] ) ) {
421 $errors[ $form_id ]['header'] = __( 'Form has not been submitted, please see the errors below.', 'everest-forms' );
422 $logger->error(
423 $errors[ $form_id ]['header'],
424 array( 'source' => 'form-submission' )
425 );
426 }
427 $this->errors = $errors;
428 return $this->errors;
429 }
430
431 // Early honeypot validation - before actual processing.
432 if ( isset( $this->form_data['settings']['honeypot'] ) && '1' === $this->form_data['settings']['honeypot'] && ! empty( $entry['hp'] ) ) {
433 $honeypot = esc_html__( 'Everest Forms honeypot field triggered.', 'everest-forms' );
434 }
435
436 $honeypot = apply_filters( 'everest_forms_process_honeypot', $honeypot, $this->form_fields, $entry, $this->form_data );
437
438 // If spam - return early.
439 if ( $honeypot ) {
440 $logger = evf_get_logger();
441 $logger->notice( sprintf( 'Spam entry for Form ID %d Response: %s', absint( $this->form_data['id'] ), evf_print_r( $entry, true ) ), array( 'source' => 'honeypot' ) );
442 return $this->errors;
443 }
444
445 /** Akismet anit-spam protection.
446 * If spam - return early
447 *
448 * @since 2.4.0
449 */
450 if ( $this->get_akismet_validate( $entry, $form_id ) ) {
451 $logger = evf_get_logger();
452 $logger->notice( sprintf( 'Spam entry for Form ID %d Response: %s', absint( $this->form_data['id'] ), evf_print_r( $entry, true ) ), array( 'source' => 'akismet' ) );
453
454 if ( isset( $this->form_data['settings']['akismet_protection_type'] ) && 'validation_failed' === $this->form_data['settings']['akismet_protection_type'] ) {
455
456 $akismet_message = apply_filters( 'evf_akisment_validatation_error_message', sprintf( 'Akismet anti-spam verification failed, please try again later.', 'everest-forms' ) );
457 $errors[ $form_id ]['header'] = $akismet_message;
458 $this->errors = $errors;
459
460 return $this->errors;
461 }
462 $entry['evf_spam_status'] = 'spam';
463 }
464 // Pass the form created date into the form data.
465 $this->form_data['created'] = $form->post_date;
466
467 // Format and Sanitize inputs.
468 foreach ( (array) $this->form_data['form_fields'] as $field ) {
469 $field_id = $field['id'];
470 $field_key = isset( $field['meta-key'] ) ? $field['meta-key'] : '';
471 $field_type = $field['type'];
472 $field_submit = isset( $entry['form_fields'][ $field_id ] ) ? $entry['form_fields'][ $field_id ] : '';
473 $repeater_fields = array_key_exists( 'repeater-fields', $field ) ? $field['repeater-fields'] : 'no';
474
475 if ( 'no' === $repeater_fields || 'repeater-fields' === $field_type ) {
476 $logger->info(
477 sprintf( 'Everest Forms Process Format %s.', $field_type ),
478 array( 'source' => 'form-submission' )
479 );
480 do_action( "everest_forms_process_format_{$field_type}", $field_id, $field_submit, $this->form_data, $field_key );
481 }
482 }
483
484 // This hook is for internal purposes and should not be leveraged.
485 $logger->info(
486 'Everest Forms Process Format After.',
487 array( 'source' => 'form-submission' )
488 );
489 do_action( 'everest_forms_process_format_after', $this->form_data );
490
491 // Process hooks/filter - this is where most addons should hook
492 // because at this point we have completed all field validation and
493 // formatted the data.
494 $this->form_fields = apply_filters( 'everest_forms_process_filter', $this->form_fields, $entry, $this->form_data );
495 $logger->notice( sprintf( 'Everest Form Process: %s', evf_print_r( $this->form_fields, true ) ) );
496
497 $logger->info(
498 'Everest Forms Process.',
499 array( 'source' => 'form-submission' )
500 );
501 do_action( 'everest_forms_process', $this->form_fields, $entry, $this->form_data );
502 $logger->info(
503 "Everest Forms Process {$form_id}.",
504 array( 'source' => 'form-submission' )
505 );
506 do_action( "everest_forms_process_{$form_id}", $this->form_fields, $entry, $this->form_data );
507
508 $this->form_fields = apply_filters( 'everest_forms_process_after_filter', $this->form_fields, $entry, $this->form_data );
509 $logger->notice( sprintf( 'Everest Form Process After: %s', evf_print_r( $this->form_fields, true ) ) );
510
511 // One last error check - don't proceed if there are any errors.
512 if ( ! empty( $this->errors[ $form_id ] ) ) {
513 if ( empty( $this->errors[ $form_id ]['header'] ) ) {
514 $this->errors[ $form_id ]['header'] = esc_html__( 'Form has not been submitted, please see the errors below.', 'everest-forms' );
515 }
516 $logger->error(
517 __( 'Form has not been submitted', 'everest-forms' ),
518 array( 'source' => 'form-submission' )
519 );
520 return $this->errors;
521 }
522
523 $logger->notice( sprintf( 'Entry is Saving to DataBase' ) );
524 // Success - add entry to database.
525 $logger->info(
526 __( 'Entry Added to Database.', 'everest-forms' ),
527 array( 'source' => 'form-submission' )
528 );
529 $entry_id = $this->entry_save( $this->form_fields, $entry, $this->form_data['id'], $this->form_data );
530 $logger->notice( sprintf( 'Entry is Saved to DataBase' ) );
531
532 $logger->notice( sprintf( 'Sending Email' ) );
533 // Success - send email notification.
534 $logger->info(
535 __( 'Sent Email Notification.', 'everest-forms' ),
536 array( 'source' => 'form-submission' )
537 );
538 $this->entry_email( $this->form_fields, $entry, $this->form_data, $entry_id, 'entry' );
539 $logger->notice( sprintf( 'Successfully Send the email' ) );
540
541 // @todo remove this way of printing notices.
542 add_filter( 'everest_forms_success', array( $this, 'check_success_message' ), 10, 2 );
543
544 // Pass completed and formatted fields in POST.
545 $_POST['everest-forms']['complete'] = $this->form_fields;
546
547 // Pass entry ID in POST.
548 $_POST['everest-forms']['entry_id'] = $entry_id;
549
550 // Post-process hooks.
551 $logger->info(
552 __( 'Everest Forms Process Completed.', 'everest-forms' ),
553 array( 'source' => 'form-submission' )
554 );
555 do_action( 'everest_forms_process_complete', $this->form_fields, $entry, $this->form_data, $entry_id );
556 $logger->info(
557 "Everest Forms Process Completed {$form_id}.",
558 array( 'source' => 'form-submission' )
559 );
560 do_action( "everest_forms_process_complete_{$form_id}", $this->form_fields, $entry, $this->form_data, $entry_id );
561 } catch ( Exception $e ) {
562 evf_add_notice( $e->getMessage(), 'error' );
563 $logger->error(
564 $e->getMessage(),
565 array( 'source' => 'form-submission' )
566 );
567 if ( '1' === $ajax_form_submission ) {
568 $this->errors[] = $e->getMessage();
569 $response_data['message'] = $this->errors;
570 $response_data['response'] = 'error';
571 return $response_data;
572 }
573 }
574
575 $settings = $this->form_data['settings'];
576 $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' );
577 $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'] );
578 $pdf_submission = $is_pdf_submission_enabled ? $settings['pdf_submission'] : '';
579
580 $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'] );
581 $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' );
582 $should_allow_pdf_download = $is_pdf_submission_enabled ? $is_pdf_download_after_submit : $is_global_pdf_download_enabled;
583
584 $is_preview_confirmation = isset( $this->form_data['settings']['preview_confirmation'] ) ? $this->form_data['settings']['preview_confirmation'] : 0;
585
586 // show preview of form after submission.
587 if ( '1' === $is_preview_confirmation ) {
588 $preview_style = isset( $this->form_data['settings']['preview_confirmation_select'] ) ? $this->form_data['settings']['preview_confirmation_select'] : 'basic';
589 if ( '1' === $ajax_form_submission ) {
590 $response_data['is_preview_confirmation'] = $is_preview_confirmation;
591 $response_data['preview_confirmation'] = apply_filters( 'everest_forms_preview_confirmation', $this->form_data, $this->form_fields, $preview_style );
592 } else {
593 do_action( 'everest_forms_preview_confirmation', $this->form_data, $this->form_fields, $preview_style );
594 }
595 }
596
597 if ( defined( 'EVF_PDF_SUBMISSION_VERSION' ) && $should_allow_pdf_download ) {
598 global $__everest_form_id;
599 global $__everest_form_entry_id;
600 $__everest_form_id = $form_id;
601 $__everest_form_entry_id = $entry_id;
602 }
603
604 // Check Conditional Logic and get the redirection URL.
605 $submission_redirection_process = apply_filters( 'everest_forms_submission_redirection_process', array(), $this->form_fields, $this->form_data );
606
607 // Backward compatibility for evf form templates.
608 $this->form_data['settings']['redirect_to'] = '0' === $this->form_data['settings']['redirect_to'] ? 'same' : $this->form_data['settings']['redirect_to'];
609
610 if ( '1' === $ajax_form_submission ) {
611 $response_data['message'] = $message;
612 $response_data['response'] = 'success';
613 $response_data['form_id'] = $form_id;
614 $response_data['entry_id'] = $entry_id;
615
616 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'] ) ) ) {
617 $response_data['pdf_download'] = true;
618 $pdf_download_message = get_option( 'everest_forms_pdf_custom_download_text', '' );
619
620 if ( isset( $pdf_submission['everest_forms_pdf_custom_download_text'] ) ) {
621 $pdf_download_message = $pdf_submission['everest_forms_pdf_custom_download_text'];
622 }
623
624 if ( empty( $pdf_download_message ) ) {
625 $pdf_download_message = __( 'Download your form submission in PDF format', 'everest-forms' );
626 }
627 $response_data['pdf_download_message'] = $pdf_download_message;
628 }
629
630 // Backward Compatibility Check.
631 switch ( $settings['redirect_to'] ) {
632 case '0':
633 $settings['redirect_to'] = 'same';
634 break;
635
636 case '1':
637 $settings['redirect_to'] = 'custom_page';
638 break;
639
640 case '2':
641 $settings['redirect_to'] = 'external_url';
642 break;
643 }
644
645 // Check for Submission Redirection in Ajax Submission.
646 if ( empty( $submission_redirection_process ) ) {
647 if ( isset( $settings['redirect_to'] ) && 'external_url' === $settings['redirect_to'] ) {
648 $response_data['redirect_url'] = isset( $settings['external_url'] ) ? esc_url( $settings['external_url'] ) : 'undefined';
649 } elseif ( isset( $settings['redirect_to'] ) && 'custom_page' === $settings['redirect_to'] ) {
650 $response_data['redirect_url'] = isset( $settings['custom_page'] ) ? get_page_link( absint( $settings['custom_page'] ) ) : 'undefined';
651 }
652 } else {
653 $response_data['redirect_url'] = $submission_redirection_process['external_url'];
654 }
655
656 // Add notice only if credit card is populated in form fields.
657 if ( isset( $this->evf_notice_print ) && $this->evf_notice_print ) {
658 evf_add_notice( $message, 'success' );
659 }
660 // $this->entry_confirmation_redirect( $this->form_data );
661 $response_data = apply_filters( 'everest_forms_after_success_ajax_message', $response_data, $this->form_data, $entry );
662 return $response_data;
663 } elseif ( ( 'same' === $this->form_data['settings']['redirect_to'] && empty( $submission_redirection_process ) ) || ( ! empty( $submission_redirection_process ) && 'same_page' == $submission_redirection_process['redirect_to'] ) ) {
664 evf_add_notice( $message, 'success' );
665 }
666 $logger->info(
667 'Everest Forms After success Message.',
668 array( 'source' => 'form-submission' )
669 );
670
671 do_action( 'everest_forms_after_success_message', $this->form_data, $entry );
672 delete_option( 'everest_forms_overall_feedback_is_called' );
673 $this->entry_confirmation_redirect( $this->form_data );
674 }
675
676 /**
677 * Process AJAX form submission.
678 *
679 * @since 1.6.0
680 *
681 * @param mixed $posted_data Posted data.
682 */
683 public function ajax_form_submission( $posted_data ) {
684 add_filter( 'wp_redirect', array( $this, 'ajax_process_redirect' ), 999 );
685 $process = $this->do_task( $posted_data );
686 return $process;
687 }
688
689 /**
690 * Process AJAX redirect.
691 *
692 * @since 1.6.0
693 *
694 * @param string $url Redirect URL.
695 */
696 public function ajax_process_redirect( $url ) {
697 $form_id = isset( $_POST['everest_forms']['id'] ) ? absint( $_POST['everest_forms']['id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
698
699 if ( empty( $form_id ) ) {
700 wp_send_json_error();
701 }
702
703 $response = array(
704 'form_id' => $form_id,
705 'redirect_url' => $url,
706 );
707
708 $response = apply_filters( 'everest_forms_ajax_submit_redirect', $response, $form_id, $url );
709
710 do_action( 'everest_forms_ajax_submit_completed', $form_id, $response );
711 wp_send_json_success( $response );
712 }
713
714 /**
715 * Check the sucessful message.
716 *
717 * @param bool $status Message status.
718 * @param int $form_id Form ID.
719 */
720 public function check_success_message( $status, $form_id ) {
721 if ( isset( $this->form_data['id'] ) && absint( $this->form_data['id'] ) === $form_id ) {
722 return true;
723 }
724 return false;
725 }
726
727 /**
728 * Validate the form return hash.
729 *
730 * @since 1.0.0
731 *
732 * @param string $hash Base64-encoded hash of form and entry IDs.
733 * @return array|false False for invalid or form id.
734 */
735 public function validate_return_hash( $hash = '' ) {
736 $query_args = base64_decode( $hash );
737
738 parse_str( $query_args, $output );
739
740 // Verify hash matches.
741 if ( wp_hash( $output['form_id'] . ',' . $output['entry_id'] ) !== $output['hash'] ) {
742 return false;
743 }
744
745 // Get lead and verify it is attached to the form we received with it.
746 $entry = evf_get_entry( $output['entry_id'] );
747
748 if ( empty( $entry->form_id ) ) {
749 return false;
750 }
751
752 if ( $output['form_id'] !== $entry->form_id ) {
753 return false;
754 }
755
756 return array(
757 'form_id' => absint( $output['form_id'] ),
758 'entry_id' => absint( $output['form_id'] ),
759 'fields' => null !== $entry && isset( $entry->fields ) ? $entry->fields : array(),
760 );
761 }
762
763 /**
764 * Redirects user to a page or URL specified in the form confirmation settings.
765 *
766 * @since 1.0.0
767 *
768 * @param array $form_data Form data and settings.
769 * @param string $hash Base64-encoded hash of form and entry IDs.
770 */
771 public function entry_confirmation_redirect( $form_data = '', $hash = '' ) {
772 $_POST = array(); // Clear fields after successful form submission.
773
774 // Process return hash.
775 if ( ! empty( $hash ) ) {
776 $hash_data = $this->validate_return_hash( $hash );
777
778 if ( ! $hash_data || ! is_array( $hash_data ) ) {
779 return;
780 }
781
782 $this->is_valid_hash = true;
783 $this->entry_id = absint( $hash_data['entry_id'] );
784 $this->form_fields = json_decode( $hash_data['fields'], true );
785 $this->form_data = evf()->form->get(
786 absint( $hash_data['form_id'] ),
787 array(
788 'content_only' => true,
789 )
790 );
791 } else {
792 $this->form_data = $form_data;
793 }
794
795 $settings = $this->form_data['settings'];
796
797 // Backward Compatibility Check.
798 switch ( $settings['redirect_to'] ) {
799 case '0':
800 $settings['redirect_to'] = 'same';
801 break;
802
803 case '1':
804 $settings['redirect_to'] = 'custom_page';
805 break;
806
807 case '2':
808 $settings['redirect_to'] = 'external_url';
809 break;
810 }
811
812 $submission_redirect_process = apply_filters( 'everest_forms_submission_redirection_process', array(), $this->form_fields, $this->form_data );
813
814 if ( ! empty( $submission_redirect_process ) ) {
815 $settings['redirect_to'] = $submission_redirect_process['redirect_to'];
816 $settings['external_url'] = $submission_redirect_process['external_url'];
817 $settings['custom_page'] = $submission_redirect_process['custom_page'];
818 }
819
820 if ( isset( $settings['redirect_to'] ) && 'custom_page' === $settings['redirect_to'] ) {
821 if ( isset( $settings['enable_redirect_query_string'] ) && '1' === $settings['enable_redirect_query_string'] ) {
822 parse_str( $settings['query_string'], $output );
823 $query_redirect_url = array();
824 foreach ( $output as $key => $value ) {
825 $query_redirect_url[ $key ] = apply_filters( 'everest_forms_process_smart_tags', $value, $this->form_data, $this->form_fields );
826 }
827 $redirect_url = add_query_arg( $query_redirect_url, esc_url( get_page_link( $settings['custom_page'] ) ) );
828 } else {
829 $redirect_url = get_page_link( $settings['custom_page'] );
830 }
831
832 ?>
833 <script>
834 var redirect = '<?php echo esc_url_raw( $redirect_url ); ?>';
835 window.setTimeout( function () {
836 window.location.href = redirect;
837 })
838 </script>
839 <?php
840 } elseif ( isset( $settings['redirect_to'] ) && 'external_url' === $settings['redirect_to'] ) {
841 ?>
842 <script>
843 window.setTimeout( function () {
844 window.location.href = '<?php echo esc_url( $settings['external_url'] ); ?>';
845 })
846 </script>
847 <?php
848 }
849
850 // Redirect if needed, to either a page or URL, after form processing.
851 if ( ! empty( $this->form_data['settings']['confirmation_type'] ) && 'message' !== $this->form_data['settings']['confirmation_type'] ) {
852 if ( 'redirect' === $this->form_data['settings']['confirmation_type'] ) {
853 $url = apply_filters( 'everest_forms_process_smart_tags', $this->form_data['settings']['confirmation_redirect'], $this->form_data, $this->form_fields, $this->entry_id );
854 }
855
856 if ( 'page' === $this->form_data['settings']['confirmation_type'] ) {
857 $url = get_permalink( (int) $this->form_data['settings']['confirmation_page'] );
858 }
859 }
860
861 if ( ! empty( $this->form_data['id'] ) ) {
862 $form_id = $this->form_data['id'];
863 } else {
864 return;
865 }
866 if ( isset( $settings['submission_message_scroll'] ) && $settings['submission_message_scroll'] ) {
867 add_filter( 'everest_forms_success_notice_class', array( $this, 'add_scroll_notice_class' ) );
868 }
869
870 if ( ! empty( $url ) ) {
871 $url = apply_filters( 'everest_forms_process_redirect_url', $url, $form_id, $this->form_fields );
872 wp_safe_redirect( esc_url_raw( $url ) );
873 do_action( 'everest_forms_process_redirect', $form_id );
874 do_action( "everest_forms_process_redirect_{$form_id}", $form_id );
875 exit;
876 }
877 }
878
879 /**
880 * Add scroll notice class.
881 *
882 * @param array $classes Notice Classes.
883 * @return array of notice classes.
884 */
885 public function add_scroll_notice_class( $classes ) {
886 $classes[] = 'everest-forms-submission-scroll';
887
888 return $classes;
889 }
890
891 /**
892 * Sends entry email notifications.
893 *
894 * @param array $fields List of fields.
895 * @param array $entry Submitted form entry.
896 * @param array $form_data Form data and settings.
897 * @param int $entry_id Saved entry id.
898 * @param string $context In which context this email is sent.
899 */
900 public function entry_email( $fields, $entry, $form_data, $entry_id, $context = '' ) {
901 // Provide the opportunity to override via a filter.
902 if ( ! apply_filters( 'everest_forms_entry_email', true, $fields, $entry, $form_data ) ) {
903 return;
904 }
905
906 // Make sure we have an entry id.
907 if ( empty( $this->entry_id ) ) {
908 $this->entry_id = (int) $entry_id;
909 }
910
911 $fields = apply_filters( 'everest_forms_entry_email_data', $fields, $entry, $form_data );
912
913 if ( ! isset( $form_data['settings']['email']['connection_1'] ) ) {
914 $old_email_data = $form_data['settings']['email'];
915 $form_data['settings']['email'] = array();
916 $form_data['settings']['email']['connection_1'] = array( 'connection_name' => __( 'Admin Notification', 'everest-forms' ) );
917
918 $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' );
919 foreach ( $email_settings as $email_setting ) {
920 $form_data['settings']['email']['connection_1'][ $email_setting ] = isset( $old_email_data[ $email_setting ] ) ? $old_email_data[ $email_setting ] : '';
921 }
922 }
923
924 $notifications = isset( $form_data['settings']['email'] ) ? $form_data['settings']['email'] : array();
925
926 foreach ( $notifications as $connection_id => $notification ) :
927
928 // Don't proceed if email notification is not enabled.
929 if ( isset( $notification['enable_email_notification'] ) && '1' !== $notification['enable_email_notification'] ) {
930 continue;
931 }
932
933 $process_email = apply_filters( 'everest_forms_entry_email_process', true, $fields, $form_data, $context, $connection_id );
934
935 if ( ! $process_email ) {
936 continue;
937 }
938
939 $email = array();
940 $evf_to_email = isset( $notification['evf_to_email'] ) ? $notification['evf_to_email'] : '';
941
942 // Setup email properties.
943 /* translators: %s - form name. */
944 $email['subject'] = ! empty( $notification['evf_email_subject'] ) ? $notification['evf_email_subject'] : sprintf( esc_html__( 'New %s Entry', 'everest-forms' ), $form_data['settings']['form_title'] );
945 $email['address'] = explode( ',', apply_filters( 'everest_forms_process_smart_tags', $evf_to_email, $form_data, $fields, $this->entry_id ) );
946 $email['address'] = array_map( 'sanitize_email', $email['address'] );
947 $email['sender_name'] = ! empty( $notification['evf_from_name'] ) ? $notification['evf_from_name'] : get_bloginfo( 'name' );
948 $email['sender_address'] = ! empty( $notification['evf_from_email'] ) ? $notification['evf_from_email'] : get_option( 'admin_email' );
949 $email['reply_to'] = ! empty( $notification['evf_reply_to'] ) ? $notification['evf_reply_to'] : $email['sender_address'];
950 if ( ! empty( get_option( 'everest_forms_ai_api_key' ) ) ) { // phpcs:ignore
951 $email['message_ai_prompt'] = ! empty( $notification['evf_email_message_prompt'] ) ? $notification['evf_email_message_prompt'] : '';
952 $email['enable_ai_prompt'] = ! empty( $notification['enable_ai_email_prompt'] ) ? $notification['enable_ai_email_prompt'] : 0;
953 }
954 $email['message'] = ! empty( $notification['evf_email_message'] ) ? evf_string_translation( $form_data['id'], 'evf_email_message', $notification['evf_email_message'] ) : '{all_fields}';
955 $email = apply_filters( 'everest_forms_entry_email_atts', $email, $fields, $entry, $form_data );
956 $attachment = '';
957
958 // Create new email.
959 $emails = new EVF_Emails();
960 $emails->__set( 'form_data', $form_data );
961 $emails->__set( 'fields', $fields );
962 $emails->__set( 'entry_id', $entry_id );
963 $emails->__set( 'from_name', $email['sender_name'] );
964 $emails->__set( 'from_address', $email['sender_address'] );
965 $emails->__set( 'reply_to', $email['reply_to'] );
966
967 /**
968 * This filter relies on consistent data being passed for the resultant filters to function.
969 * The third param passed for the filter, $fields, is derived from validation routine, not the DB.
970 */
971 $emails->__set( 'attachments', apply_filters( 'everest_forms_email_file_attachments', $attachment, $fields, $form_data, 'entry-email', $connection_id, $entry_id ) );
972
973 // Maybe include Cc and Bcc email addresses.
974 if ( 'yes' === get_option( 'everest_forms_enable_email_copies' ) ) {
975 if ( ! empty( $notification['evf_carboncopy'] ) ) {
976 $emails->__set( 'cc', $notification['evf_carboncopy'] );
977 }
978 if ( ! empty( $notification['evf_blindcarboncopy'] ) ) {
979 $emails->__set( 'bcc', $notification['evf_blindcarboncopy'] );
980 }
981 }
982
983 $emails = apply_filters( 'everest_forms_entry_email_before_send', $emails );
984
985 // Send entry email.
986 foreach ( $email['address'] as $address ) {
987 $emails->send( trim( $address ), $email['subject'], $email['message'], '', $connection_id );
988 }
989
990 endforeach;
991 if ( isset( $attachment ) ) {
992 do_action( 'everest_forms_remove_attachments_after_send_email', $attachment, $fields, $form_data, 'entry-email', $connection_id, $entry_id );
993 }
994 }
995
996 /**
997 * Saves entry to database.
998 *
999 * @param array $fields List of form fields.
1000 * @param array $entry User submitted data.
1001 * @param int $form_id Form ID.
1002 * @param array $form_data Prepared form settings.
1003 * @return int
1004 */
1005 public function entry_save( $fields, $entry, $form_id, $form_data = array() ) {
1006 global $wpdb;
1007
1008 // Check if form has entries disabled.
1009 if ( isset( $form_data['settings']['disabled_entries'] ) && '1' === $form_data['settings']['disabled_entries'] ) {
1010 return;
1011 }
1012
1013 // Provide the opportunity to override via a filter.
1014 if ( ! apply_filters( 'everest_forms_entry_save', true, $fields, $entry, $form_data ) ) {
1015 return;
1016 }
1017
1018 do_action( 'everest_forms_process_entry_save', $fields, $entry, $form_id, $form_data );
1019
1020 $fields = apply_filters( 'everest_forms_entry_save_data', $fields, $entry, $form_data );
1021 $browser = evf_get_browser();
1022 $user_ip = evf_get_ip_address();
1023 $user_device = evf_get_user_device();
1024 $user_agent = $browser['name'] . '/' . $browser['platform'] . '/' . $user_device;
1025 $referer = ! empty( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
1026 $entry_id = false;
1027 $status = isset( $entry['evf_spam_status'] ) ? $entry['evf_spam_status'] : 'publish';
1028 $admin_approval_entries = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
1029 $settings = isset( $form_data['settings'] ) ? $form_data['settings'] : array();
1030 $evf_form_admin_approval_entries = isset( $settings['enable_admin_approval_entries'] ) ? $settings['enable_admin_approval_entries'] : '0';
1031
1032 if ( 'yes' === $admin_approval_entries && '1' === $evf_form_admin_approval_entries ) {
1033 $status = 'pending';
1034 }
1035
1036 // GDPR enhancements - If user details are disabled globally discard the IP and UA.
1037 if ( 'yes' === get_option( 'everest_forms_disable_user_details' ) ) {
1038 $user_agent = '';
1039 $user_ip = '';
1040 }
1041
1042 $entry_data = apply_filters(
1043 'everest_forms_entry_data',
1044 array(
1045 'form_id' => $form_id,
1046 'user_id' => get_current_user_id(),
1047 'user_device' => sanitize_text_field( $user_agent ),
1048 'user_ip_address' => sanitize_text_field( $user_ip ),
1049 'status' => $status,
1050 'referer' => $referer,
1051 'fields' => wp_json_encode( $fields ),
1052 'date_created' => current_time( 'mysql', true ),
1053 ),
1054 $entry
1055 );
1056
1057 if ( ! $entry_data['form_id'] ) {
1058 return new WP_Error( 'no-form-id', __( 'No form ID was found.', 'everest-forms' ) );
1059 }
1060
1061 // Create entry.
1062 $success = $wpdb->insert( $wpdb->prefix . 'evf_entries', $entry_data );
1063
1064 if ( is_wp_error( $success ) || ! $success ) {
1065 return new WP_Error( 'could-not-create', __( 'Could not create an entry', 'everest-forms' ) );
1066 }
1067
1068 $entry_id = $wpdb->insert_id;
1069
1070 // Create meta data.
1071 if ( $entry_id ) {
1072 foreach ( $fields as $field ) {
1073 $field = apply_filters( 'everest_forms_entry_save_fields', $field, $form_data, $entry_id );
1074 // Add only whitelisted fields to entry meta.
1075 if ( in_array( $field['type'], array( 'html', 'title' ), true ) ) {
1076 continue;
1077 }
1078
1079 // If empty file is supplied, don't store their data nor send email.
1080 if ( in_array( $field['type'], array( 'image-upload', 'file-upload' ), true ) ) {
1081
1082 // BW compatibility for previous file uploader.
1083 if ( isset( $field['value']['file_url'] ) && '' === $field['value']['file_url'] ) {
1084 continue;
1085 }
1086 }
1087
1088 // If empty label is provided for choice field, don't store their data nor send email.
1089 if ( in_array( $field['type'], array( 'radio', 'payment-multiple' ), true ) ) {
1090 if ( isset( $field['value']['label'] ) && '' === $field['value']['label'] ) {
1091 continue;
1092 }
1093 } elseif ( in_array( $field['type'], array( 'checkbox', 'payment-checkbox' ), true ) ) {
1094 if ( isset( $field['value']['label'] ) && ( empty( $field['value']['label'] ) || '' === current( $field['value']['label'] ) ) ) {
1095 continue;
1096 }
1097 }
1098
1099 if ( isset( $field['meta_key'], $field['value'] ) && '' !== $field['value'] ) {
1100 $entry_metadata = array(
1101 'entry_id' => $entry_id,
1102 'meta_key' => sanitize_key( $field['meta_key'] ),
1103 'meta_value' => maybe_serialize( $field['value'] ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
1104 );
1105
1106 // Insert entry meta.
1107 $wpdb->insert( $wpdb->prefix . 'evf_entrymeta', $entry_metadata );
1108 }
1109 }
1110 }
1111
1112 $this->entry_id = $entry_id;
1113
1114 // Removing Entries Cache.
1115 wp_cache_delete( $entry_id, 'evf-entry' );
1116 wp_cache_delete( $entry_id, 'evf-entrymeta' );
1117 wp_cache_delete( $form_id, 'evf-entries-ids' );
1118 wp_cache_delete( $form_id, 'evf-last-entries-count' );
1119 wp_cache_delete( $form_id, 'evf-search-entries' );
1120 wp_cache_delete( EVF_Cache_Helper::get_cache_prefix( 'entries' ) . '_unread_count', 'entries' );
1121
1122 do_action( 'everest_forms_complete_entry_save', $entry_id, $fields, $entry, $form_id, $form_data );
1123
1124 return $this->entry_id;
1125 }
1126
1127 /**
1128 * Insert or update the slot booking data.
1129 *
1130 * @param int $entry_id Entry id.
1131 * @param array $fields List of form fields.
1132 * @param array $entry User submitted data.
1133 * @param int $form_id Form ID.
1134 * @param array $form_data Prepared form settings.
1135 */
1136 public function update_slot_booking_value( $entry_id, $fields, $entry, $form_id, $form_data ) {
1137 $new_slot_booking_field_meta_key_list = array();
1138 $time_interval = 0;
1139 foreach ( $form_data['form_fields'] as $field ) {
1140 if ( ( 'date-time' === $field['type'] ) && isset( $field['slot_booking_advanced'] ) && evf_string_to_bool( $field['slot_booking_advanced'] ) ) {
1141 $new_slot_booking_field_meta_key_list[ $field['meta-key'] ] = array(
1142 $field['datetime_format'],
1143 $field['date_format'],
1144 $field['date_mode'],
1145 );
1146 $time_interval = $field['time_interval'];
1147 }
1148 }
1149
1150 foreach ( $fields as $key => $value ) {
1151 if ( array_key_exists( $value['meta_key'], $new_slot_booking_field_meta_key_list ) ) {
1152 $new_value = $value['value'];
1153 $datetime_format = $new_slot_booking_field_meta_key_list[ $value['meta_key'] ][0];
1154 $date_format = $new_slot_booking_field_meta_key_list[ $value['meta_key'] ][1];
1155 $mode = $new_slot_booking_field_meta_key_list[ $value['meta_key'] ][2];
1156 $datetime_arr = parse_datetime_values( $new_value, $datetime_format, $date_format, $mode, $time_interval, $entry_id );
1157 }
1158 }
1159 if ( ! empty( $datetime_arr ) ) {
1160 $get_booked_slot = get_option( 'evf_booked_slot', array() );
1161 $new_booked_slot = array( $form_id => $datetime_arr );
1162
1163 if ( empty( $get_booked_slot ) ) {
1164 $all_booked_slot = maybe_serialize( $new_booked_slot );
1165 } else {
1166 $unserialized_booked_slot = maybe_unserialize( $get_booked_slot );
1167
1168 if ( array_key_exists( $form_id, $unserialized_booked_slot ) ) {
1169 $booked_slot = $unserialized_booked_slot[ $form_id ];
1170 $booked_slot = (array) $booked_slot + $datetime_arr;
1171 $new_booked_slot = array( $form_id => $booked_slot );
1172 }
1173
1174 $all_booked_slot = maybe_serialize( array_replace( $unserialized_booked_slot, $new_booked_slot ) );
1175 }
1176
1177 update_option( 'evf_booked_slot', $all_booked_slot );
1178 }
1179 }
1180
1181 /**
1182 * Load Previous Field Value.
1183 *
1184 * @param string $properties Value.
1185 * @param mixed $field Field.
1186 * @param mixed $form_data Form Data.
1187 * @return $properties Properties.
1188 */
1189 public function load_previous_field_value( $properties, $field, $form_data ) {
1190
1191 if ( ! isset( $_POST['everest_forms'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1192 return $properties;
1193 }
1194 $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
1195
1196 if ( 'checkbox' === $field['type'] ) {
1197 foreach ( $field['choices'] as $key => $option_value ) {
1198 $selected = ! empty( $option_value['default'] ) ? $option_value['default'] : '';
1199 foreach ( $data as $value ) {
1200 if ( $value === $option_value['label'] ) {
1201 $selected = 1;
1202 $properties['inputs'][ $key ]['default'] = $selected;
1203 }
1204 }
1205 }
1206 } elseif ( 'radio' === $field['type'] || 'select' === $field['type'] ) {
1207 foreach ( $field['choices'] as $key => $option_value ) {
1208 if ( $data === $option_value['label'] ) { // phpcs:ignore WordPress.Security.NonceVerification
1209 $selected = 1;
1210 $properties['inputs'][ $key ]['default'] = $selected;
1211 }
1212 }
1213 } elseif ( 'likert' === $field['type'] ) {
1214 if ( count( $data ) ) {
1215 foreach ( $data as $row => $col ) {
1216 foreach ( (array) $col as $col_selected ) {
1217 $index = sprintf( 'rows%d_columns%d', (int) $row, (int) $col_selected );
1218 $properties['inputs'][ $index ]['attr']['checked'] = true;
1219 }
1220 }
1221 }
1222 } elseif ( ! is_array( $data ) ) {
1223 $properties['inputs']['primary']['attr']['value'] = esc_attr( $data );
1224 }
1225 return $properties;
1226 }
1227
1228 /**
1229 * Check if a form entry should be validated by Akismet for potential spam.
1230 *
1231 * This function checks whether the Akismet plugin is installed and configured, and if the Akismet
1232 * validation option is enabled for a specific form. If validation is enabled, it prepares the
1233 * necessary data for the validation request and sends it to Akismet's 'comment-check' endpoint.
1234 *
1235 * @param array $entry The form entry data to validate.
1236 * @param string $form_id (Optional) The identifier of the form.
1237 *
1238 * @return bool
1239 * - true if the form entry is potentially spam according to Akismet.
1240 * - false if Akismet validation is not enabled, the plugin is not properly configured, or the entry is not considered spam.
1241 */
1242 public function get_akismet_validate( $entry, $form_id = '' ) {
1243
1244 if ( ! file_exists( WP_PLUGIN_DIR . '/akismet/akismet.php' ) ) {
1245 return false;
1246 }
1247
1248 if ( ! evf_is_akismet_configured() ) {
1249 return false;
1250 }
1251
1252 if ( isset( $this->form_data['settings']['akismet'] ) && '1' === $this->form_data['settings']['akismet'] ) {
1253 $entry_data = $this->get_entry_data_for_akismet( $this->form_data['form_fields'], $entry );
1254
1255 $entry_data = apply_filters( 'evf_entry_akismet_entry_data', $entry_data, $entry, $this->form_data );
1256
1257 $request = array(
1258 'blog' => get_option( 'home' ),
1259 'user_ip' => evf_get_ip_address(),
1260 'user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) : null, // phpcs:ignore
1261 'referrer' => wp_get_referer() ? wp_get_referer() : null,
1262 'permalink' => evf_current_url(),
1263 'comment_type' => 'contact-form',
1264 'comment_author' => isset( $entry_data['name'] ) ? $entry_data['name'] : '',
1265 'comment_author_email' => isset( $entry_data['email'] ) ? $entry_data['email'] : '',
1266 'comment_author_url' => isset( $entry_data['url'] ) ? $entry_data['url'] : '',
1267 'comment_content' => isset( $entry_data['content'] ) ? $entry_data['content'] : '',
1268 'blog_lang' => get_locale(),
1269 'blog_charset' => get_bloginfo( 'charset' ),
1270 'honypot_field_name' => 'everest_forms[hp]',
1271 );
1272
1273 $request = apply_filters( 'evf_akismet_request_data', $request, $this->form_data, $entry, $form_id );
1274
1275 $response = Akismet::http_post( build_query( $request ), 'comment-check' );
1276
1277 return ! empty( $response ) && isset( $response[1] ) && 'true' === trim( $response[1] );
1278 }
1279
1280 return false;
1281 }
1282
1283 /**
1284 * Get the list of field types that are allowed to be sent to Akismet.
1285 *
1286 * @since 1.7.6
1287 *
1288 * @return array List of field types that are allowed to be sent to Akismet
1289 */
1290 private function get_field_type_allowlist_for_akisment() {
1291
1292 $field_type_allowlist = array(
1293 'first-name',
1294 'last-name',
1295 'text',
1296 'textarea',
1297 'email',
1298 'phone',
1299 'address',
1300 'url',
1301 'wysiwyg',
1302 );
1303
1304 /**
1305 * Filters the field types that are allowed to be sent to Akismet.
1306 *
1307 * @since 2.4.0
1308 *
1309 * @param array $field_type_allowlist Field types allowed to be sent to Akismet.
1310 */
1311 return (array) apply_filters( 'evf_forms_akismet_get_field_type_allowlist', $field_type_allowlist );
1312 }
1313
1314 /**
1315 * Get the entry data to be sent to Akismet.
1316 *
1317 * @since 2.4.0
1318 *
1319 * @param array $fields Field data for the current form.
1320 * @param array $entry Entry data for the current entry.
1321 *
1322 * @return array $entry_data Entry data to be sent to Akismet.
1323 */
1324 private function get_entry_data_for_akismet( $fields, $entry ) {
1325 $field_type_allowlist = $this->get_field_type_allowlist_for_akisment();
1326 $entry_data = array();
1327 $entry_content = array();
1328
1329 foreach ( $fields as $key => $field ) {
1330 $field_type = $field['type'];
1331
1332 if ( ! in_array( $field_type, $field_type_allowlist, true ) ) {
1333 continue;
1334 }
1335 if ( ! isset( $entry['form_fields'][ $key ] ) ) {
1336 continue;
1337 }
1338 $field_content = is_array( $entry['form_fields'][ $key ] ) ? implode( ' ', $entry['form_fields'][ $key ] ) : $entry['form_fields'][ $key ];
1339
1340 if ( ! isset( $entry_data[ $field_type ] ) && in_array( $field_type, array( 'first-name', 'last-name', 'email', 'url' ), true ) ) {
1341 if ( 'first-name' === $field_type ) {
1342 $entry_data['name'] = isset( $entry_data['name'] ) ? "$field_content " . $entry_data['name'] : $field_content;
1343 continue;
1344 } elseif ( 'last-name' === $field_type ) {
1345 $entry_data['name'] = isset( $entry_data['name'] ) ? $entry_data['name'] . " $field_content" : $field_content;
1346 continue;
1347 }
1348 $entry_data[ $field_type ] = $field_content;
1349 continue;
1350 }
1351
1352 $entry_content[] = $field_content;
1353 }
1354
1355 $entry_data['content'] = implode( ' ', $entry_content );
1356
1357 return $entry_data;
1358 }
1359
1360 /**
1361 * Verify the token and approve the entry if the token matches.
1362 *
1363 * @since 2.0.9
1364 */
1365 public static function evf_admin_approve_entry() {
1366 if ( ! isset( $_GET['evf_admin_approval_entry_token'] ) || empty( $_GET['evf_admin_approval_entry_token'] ) ) {
1367 return;
1368 }
1369
1370 if ( current_user_can( 'edit_users' ) ) {
1371 global $wpdb;
1372 $evf_admin_approve_entry_token_raw = sanitize_text_field( wp_unslash( $_GET['evf_admin_approval_entry_token'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1373
1374 $evf_admin_approval_entry_enable = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
1375 $evf_admin_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1376 $evf_admin_entry_id = isset( $_GET['entry_id'] ) ? absint( $_GET['entry_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1377 $evf_entry_redirect_url = admin_url() . 'admin.php?page=evf-entries&form_id=' . $evf_admin_form_id . '&view-entry=' . $evf_admin_entry_id;
1378 $evf_admin_entry_saved_token = get_option( 'everest_forms_admin_entry_approval_token', array() );
1379
1380 if ( 'yes' === $evf_admin_approval_entry_enable ) {
1381 $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
1382 if ( in_array( $evf_admin_approve_entry_token_raw, $evf_admin_entry_saved_token ) ) {
1383 $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 ) );
1384 wp_redirect( $evf_entry_redirect_url );
1385 }
1386 }
1387 }
1388 }
1389
1390 /**
1391 * Verify the token and deny the entry if the token matches.
1392 *
1393 * @since 2.0.9
1394 */
1395 public static function evf_admin_deny_entry() {
1396 if ( ! isset( $_GET['evf_admin_denial_entry_token'] ) || empty( $_GET['evf_admin_denial_entry_token'] ) ) {
1397 return;
1398 }
1399
1400 if ( current_user_can( 'edit_users' ) ) {
1401 global $wpdb;
1402
1403 $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
1404 $evf_admin_approval_entry_enable = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
1405 $evf_admin_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1406 $evf_admin_entry_id = isset( $_GET['entry_id'] ) ? absint( $_GET['entry_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
1407 $evf_entry_redirect_url = admin_url() . 'admin.php?page=evf-entries&form_id=' . $evf_admin_form_id . '&view-entry=' . $evf_admin_entry_id;
1408 $evf_admin_entry_saved_token = get_option( 'everest_forms_admin_entry_approval_token', array() );
1409
1410 if ( 'yes' === $evf_admin_approval_entry_enable ) {
1411
1412 $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
1413 if ( in_array( $evf_admin_approve_entry_token_raw, $evf_admin_entry_saved_token ) ) {
1414 $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 ) );
1415 wp_redirect( $evf_entry_redirect_url );
1416 }
1417 }
1418 }
1419 }
1420
1421 /**
1422 * Set the entry approval token of the entry and update it to the options table in database.
1423 *
1424 * @param int $entry_id Entry ID.
1425 * @param array $form_data Form field data.
1426 *
1427 * @since 2.0.9
1428 */
1429 public function evf_set_approval_status( $entry_id, $form_data ) {
1430 $evf_admin_approval_token_list = array();
1431 $form_id = isset( $form_data['id'] ) ? $form_id['id'] : '';
1432 $evf_admin_entry_enable = get_option( 'everest_forms_admin_approval_entries_enable', 'no' );
1433 $evf_admin_entry_approval_token = get_option( 'everest_forms_admin_entry_approval_token', array() );
1434 $evf_approval_key = 'approval_token_' . $entry_id;
1435
1436 // Checks if admin approval entry is enabled.
1437 if ( ! isset( $evf_admin_entry_enable ) ) {
1438 return;
1439 } else {
1440 $token = evf_get_random_string( 20 );
1441 $evf_approval_token = array(
1442 $evf_approval_key => $token,
1443 );
1444 $evf_new_token = array_merge( $evf_admin_entry_approval_token, $evf_approval_token );
1445 update_option( 'everest_forms_admin_entry_approval_token', $evf_new_token );
1446 }
1447 }
1448
1449 /**
1450 * Prevents form submission before the specified duration.
1451 *
1452 * @param array $errors Form submit errors.
1453 * @param object $form_data An object containing settings for the form.
1454 */
1455 public function form_submission_waiting_time( $errors, $form_data ) {
1456 $form_submission_waiting_time_enable = isset( $form_data['settings']['form_submission_min_waiting_time'] ) ? $form_data['settings']['form_submission_min_waiting_time'] : '';
1457 $submission_duration = isset( $form_data['settings']['form_submission_min_waiting_time_input'] ) ? $form_data['settings']['form_submission_min_waiting_time_input'] : '';
1458
1459 if ( isset( $form_submission_waiting_time_enable ) && '1' === $form_submission_waiting_time_enable && 0 <= absint( $submission_duration ) ) {
1460 $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
1461 $atts = $form_data['id'];
1462 $submission_time = time() * 1000;
1463
1464 if ( $submission_duration <= 0 ) {
1465 $submission_duration = 1;
1466 }
1467 $waiting_time = absint( $submission_time ) - absint( $evf_submission_start_time );
1468 $form_id = ! empty( $form_data['id'] ) ? $form_data['id'] : 0;
1469
1470 if ( absint( $submission_time ) - absint( $evf_submission_start_time ) <= absint( $submission_duration ) * 1000 ) {
1471 /**
1472 * Filter to modify the waiting time message content.
1473 *
1474 * @since 3.0.2
1475 */
1476 $form_submission_err_msg = apply_filters(
1477 'everest_forms_minimum_waiting_time_form_submission',
1478 sprintf(
1479 "%s <span id='evf_submission_duration' data-duration='%s'>%s</span> %s",
1480 esc_html__( 'Please wait', 'everest-forms' ),
1481 $submission_duration,
1482 $submission_duration,
1483 esc_html__( 'seconds, security checkup is being executed.', 'everest-forms' )
1484 )
1485 );
1486
1487 $errors[ $form_id ]['header'] = $form_submission_err_msg;
1488 }
1489
1490 return $errors;
1491 }
1492 }
1493 }
1494