PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 1.8.7
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v1.8.7
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
abstracts 4 years ago admin 4 years ago elementor 4 years ago export 4 years ago fields 4 years ago interfaces 8 years ago libraries 7 years ago log-handlers 4 years ago shortcodes 4 years ago templates 5 years ago class-everest-forms.php 4 years ago class-evf-ajax.php 4 years ago class-evf-autoloader.php 7 years ago class-evf-background-updater.php 7 years ago class-evf-cache-helper.php 6 years ago class-evf-deprecated-action-hooks.php 6 years ago class-evf-deprecated-filter-hooks.php 5 years ago class-evf-emails.php 5 years ago class-evf-fields.php 6 years ago class-evf-form-block.php 4 years ago class-evf-form-handler.php 4 years ago class-evf-form-task.php 4 years ago class-evf-forms-features.php 4 years ago class-evf-frontend-scripts.php 4 years ago class-evf-install.php 5 years ago class-evf-integrations.php 7 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-session-handler.php 7 years ago class-evf-shortcodes.php 4 years ago class-evf-smart-tags.php 4 years ago class-evf-template-loader.php 4 years ago class-evf-validation.php 6 years ago evf-conditional-functions.php 6 years ago evf-core-functions.php 4 years ago evf-deprecated-functions.php 6 years ago evf-entry-functions.php 4 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 7 years ago evf-update-functions.php 5 years ago
class-evf-form-task.php
1053 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 }
65
66 /**
67 * Listen to see if this is a return callback or a posted form entry.
68 *
69 * @since 1.0.0
70 */
71 public function listen_task() {
72 if ( ! empty( $_GET['everest_forms_return'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
73 $this->entry_confirmation_redirect( '', sanitize_text_field( wp_unslash( $_GET['everest_forms_return'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
74 }
75
76 $form_id = ! empty( $_POST['everest_forms']['id'] ) ? absint( $_POST['everest_forms']['id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
77
78 if ( ! $form_id ) {
79 return;
80 }
81
82 if ( ! empty( $_POST['everest_forms']['id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
83 $this->do_task( evf_sanitize_entry( wp_unslash( $_POST['everest_forms'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
84 }
85
86 if ( ! evf_is_amp() ) {
87 return;
88 }
89
90 $settings = $this->form_data['settings'];
91 $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' );
92 // Send 400 Bad Request when there are errors.
93 if ( empty( $this->errors[ $form_id ] ) ) {
94 wp_send_json(
95 array(
96 'message' => $success_message,
97 ),
98 200
99 );
100
101 return;
102 }
103 $message = $this->errors[ $form_id ]['header'];
104
105 if ( ! empty( $this->errors[ $form_id ]['footer'] ) ) {
106 $message .= ' ' . $this->errors[ $form_id ]['footer'];
107 }
108
109 wp_send_json(
110 array(
111 'message' => $message,
112 ),
113 400
114 );
115
116 }
117
118 /**
119 * Do task of form entry
120 *
121 * @since 1.0.0
122 * @param array $entry $_POST object.
123 */
124 public function do_task( $entry ) {
125 $logger = evf_get_logger();
126 try {
127 $this->errors = array();
128 $this->form_fields = array();
129 $form_id = absint( $entry['id'] );
130 $form = evf()->form->get( $form_id );
131 $honeypot = false;
132 $response_data = array();
133 $this->ajax_err = array();
134 $this->evf_notice_print = false;
135 $logger = evf_get_logger();
136
137 // Check nonce for form submission.
138 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
139 $this->errors[ $form_id ]['header'] = esc_html__( 'We were unable to process your form, please try again.', 'everest-forms' );
140 $logger->error(
141 $this->errors[ $form_id ]['header'],
142 array( 'source' => 'form-submission' )
143 );
144 return $this->errors;
145 }
146
147 // Validate form is real and active (published).
148 if ( ! $form || 'publish' !== $form->post_status ) {
149 $this->errors[ $form_id ]['header'] = esc_html__( 'Invalid form. Please check again.', 'everest-forms' );
150 $logger->error(
151 $this->errors[ $form_id ]['header'],
152 array( 'source' => 'form-submission' )
153 );
154 return $this->errors;
155 }
156
157 // Formatted form data for hooks.
158 $this->form_data = apply_filters( 'everest_forms_process_before_form_data', evf_decode( $form->post_content ), $entry );
159
160 // Pre-process/validate hooks and filter. Data is not validated or cleaned yet so use with caution.
161 $entry = apply_filters( 'everest_forms_process_before_filter', $entry, $this->form_data );
162 $this->form_data['page_id'] = array_key_exists( 'post_id', $entry ) ? $entry['post_id'] : $form_id;
163
164 $logger->info(
165 __( 'Everest Forms Process Before.', 'everest-forms' ),
166 array( 'source' => 'form-submission' )
167 );
168 do_action( 'everest_forms_process_before', $entry, $this->form_data );
169 $logger->info(
170 __( 'Everest Forms Process Before Form ID.', 'everest-forms' ),
171 array( 'source' => 'form-submission' )
172 );
173 do_action( "everest_forms_process_before_{$form_id}", $entry, $this->form_data );
174
175 $ajax_form_submission = isset( $this->form_data['settings']['ajax_form_submission'] ) ? $this->form_data['settings']['ajax_form_submission'] : 0;
176 if ( '1' === $ajax_form_submission ) {
177
178 // For the sake of validation we completely remove the validator option.
179 update_option( 'evf_validation_error', '' );
180
181 // Prepare fields for entry_save.
182 foreach ( $this->form_data['form_fields'] as $field ) {
183 if ( '' === isset( $this->form_data['form_fields']['meta-key'] ) ) {
184 continue;
185 }
186
187 $field_id = $field['id'];
188 $field_type = $field['type'];
189 $field_submit = isset( $entry['form_fields'][ $field_id ] ) ? $entry['form_fields'][ $field_id ] : '';
190
191 if ( 'signature' === $field_type ) {
192 $field_submit = isset( $field_submit['signature_image'] ) ? $field_submit['signature_image'] : '';
193 }
194
195 $exclude = array( 'title', 'html', 'captcha', 'image-upload', 'file-upload', 'divider' );
196
197 if ( ! in_array( $field_type, $exclude, true ) ) {
198
199 $this->form_fields[ $field_id ] = array(
200 'id' => $field_id,
201 'name' => sanitize_text_field( $field['label'] ),
202 'meta_key' => $this->form_data['form_fields'][ $field_id ]['meta-key'],
203 'type' => $field_type,
204 'value' => evf_sanitize_textarea_field( $field_submit ),
205 );
206 }
207 }
208 }
209
210 // Validate fields.
211 foreach ( $this->form_data['form_fields'] as $field ) {
212 $field_id = $field['id'];
213 $field_type = $field['type'];
214 $repeater_fields = array_key_exists( 'repeater-fields', $field ) ? $field['repeater-fields'] : 'no';
215
216 $field_submit = isset( $entry['form_fields'][ $field_id ] ) ? $entry['form_fields'][ $field_id ] : '';
217
218 if ( 'no' === $repeater_fields || 'repeater-fields' === $field_type ) {
219 $logger->info(
220 "Everest Forms Process Before validate {$field_type}.",
221 array( 'source' => 'form-submission' )
222 );
223 do_action( "everest_forms_process_validate_{$field_type}", $field_id, $field_submit, $this->form_data, $field_type );
224 }
225
226 if ( 'credit-card' === $field_type && isset( $_POST['everest_form_stripe_payment_intent_id'] ) ) {
227 $this->evf_notice_print = true;
228 }
229
230 if ( 'yes' === get_option( 'evf_validation_error' ) && $ajax_form_submission ) {
231 if ( count( $this->errors ) ) {
232 foreach ( $this->errors as $_error ) {
233 $this->ajax_err [] = $_error;
234 }
235 }
236 update_option( 'evf_validation_error', '' );
237 }
238 }
239
240 // If validation issues occur, send the results accordingly.
241 if ( $ajax_form_submission && count( $this->ajax_err ) ) {
242 $response_data['error'] = $this->ajax_err;
243 $response_data['message'] = __( 'Form has not been submitted, please see the errors below.', 'everest-forms' );
244 $response_data['response'] = 'error';
245 $logger->error(
246 __( 'Form has not been submitted.', 'everest-forms' ),
247 array( 'source' => 'form-submission' )
248 );
249 return $response_data;
250 }
251
252 // reCAPTCHA check.
253 if ( ! apply_filters( 'everest_forms_recaptcha_disabled', false ) ) {
254 $recaptcha_type = get_option( 'everest_forms_recaptcha_type', 'v2' );
255 $invisible_recaptcha = get_option( 'everest_forms_recaptcha_v2_invisible', 'no' );
256
257 if ( 'v2' === $recaptcha_type && 'no' === $invisible_recaptcha ) {
258 $site_key = get_option( 'everest_forms_recaptcha_v2_site_key' );
259 $secret_key = get_option( 'everest_forms_recaptcha_v2_secret_key' );
260 } elseif ( 'v2' === $recaptcha_type && 'yes' === $invisible_recaptcha ) {
261 $site_key = get_option( 'everest_forms_recaptcha_v2_invisible_site_key' );
262 $secret_key = get_option( 'everest_forms_recaptcha_v2_invisible_secret_key' );
263 } elseif ( 'v3' === $recaptcha_type ) {
264 $site_key = get_option( 'everest_forms_recaptcha_v3_site_key' );
265 $secret_key = get_option( 'everest_forms_recaptcha_v3_secret_key' );
266 } elseif ( 'hcaptcha' === $recaptcha_type ) {
267 $site_key = get_option( 'everest_forms_recaptcha_hcaptcha_site_key' );
268 $secret_key = get_option( 'everest_forms_recaptcha_hcaptcha_secret_key' );
269 }
270
271 if ( ! empty( $site_key ) && ! empty( $secret_key ) && isset( $this->form_data['settings']['recaptcha_support'] ) && '1' === $this->form_data['settings']['recaptcha_support'] &&
272 ! isset( $_POST['__amp_form_verify'] ) && ( 'v3' === $recaptcha_type || ! evf_is_amp() ) ) {
273 if ( 'hcaptcha' === $recaptcha_type ) {
274 $error = esc_html__( 'hCaptcha verification failed, please try again later.', 'everest-forms' );
275 } else {
276 $error = esc_html__( 'Google reCAPTCHA verification failed, please try again later.', 'everest-forms' );
277 }
278
279 $logger->error(
280 $error,
281 array( 'source' => 'Google reCAPTCHA' )
282 );
283
284 $token = ! empty( $_POST['g-recaptcha-response'] ) ? evf_clean( wp_unslash( $_POST['g-recaptcha-response'] ) ) : false;
285
286 if ( 'v3' === $recaptcha_type ) {
287 $token = ! empty( $_POST['everest_forms']['recaptcha'] ) ? evf_clean( wp_unslash( $_POST['everest_forms']['recaptcha'] ) ) : false;
288 }
289 if ( 'hcaptcha' === $recaptcha_type ) {
290 $token = ! empty( $_POST['h-captcha-response'] ) ? evf_clean( wp_unslash( $_POST['h-captcha-response'] ) ) : false;
291 $raw_response = wp_safe_remote_get( 'https://hcaptcha.com/siteverify?secret=' . $secret_key . '&response=' . $token );
292 } else {
293 $raw_response = wp_safe_remote_get( 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secret_key . '&response=' . $token );
294 }
295
296 if ( ! is_wp_error( $raw_response ) ) {
297 $response = json_decode( wp_remote_retrieve_body( $raw_response ) );
298 // Check reCAPTCHA response.
299 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' ) ) ) ) {
300 if ( 'v3' === $recaptcha_type ) {
301 if ( isset( $response->score ) ) {
302 $error .= ' (' . esc_html( $response->score ) . ')';
303 }
304 }
305 $this->errors[ $form_id ]['header'] = $error;
306 $logger->error(
307 $error,
308 array( 'source' => 'Google reCAPTCHA' )
309 );
310 return $this->errors;
311 }
312 }
313 }
314 }
315 // Initial error check.
316 $errors = apply_filters( 'everest_forms_process_initial_errors', $this->errors, $this->form_data );
317 if ( isset( $_POST['__amp_form_verify'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
318 if ( empty( $errors[ $form_id ] ) ) {
319 wp_send_json( array(), 200 );
320 } else {
321 $verify_errors = array();
322
323 foreach ( $errors[ $form_id ] as $field_id => $error_fields ) {
324 $field = $this->form_data['fields'][ $field_id ];
325 $field_properties = EVF_Shortcode_Form::get_field_properties( $field, $this->form_data );
326
327 if ( is_string( $error_fields ) ) {
328
329 if ( 'checkbox' === $field['type'] || 'radio' === $field['type'] || 'select' === $field['type'] ) {
330 $first = current( $field_properties['inputs'] );
331 $name = $first['attr']['name'];
332 } elseif ( isset( $field_properties['inputs']['primary']['attr']['name'] ) ) {
333 $name = $field_properties['inputs']['primary']['attr']['name'];
334 }
335
336 $verify_errors[] = array(
337 'name' => $name,
338 'message' => $error_fields,
339 );
340 } else {
341 foreach ( $error_fields as $error_field => $error_message ) {
342
343 if ( isset( $field_properties['inputs'][ $error_field ]['attr']['name'] ) ) {
344 $name = $field_properties['inputs'][ $error_field ]['attr']['name'];
345 }
346
347 $verify_errors[] = array(
348 'name' => $name,
349 'message' => $error_message,
350 );
351 }
352 }
353 }
354
355 wp_send_json(
356 array(
357 'verifyErrors' => $verify_errors,
358 ),
359 400
360 );
361 }
362 return;
363 }
364 if ( ! empty( $errors[ $form_id ] ) ) {
365 if ( empty( $errors[ $form_id ]['header'] ) ) {
366 $errors[ $form_id ]['header'] = __( 'Form has not been submitted, please see the errors below.', 'everest-forms' );
367 $logger->error(
368 $errors[ $form_id ]['header'],
369 array( 'source' => 'form-submission' )
370 );
371 }
372 $this->errors = $errors;
373 return $this->errors;
374 }
375
376 // Early honeypot validation - before actual processing.
377 if ( isset( $this->form_data['settings']['honeypot'] ) && '1' === $this->form_data['settings']['honeypot'] && ! empty( $entry['hp'] ) ) {
378 $honeypot = esc_html__( 'Everest Forms honeypot field triggered.', 'everest-forms' );
379 }
380
381 $honeypot = apply_filters( 'everest_forms_process_honeypot', $honeypot, $this->form_fields, $entry, $this->form_data );
382
383 // If spam - return early.
384 if ( $honeypot ) {
385 $logger = evf_get_logger();
386 $logger->notice( sprintf( 'Spam entry for Form ID %d Response: %s', absint( $this->form_data['id'] ), evf_print_r( $entry, true ) ), array( 'source' => 'honeypot' ) );
387 return $this->errors;
388 }
389
390 // Pass the form created date into the form data.
391 $this->form_data['created'] = $form->post_date;
392
393 // Format and Sanitize inputs.
394 foreach ( (array) $this->form_data['form_fields'] as $field ) {
395 $field_id = $field['id'];
396 $field_key = isset( $field['meta-key'] ) ? $field['meta-key'] : '';
397 $field_type = $field['type'];
398 $field_submit = isset( $entry['form_fields'][ $field_id ] ) ? $entry['form_fields'][ $field_id ] : '';
399 $repeater_fields = array_key_exists( 'repeater-fields', $field ) ? $field['repeater-fields'] : 'no';
400
401 if ( 'no' === $repeater_fields || 'repeater-fields' === $field_type ) {
402 $logger->info(
403 sprintf( 'Everest Forms Process Format %s.', $field_type ),
404 array( 'source' => 'form-submission' )
405 );
406 do_action( "everest_forms_process_format_{$field_type}", $field_id, $field_submit, $this->form_data, $field_key );
407 }
408 }
409
410 // This hook is for internal purposes and should not be leveraged.
411 $logger->info(
412 'Everest Forms Process Format After.',
413 array( 'source' => 'form-submission' )
414 );
415 do_action( 'everest_forms_process_format_after', $this->form_data );
416
417 // Process hooks/filter - this is where most addons should hook
418 // because at this point we have completed all field validation and
419 // formatted the data.
420 $this->form_fields = apply_filters( 'everest_forms_process_filter', $this->form_fields, $entry, $this->form_data );
421 $logger->notice( sprintf( 'Everest Form Process: %s', evf_print_r( $this->form_fields, true ) ) );
422
423 $logger->info(
424 'Everest Forms Process.',
425 array( 'source' => 'form-submission' )
426 );
427 do_action( 'everest_forms_process', $this->form_fields, $entry, $this->form_data );
428 $logger->info(
429 "Everest Forms Process {$form_id}.",
430 array( 'source' => 'form-submission' )
431 );
432 do_action( "everest_forms_process_{$form_id}", $this->form_fields, $entry, $this->form_data );
433
434 $this->form_fields = apply_filters( 'everest_forms_process_after_filter', $this->form_fields, $entry, $this->form_data );
435 $logger->notice( sprintf( 'Everest Form Process After: %s', evf_print_r( $this->form_fields, true ) ) );
436
437 // One last error check - don't proceed if there are any errors.
438 if ( ! empty( $this->errors[ $form_id ] ) ) {
439 if ( empty( $this->errors[ $form_id ]['header'] ) ) {
440 $this->errors[ $form_id ]['header'] = esc_html__( 'Form has not been submitted, please see the errors below.', 'everest-forms' );
441 }
442 $logger->error(
443 __( 'Form has not been submitted', 'everest-forms' ),
444 array( 'source' => 'form-submission' )
445 );
446 return $this->errors;
447 }
448
449 $logger->notice( sprintf( 'Entry is Saving to DataBase' ) );
450 // Success - add entry to database.
451 $logger->info(
452 __( 'Entry Added to Database.', 'everest-forms' ),
453 array( 'source' => 'form-submission' )
454 );
455 $entry_id = $this->entry_save( $this->form_fields, $entry, $this->form_data['id'], $this->form_data );
456 $logger->notice( sprintf( 'Entry is Saved to DataBase' ) );
457
458 $logger->notice( sprintf( 'Sending Email' ) );
459 // Success - send email notification.
460 $logger->info(
461 __( 'Sent Email Notification.', 'everest-forms' ),
462 array( 'source' => 'form-submission' )
463 );
464 $this->entry_email( $this->form_fields, $entry, $this->form_data, $entry_id, 'entry' );
465 $logger->notice( sprintf( 'Successfully Send the email' ) );
466
467 // @todo remove this way of printing notices.
468 add_filter( 'everest_forms_success', array( $this, 'check_success_message' ), 10, 2 );
469
470 // Pass completed and formatted fields in POST.
471 $_POST['everest-forms']['complete'] = $this->form_fields;
472
473 // Pass entry ID in POST.
474 $_POST['everest-forms']['entry_id'] = $entry_id;
475
476 // Post-process hooks.
477 $logger->info(
478 __( 'Everest Forms Process Completed.', 'everest-forms' ),
479 array( 'source' => 'form-submission' )
480 );
481 do_action( 'everest_forms_process_complete', $this->form_fields, $entry, $this->form_data, $entry_id );
482 $logger->info(
483 "Everest Forms Process Completed {$form_id}.",
484 array( 'source' => 'form-submission' )
485 );
486 do_action( "everest_forms_process_complete_{$form_id}", $this->form_fields, $entry, $this->form_data, $entry_id );
487 } catch ( Exception $e ) {
488 evf_add_notice( $e->getMessage(), 'error' );
489 $logger->error(
490 $e->getMessage(),
491 array( 'source' => 'form-submission' )
492 );
493 if ( '1' === $ajax_form_submission ) {
494 $this->errors[] = $e->getMessage();
495 $response_data['message'] = $this->errors;
496 $response_data['response'] = 'error';
497 return $response_data;
498 }
499 }
500
501 $settings = $this->form_data['settings'];
502 $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' );
503
504 if ( defined( 'EVF_PDF_SUBMISSION_VERSION' ) && 'yes' === get_option( 'everest_forms_pdf_download_after_submit', 'no' ) ) {
505 global $__everest_form_id;
506 global $__everest_form_entry_id;
507 $__everest_form_id = $form_id;
508 $__everest_form_entry_id = $entry_id;
509 }
510
511 // Check Conditional Logic and get the redirection URL.
512 $submission_redirection_process = apply_filters( 'everest_forms_submission_redirection_process', array(), $this->form_fields, $this->form_data );
513
514 // Backward compatibility for evf form templates.
515 $this->form_data['settings']['redirect_to'] = '0' === $this->form_data['settings']['redirect_to'] ? 'same' : $this->form_data['settings']['redirect_to'];
516
517 if ( '1' === $ajax_form_submission ) {
518 $response_data['message'] = $message;
519 $response_data['response'] = 'success';
520 $response_data['form_id'] = $form_id;
521 $response_data['entry_id'] = $entry_id;
522
523 if ( defined( 'EVF_PDF_SUBMISSION_VERSION' ) && 'yes' === get_option( 'everest_forms_pdf_download_after_submit', 'no' ) ) {
524 $response_data['pdf_download'] = true;
525 $pdf_download_message = get_option( 'everest_forms_pdf_custom_download_text', '' );
526 if ( empty( $pdf_download_message ) ) {
527 $pdf_download_message = __( 'Download your form submission in PDF format', 'everest-forms' );
528 }
529 $response_data['pdf_download_message'] = $pdf_download_message;
530 }
531
532 // Backward Compatibility Check.
533 switch ( $settings['redirect_to'] ) {
534 case '0':
535 $settings['redirect_to'] = 'same';
536 break;
537
538 case '1':
539 $settings['redirect_to'] = 'custom_page';
540 break;
541
542 case '2':
543 $settings['redirect_to'] = 'external_url';
544 break;
545 }
546
547 // Check for Submission Redirection in Ajax Submission.
548 if ( empty( $submission_redirection_process ) ) {
549 if ( isset( $settings['redirect_to'] ) && 'external_url' === $settings['redirect_to'] ) {
550 $response_data['redirect_url'] = isset( $settings['external_url'] ) ? esc_url( $settings['external_url'] ) : 'undefined';
551 } elseif ( isset( $settings['redirect_to'] ) && 'custom_page' === $settings['redirect_to'] ) {
552 $response_data['redirect_url'] = isset( $settings['custom_page'] ) ? get_page_link( absint( $settings['custom_page'] ) ) : 'undefined';
553 }
554 } else {
555 $response_data['redirect_url'] = $submission_redirection_process['external_url'];
556 }
557
558 // Add notice only if credit card is populated in form fields.
559 if ( isset( $this->evf_notice_print ) && $this->evf_notice_print ) {
560 evf_add_notice( $message, 'success' );
561 }
562 // $this->entry_confirmation_redirect( $this->form_data );
563 $response_data = apply_filters( 'everest_forms_after_success_ajax_message', $response_data, $this->form_data, $entry );
564 return $response_data;
565 } elseif ( ( 'same' === $this->form_data['settings']['redirect_to'] && empty( $submission_redirection_process ) ) || ( ! empty( $submission_redirection_process ) && 'same_page' == $submission_redirection_process['redirect_to'] ) ) {
566 evf_add_notice( $message, 'success' );
567 }
568 $logger->info(
569 'Everest Forms After success Message.',
570 array( 'source' => 'form-submission' )
571 );
572
573 do_action( 'everest_forms_after_success_message', $this->form_data, $entry );
574 $this->entry_confirmation_redirect( $this->form_data );
575
576 }
577
578 /**
579 * Process AJAX form submission.
580 *
581 * @since 1.6.0
582 *
583 * @param mixed $posted_data Posted data.
584 */
585 public function ajax_form_submission( $posted_data ) {
586 add_filter( 'wp_redirect', array( $this, 'ajax_process_redirect' ), 999 );
587 $process = $this->do_task( $posted_data );
588 return $process;
589 }
590
591 /**
592 * Process AJAX redirect.
593 *
594 * @since 1.6.0
595 *
596 * @param string $url Redirect URL.
597 */
598 public function ajax_process_redirect( $url ) {
599 $form_id = isset( $_POST['everest_forms']['id'] ) ? absint( $_POST['everest_forms']['id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification
600
601 if ( empty( $form_id ) ) {
602 wp_send_json_error();
603 }
604
605 $response = array(
606 'form_id' => $form_id,
607 'redirect_url' => $url,
608 );
609
610 $response = apply_filters( 'everest_forms_ajax_submit_redirect', $response, $form_id, $url );
611
612 do_action( 'everest_forms_ajax_submit_completed', $form_id, $response );
613 wp_send_json_success( $response );
614 }
615
616 /**
617 * Check the sucessful message.
618 *
619 * @param bool $status Message status.
620 * @param int $form_id Form ID.
621 */
622 public function check_success_message( $status, $form_id ) {
623 if ( isset( $this->form_data['id'] ) && absint( $this->form_data['id'] ) === $form_id ) {
624 return true;
625 }
626 return false;
627 }
628
629 /**
630 * Validate the form return hash.
631 *
632 * @since 1.0.0
633 *
634 * @param string $hash Base64-encoded hash of form and entry IDs.
635 * @return array|false False for invalid or form id.
636 */
637 public function validate_return_hash( $hash = '' ) {
638 $query_args = base64_decode( $hash );
639
640 parse_str( $query_args, $output );
641
642 // Verify hash matches.
643 if ( wp_hash( $output['form_id'] . ',' . $output['entry_id'] ) !== $output['hash'] ) {
644 return false;
645 }
646
647 // Get lead and verify it is attached to the form we received with it.
648 $entry = evf_get_entry( $output['entry_id'] );
649
650 if ( empty( $entry->form_id ) ) {
651 return false;
652 }
653
654 if ( $output['form_id'] !== $entry->form_id ) {
655 return false;
656 }
657
658 return array(
659 'form_id' => absint( $output['form_id'] ),
660 'entry_id' => absint( $output['form_id'] ),
661 'fields' => null !== $entry && isset( $entry->fields ) ? $entry->fields : array(),
662 );
663 }
664
665 /**
666 * Redirects user to a page or URL specified in the form confirmation settings.
667 *
668 * @since 1.0.0
669 *
670 * @param array $form_data Form data and settings.
671 * @param string $hash Base64-encoded hash of form and entry IDs.
672 */
673 public function entry_confirmation_redirect( $form_data = '', $hash = '' ) {
674 $_POST = array(); // Clear fields after successful form submission.
675
676 // Process return hash.
677 if ( ! empty( $hash ) ) {
678 $hash_data = $this->validate_return_hash( $hash );
679
680 if ( ! $hash_data || ! is_array( $hash_data ) ) {
681 return;
682 }
683
684 $this->is_valid_hash = true;
685 $this->entry_id = absint( $hash_data['entry_id'] );
686 $this->form_fields = json_decode( $hash_data['fields'], true );
687 $this->form_data = evf()->form->get(
688 absint( $hash_data['form_id'] ),
689 array(
690 'content_only' => true,
691 )
692 );
693 } else {
694 $this->form_data = $form_data;
695 }
696
697 $settings = $this->form_data['settings'];
698
699 // Backward Compatibility Check.
700 switch ( $settings['redirect_to'] ) {
701 case '0':
702 $settings['redirect_to'] = 'same';
703 break;
704
705 case '1':
706 $settings['redirect_to'] = 'custom_page';
707 break;
708
709 case '2':
710 $settings['redirect_to'] = 'external_url';
711 break;
712 }
713
714 $submission_redirect_process = apply_filters( 'everest_forms_submission_redirection_process', array(), $this->form_fields, $this->form_data );
715
716 if ( ! empty( $submission_redirect_process ) ) {
717 $settings['redirect_to'] = $submission_redirect_process['redirect_to'];
718 $settings['external_url'] = $submission_redirect_process['external_url'];
719 $settings['custom_page'] = $submission_redirect_process['custom_page'];
720 }
721
722 if ( isset( $settings['redirect_to'] ) && 'custom_page' === $settings['redirect_to'] ) {
723 ?>
724 <script>
725 var redirect = '<?php echo esc_url( get_page_link( $settings['custom_page'] ) ); ?>';
726 window.setTimeout( function () {
727 window.location.href = redirect;
728 })
729 </script>
730 <?php
731 } elseif ( isset( $settings['redirect_to'] ) && 'external_url' === $settings['redirect_to'] ) {
732 ?>
733 <script>
734 window.setTimeout( function () {
735 window.location.href = '<?php echo esc_url( $settings['external_url'] ); ?>';
736 })
737 </script>
738 <?php
739 }
740
741 // Redirect if needed, to either a page or URL, after form processing.
742 if ( ! empty( $this->form_data['settings']['confirmation_type'] ) && 'message' !== $this->form_data['settings']['confirmation_type'] ) {
743 if ( 'redirect' === $this->form_data['settings']['confirmation_type'] ) {
744 $url = apply_filters( 'everest_forms_process_smart_tags', $this->form_data['settings']['confirmation_redirect'], $this->form_data, $this->form_fields, $this->entry_id );
745 }
746
747 if ( 'page' === $this->form_data['settings']['confirmation_type'] ) {
748 $url = get_permalink( (int) $this->form_data['settings']['confirmation_page'] );
749 }
750 }
751
752 if ( ! empty( $this->form_data['id'] ) ) {
753 $form_id = $this->form_data['id'];
754 } else {
755 return;
756 }
757 if ( isset( $settings['submission_message_scroll'] ) && $settings['submission_message_scroll'] ) {
758 add_filter( 'everest_forms_success_notice_class', array( $this, 'add_scroll_notice_class' ) );
759 }
760
761 if ( ! empty( $url ) ) {
762 $url = apply_filters( 'everest_forms_process_redirect_url', $url, $form_id, $this->form_fields );
763 wp_safe_redirect( esc_url_raw( $url ) );
764 do_action( 'everest_forms_process_redirect', $form_id );
765 do_action( "everest_forms_process_redirect_{$form_id}", $form_id );
766 exit;
767 }
768 }
769
770 /**
771 * Add scroll notice class.
772 *
773 * @param array $classes Notice Classes.
774 * @return array of notice classes.
775 */
776 public function add_scroll_notice_class( $classes ) {
777 $classes[] = 'everest-forms-submission-scroll';
778
779 return $classes;
780 }
781
782 /**
783 * Sends entry email notifications.
784 *
785 * @param array $fields List of fields.
786 * @param array $entry Submitted form entry.
787 * @param array $form_data Form data and settings.
788 * @param int $entry_id Saved entry id.
789 * @param string $context In which context this email is sent.
790 */
791 public function entry_email( $fields, $entry, $form_data, $entry_id, $context = '' ) {
792 // Provide the opportunity to override via a filter.
793 if ( ! apply_filters( 'everest_forms_entry_email', true, $fields, $entry, $form_data ) ) {
794 return;
795 }
796
797 // Make sure we have an entry id.
798 if ( empty( $this->entry_id ) ) {
799 $this->entry_id = (int) $entry_id;
800 }
801
802 $fields = apply_filters( 'everest_forms_entry_email_data', $fields, $entry, $form_data );
803
804 if ( ! isset( $form_data['settings']['email']['connection_1'] ) ) {
805 $old_email_data = $form_data['settings']['email'];
806 $form_data['settings']['email'] = array();
807 $form_data['settings']['email']['connection_1'] = array( 'connection_name' => __( 'Admin Notification', 'everest-forms' ) );
808
809 $email_settings = array( 'evf_to_email', 'evf_from_name', 'evf_from_email', 'evf_reply_to', 'evf_email_subject', 'evf_email_message', 'attach_pdf_to_admin_email', 'show_header_in_attachment_pdf_file', 'conditional_logic_status', 'conditional_option', 'conditionals' );
810 foreach ( $email_settings as $email_setting ) {
811 $form_data['settings']['email']['connection_1'][ $email_setting ] = isset( $old_email_data[ $email_setting ] ) ? $old_email_data[ $email_setting ] : '';
812 }
813 }
814
815 $notifications = isset( $form_data['settings']['email'] ) ? $form_data['settings']['email'] : array();
816
817 foreach ( $notifications as $connection_id => $notification ) :
818
819 // Don't proceed if email notification is not enabled.
820 if ( isset( $notification['enable_email_notification'] ) && '1' !== $notification['enable_email_notification'] ) {
821 continue;
822 }
823
824 $process_email = apply_filters( 'everest_forms_entry_email_process', true, $fields, $form_data, $context, $connection_id );
825
826 if ( ! $process_email ) {
827 continue;
828 }
829
830 $email = array();
831 $evf_to_email = isset( $notification['evf_to_email'] ) ? $notification['evf_to_email'] : '';
832
833 // Setup email properties.
834 /* translators: %s - form name. */
835 $email['subject'] = ! empty( $notification['evf_email_subject'] ) ? $notification['evf_email_subject'] : sprintf( esc_html__( 'New %s Entry', 'everest-forms' ), $form_data['settings']['form_title'] );
836 $email['address'] = explode( ',', apply_filters( 'everest_forms_process_smart_tags', $evf_to_email, $form_data, $fields, $this->entry_id ) );
837 $email['address'] = array_map( 'sanitize_email', $email['address'] );
838 $email['sender_name'] = ! empty( $notification['evf_from_name'] ) ? $notification['evf_from_name'] : get_bloginfo( 'name' );
839 $email['sender_address'] = ! empty( $notification['evf_from_email'] ) ? $notification['evf_from_email'] : get_option( 'admin_email' );
840 $email['reply_to'] = ! empty( $notification['evf_reply_to'] ) ? $notification['evf_reply_to'] : $email['sender_address'];
841 $email['message'] = ! empty( $notification['evf_email_message'] ) ? $notification['evf_email_message'] : '{all_fields}';
842 $email = apply_filters( 'everest_forms_entry_email_atts', $email, $fields, $entry, $form_data );
843
844 $attachment = '';
845
846 // Create new email.
847 $emails = new EVF_Emails();
848 $emails->__set( 'form_data', $form_data );
849 $emails->__set( 'fields', $fields );
850 $emails->__set( 'entry_id', $entry_id );
851 $emails->__set( 'from_name', $email['sender_name'] );
852 $emails->__set( 'from_address', $email['sender_address'] );
853 $emails->__set( 'reply_to', $email['reply_to'] );
854
855 /**
856 * This filter relies on consistent data being passed for the resultant filters to function.
857 * The third param passed for the filter, $fields, is derived from validation routine, not the DB.
858 */
859 $emails->__set( 'attachments', apply_filters( 'everest_forms_email_file_attachments', $attachment, $fields, $form_data, 'entry-email', $connection_id, $entry_id ) );
860
861 // Maybe include Cc and Bcc email addresses.
862 if ( 'yes' === get_option( 'everest_forms_enable_email_copies' ) ) {
863 if ( ! empty( $notification['evf_carboncopy'] ) ) {
864 $emails->__set( 'cc', $notification['evf_carboncopy'] );
865 }
866 if ( ! empty( $notification['evf_blindcarboncopy'] ) ) {
867 $emails->__set( 'bcc', $notification['evf_blindcarboncopy'] );
868 }
869 }
870
871 $emails = apply_filters( 'everest_forms_entry_email_before_send', $emails );
872
873 // Send entry email.
874 foreach ( $email['address'] as $address ) {
875 $emails->send( trim( $address ), $email['subject'], $email['message'], '', $connection_id );
876 }
877
878 endforeach;
879 }
880
881 /**
882 * Saves entry to database.
883 *
884 * @param array $fields List of form fields.
885 * @param array $entry User submitted data.
886 * @param int $form_id Form ID.
887 * @param array $form_data Prepared form settings.
888 * @return int
889 */
890 public function entry_save( $fields, $entry, $form_id, $form_data = array() ) {
891 global $wpdb;
892
893 // Check if form has entries disabled.
894 if ( isset( $form_data['settings']['disabled_entries'] ) && '1' === $form_data['settings']['disabled_entries'] ) {
895 return;
896 }
897
898 // Provide the opportunity to override via a filter.
899 if ( ! apply_filters( 'everest_forms_entry_save', true, $fields, $entry, $form_data ) ) {
900 return;
901 }
902
903 do_action( 'everest_forms_process_entry_save', $fields, $entry, $form_id, $form_data );
904
905 $fields = apply_filters( 'everest_forms_entry_save_data', $fields, $entry, $form_data );
906 $browser = evf_get_browser();
907 $user_ip = evf_get_ip_address();
908 $user_device = evf_get_user_device();
909 $user_agent = $browser['name'] . '/' . $browser['platform'] . '/' . $user_device;
910 $referer = ! empty( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
911 $entry_id = false;
912
913 // GDPR enhancements - If user details are disabled globally discard the IP and UA.
914 if ( 'yes' === get_option( 'everest_forms_disable_user_details' ) ) {
915 $user_agent = '';
916 $user_ip = '';
917 }
918
919 $entry_data = apply_filters(
920 'everest_forms_entry_data',
921 array(
922 'form_id' => $form_id,
923 'user_id' => get_current_user_id(),
924 'user_device' => sanitize_text_field( $user_agent ),
925 'user_ip_address' => sanitize_text_field( $user_ip ),
926 'status' => 'publish',
927 'referer' => $referer,
928 'fields' => wp_json_encode( $fields ),
929 'date_created' => current_time( 'mysql', true ),
930 ),
931 $entry
932 );
933
934 if ( ! $entry_data['form_id'] ) {
935 return new WP_Error( 'no-form-id', __( 'No form ID was found.', 'everest-forms' ) );
936 }
937
938 // Create entry.
939 $success = $wpdb->insert( $wpdb->prefix . 'evf_entries', $entry_data );
940
941 if ( is_wp_error( $success ) || ! $success ) {
942 return new WP_Error( 'could-not-create', __( 'Could not create an entry', 'everest-forms' ) );
943 }
944
945 $entry_id = $wpdb->insert_id;
946
947 // Create meta data.
948 if ( $entry_id ) {
949 foreach ( $fields as $field ) {
950 $field = apply_filters( 'everest_forms_entry_save_fields', $field, $form_data, $entry_id );
951 // Add only whitelisted fields to entry meta.
952 if ( in_array( $field['type'], array( 'html', 'title' ), true ) ) {
953 continue;
954 }
955
956 // If empty file is supplied, don't store their data nor send email.
957 if ( in_array( $field['type'], array( 'image-upload', 'file-upload' ), true ) ) {
958
959 // BW compatibility for previous file uploader.
960 if ( isset( $field['value']['file_url'] ) && '' === $field['value']['file_url'] ) {
961 continue;
962 }
963 }
964
965 // If empty label is provided for choice field, don't store their data nor send email.
966 if ( in_array( $field['type'], array( 'radio', 'payment-multiple' ), true ) ) {
967 if ( isset( $field['value']['label'] ) && '' === $field['value']['label'] ) {
968 continue;
969 }
970 } elseif ( in_array( $field['type'], array( 'checkbox', 'payment-checkbox' ), true ) ) {
971 if ( isset( $field['value']['label'] ) && ( empty( $field['value']['label'] ) || '' === current( $field['value']['label'] ) ) ) {
972 continue;
973 }
974 }
975
976 if ( isset( $field['meta_key'], $field['value'] ) && '' !== $field['value'] ) {
977 $entry_metadata = array(
978 'entry_id' => $entry_id,
979 'meta_key' => sanitize_key( $field['meta_key'] ),
980 'meta_value' => maybe_serialize( $field['value'] ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
981 );
982
983 // Insert entry meta.
984 $wpdb->insert( $wpdb->prefix . 'evf_entrymeta', $entry_metadata );
985 }
986 }
987 }
988
989 $this->entry_id = $entry_id;
990
991 // Removing Entries Cache.
992 wp_cache_delete( $entry_id, 'evf-entry' );
993 wp_cache_delete( $entry_id, 'evf-entrymeta' );
994 wp_cache_delete( $form_id, 'evf-entries-ids' );
995 wp_cache_delete( $form_id, 'evf-last-entries-count' );
996 wp_cache_delete( $form_id, 'evf-search-entries' );
997 wp_cache_delete( EVF_Cache_Helper::get_cache_prefix( 'entries' ) . '_unread_count', 'entries' );
998
999 do_action( 'everest_forms_complete_entry_save', $entry_id, $fields, $entry, $form_id, $form_data );
1000
1001 return $this->entry_id;
1002 }
1003
1004 /**
1005 * Load Previous Field Value.
1006 *
1007 * @param string $properties Value.
1008 * @param mixed $field Field.
1009 * @param mixed $form_data Form Data.
1010 * @return $properties Properties.
1011 */
1012 public function load_previous_field_value( $properties, $field, $form_data ) {
1013
1014 if ( ! isset( $_POST['everest_forms'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1015 return $properties;
1016 }
1017 $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
1018
1019 if ( 'checkbox' === $field['type'] ) {
1020 foreach ( $field['choices'] as $key => $option_value ) {
1021 $selected = ! empty( $option_value['default'] ) ? $option_value['default'] : '';
1022 foreach ( $data as $value ) {
1023 if ( $value === $option_value['label'] ) {
1024 $selected = 1;
1025 $properties['inputs'][ $key ]['default'] = $selected;
1026 }
1027 }
1028 }
1029 } elseif ( 'radio' === $field['type'] || 'select' === $field['type'] ) {
1030 foreach ( $field['choices'] as $key => $option_value ) {
1031 if ( $data === $option_value['label'] ) { // phpcs:ignore WordPress.Security.NonceVerification
1032 $selected = 1;
1033 $properties['inputs'][ $key ]['default'] = $selected;
1034 }
1035 }
1036 } elseif ( 'likert' === $field['type'] ) {
1037 if ( count( $data ) ) {
1038 foreach ( $data as $row => $col ) {
1039 foreach ( (array) $col as $col_selected ) {
1040 $index = sprintf( 'rows%d_columns%d', (int) $row, (int) $col_selected );
1041 $properties['inputs'][ $index ]['attr']['checked'] = true;
1042 }
1043 }
1044 }
1045 } else {
1046 if ( ! is_array( $data ) ) {
1047 $properties['inputs']['primary']['attr']['value'] = esc_attr( $data );
1048 }
1049 }
1050 return $properties;
1051 }
1052 }
1053