PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.5.2
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.5.2
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 / export / class-evf-entry-csv-exporter.php
everest-forms / includes / export Last commit date
abstract-evf-csv-exporter.php 5 years ago class-evf-entry-csv-exporter.php 2 months ago
class-evf-entry-csv-exporter.php
588 lines
1 <?php
2 /**
3 * Handles entry CSV export.
4 *
5 * @package EverestForms\Export
6 * @since 1.3.0
7 */
8
9 defined( 'ABSPATH' ) || exit;
10
11 /**
12 * Include dependencies.
13 */
14 if ( ! class_exists( 'EVF_CSV_Exporter', false ) ) {
15 require_once EVF_ABSPATH . 'includes/export/abstract-evf-csv-exporter.php';
16 }
17
18 /**
19 * EVF_Entry_CSV_Exporter Class.
20 */
21 class EVF_Entry_CSV_Exporter extends EVF_CSV_Exporter {
22
23 /**
24 * Form ID.
25 *
26 * @var int|mixed
27 */
28 public $form_id;
29
30 /**
31 * Request Data.
32 *
33 * @since 1.8.7
34 * @var array
35 */
36 public $request_data;
37
38 /**
39 * Entry ID.
40 *
41 * @var int|mixed
42 */
43 public $entry_id;
44
45 /**
46 * Type of export used in filter names.
47 *
48 * @var string
49 */
50 protected $export_type = 'entry';
51
52 /**
53 * Constructor.
54 *
55 * @param int $form_id Form ID.
56 * @param int $entry_id Entry ID.
57 * @param array $request_data Request Data.
58 */
59 public function __construct( $form_id = '', $entry_id = '', $request_data = array() ) {
60 $this->form_id = absint( $form_id );
61 $this->entry_id = absint( $entry_id );
62 $this->request_data = $request_data;
63 $this->column_names = $this->get_default_column_names();
64 }
65
66 /**
67 * Return an array of columns to export.
68 *
69 * @return array
70 */
71 public function get_default_column_names() {
72 $columns = array();
73 $form_obj = evf()->form->get( $this->form_id );
74 $form_data = ! empty( $form_obj->post_content ) ? evf_decode( $form_obj->post_content ) : '';
75
76 // Set Entry ID at first.
77 $columns['entry_id'] = esc_html__( 'ID', 'everest-forms' );
78
79 // Add whitelisted fields to export columns.
80 if ( ! empty( $form_data['form_fields'] ) ) {
81 foreach ( $form_data['form_fields'] as $field ) {
82 if ( ! in_array( $field['type'], array( 'html', 'title', 'captcha', 'divider', 'payment_summary', 'private-note' ), true ) ) {
83 switch ( $field['type'] ) {
84 case 'likert':
85 $field_id = $field['id'];
86 foreach ( $field['likert_rows'] as $key => $col_row ) {
87 $col_row_key = "$field_id-likert-$key";
88 $columns[ $col_row_key ] = $col_row;
89 }
90 break;
91 default:
92 $columns[ $field['id'] ] = evf_clean( $field['label'] );
93 break;
94 }
95 }
96 }
97 }
98
99 // Set the default columns.
100 $columns['status'] = esc_html__( 'Status', 'everest-forms' );
101 $columns['date_created'] = esc_html__( 'Date Created', 'everest-forms' );
102 $columns['date_created_gmt'] = esc_html__( 'Date Created GMT', 'everest-forms' );
103
104 // If user details are disabled globally discard the IP and UA.
105 if ( 'yes' !== get_option( 'everest_forms_disable_user_details' ) ) {
106 $columns['user_device'] = esc_html__( 'User Device', 'everest-forms' );
107 $columns['user_ip_address'] = esc_html__( 'User IP Address', 'everest-forms' );
108 }
109
110 return apply_filters( "everest_forms_export_{$this->export_type}_default_columns", $columns, $this->request_data );
111 }
112
113 /**
114 * Prepare data for export.
115 *
116 * @since 1.6.0
117 */
118 public function prepare_data_to_export() {
119 $this->row_data = array();
120
121 if ( $this->entry_id ) {
122 $entry = evf_get_entry( $this->entry_id );
123 $this->row_data[] = $this->generate_row_data( $entry );
124 } else {
125 $entry_ids = evf_search_entries(
126 array(
127 'limit' => -1,
128 'order' => 'ASC',
129 'form_id' => $this->form_id,
130 )
131 );
132
133 // Get the entries.
134 $entries = array_map( 'evf_get_entry', $entry_ids );
135 $checked_entry_id = isset( $_REQUEST['entry'] ) ? wp_parse_id_list( wp_unslash( $_REQUEST['entry'] ) ) : array(); // phpcs:ignore WordPress.Security.NonceVerification
136 foreach ( $entries as $entry ) {
137
138 if ( ! empty( $checked_entry_id ) && ! in_array( absint( $entry->entry_id ), $checked_entry_id, true ) ) {
139 continue;
140 }
141
142 $this->row_data[] = $this->generate_row_data( $entry );
143 }
144 }
145
146 return $this->row_data;
147 }
148
149 /**
150 * Prepare and get quiz report data in CSV format.
151 */
152 public function get_quiz_report() {
153 $form_data = EVF()->form->get(
154 absint( $this->form_id ),
155 array(
156 'content_only' => true,
157 )
158 );
159 $form_fields = isset( $form_data['form_fields'] ) ? $form_data['form_fields'] : array();
160 $entry = evf_get_entry( $this->entry_id );
161 $columns = array( 'ID' );
162 $row = array( $this->entry_id );
163 $total_score = 0;
164 $respondent_score = 0;
165 $obtained_score = 0;
166 $include_all_fields = apply_filters( 'evf_include_all_fields_in_quiz_report_csv', false );
167
168 // Add form fields in the CSV content.
169 foreach ( $form_fields as $field_id => $field ) {
170 $quiz_enabled = isset( $field['quiz_status'] ) && '1' === $field['quiz_status'] ? true : false;
171
172 // Move onto next field if this field has quiz disabled and non-quiz fields are to be excluded.
173 if ( false === $include_all_fields && false === $quiz_enabled ) {
174 continue;
175 }
176
177 $meta_key = isset( $field['meta-key'] ) ? $field['meta-key'] : '';
178 $given_answer = isset( $entry->meta[ $meta_key ] ) ? $entry->meta[ $meta_key ] : null;
179 $correct_answer = isset( $field['correct_answer'] ) ? $field['correct_answer'] : array();
180 $field_score = empty( $field['score'] ) ? 0 : $field['score'];
181 $score = 0;
182 $total_score += $field_score;
183 $is_correct = false;
184
185 if ( ! is_null( $given_answer ) ) {
186 $respondent_score += $field_score;
187
188 if ( ! empty( $correct_answer ) ) {
189 // Determine if the given answer is correct.
190 if ( 'select' === $field['type'] ) {
191 foreach ( $correct_answer as $answer_key => $answer_status ) {
192 $choice = $field['choices'][ $answer_key ]['label'];
193
194 if ( $given_answer === $choice ) {
195 $is_correct = true;
196 break;
197 }
198 }
199 } elseif ( 'radio' === $field['type'] ) {
200 $correct_answer_key = array_keys( $correct_answer )[0];
201 $correct_answer = $field['choices'][ $correct_answer_key ]['label'];
202 $given_answer = evf_maybe_unserialize( $given_answer )['label'];
203 $is_correct = ( $given_answer === $correct_answer );
204 } elseif ( 'checkbox' === $field['type'] ) {
205 $given_answer_data = evf_maybe_unserialize( $given_answer )['label'];
206 $is_correct = true;
207 $choices = $field['choices'];
208 $correct_answer_keys = array_keys( $correct_answer );
209 $correct_answers = array();
210 $given_answers = array();
211
212 // Prepare list of correct answers.
213 foreach ( $correct_answer_keys as $correct_answer_key ) {
214 $correct_answers[] = $choices[ $correct_answer_key ]['label'];
215 }
216
217 // Prepare list of given answers.
218 foreach ( $given_answer_data as $given_answer ) {
219 $given_answers[] = $given_answer;
220 }
221
222 // See if all the given answers are correct answers.
223 foreach ( $given_answers as $given_answer ) {
224 if ( ! in_array( $given_answer, $correct_answers, true ) ) {
225 $is_correct = false;
226 break;
227 }
228 }
229 }
230 }
231 }
232
233 // Add score if the given answer is correct.
234 if ( true === $is_correct ) {
235 $score = $field_score;
236 $obtained_score += $field_score;
237 }
238
239 $columns[] = $this->sanitize_csv_cell_data( $field['label'] );
240 $row[] = $this->sanitize_csv_cell_data( $score );
241 }
242
243 // Add extra columns.
244 $extra_data = array(
245 'Total Score' => $total_score,
246 'Respondent Score' => $respondent_score,
247 'Obtained Score' => $obtained_score,
248 );
249 foreach ( $extra_data as $key => $value ) {
250 $columns[] = $this->sanitize_csv_cell_data( $key );
251 $row[] = $this->sanitize_csv_cell_data( $value );
252 }
253
254 ob_start();
255 echo esc_html( implode( ', ', $columns ) );
256 echo "\n";
257 echo esc_html( implode( ', ', $row ) );
258
259 return ob_get_clean();
260 }
261
262 /**
263 * Sanitize data for a cell in CSV.
264 *
265 * @param string $str Data to sanitize.
266 */
267 public function sanitize_csv_cell_data( $str ) {
268 $str = (string) $str;
269 $str = str_replace( '"', '""', $str );
270 $str = '"' . $str . '"';
271 return $str;
272 }
273
274 /**
275 * Take a entry id and generate row data from it for export.
276 *
277 * @param object $entry Entry object.
278 * @return array
279 */
280 protected function generate_row_data( $entry ) {
281 $columns = $this->get_column_names();
282 $row = array();
283 $fields = json_decode( $entry->fields, true );
284 foreach ( $columns as $column_id => $column_name ) {
285 $column_id = strstr( $column_id, ':' ) ? current( explode( ':', $column_id ) ) : $column_id;
286 $position = strpos( $column_id, '-likert-' );
287
288 if ( $position !== false ) {
289 $column_id = substr( $column_id, 0, $position );
290 }
291
292 $value = '';
293 $raw_value = '';
294
295 if ( isset( $fields[ $column_id ] ) ) {
296 // Filter for entry meta data.
297 $field_type = isset( $fields[ $column_id ]['type'] ) ? $fields[ $column_id ]['type'] : '';
298
299 switch ( $field_type ) {
300 case 'checkbox':
301 case 'payment-checkbox':
302 $value = isset( $fields[ $column_id ]['value']['label'] ) ? $fields[ $column_id ]['value']['label'] : '';
303 if ( is_array( $value ) ) {
304 $value = implode( ',', $value );
305 } else {
306 $value = $value;
307 }
308 break;
309 case 'radio':
310 case 'payment-multiple':
311 $value = $fields[ $column_id ]['value']['label'];
312 break;
313 case 'select':
314 $value = $fields[ $column_id ]['value'];
315 if ( is_array( $value ) ) {
316 $value = implode( ',', $value );
317 } else {
318 $value = $value;
319 }
320
321 break;
322 case 'rating':
323 $value = ! empty( $fields[ $column_id ]['value']['value'] ) ? $fields[ $column_id ]['value']['value'] : 0;
324 $number_of_stars = ! empty( $fields[ $column_id ]['number_of_rating'] ) ? $fields[ $column_id ]['number_of_rating'] : 5;
325 $value = $value . '/' . $number_of_stars;
326 break;
327 case 'country':
328 $value = apply_filters( 'everest_forms_plaintext_field_value', $fields[ $column_id ]['value']['country_code'], $fields[ $column_id ]['value'], $entry, 'email-plain' );
329 break;
330 case 'repeater-fields':
331 $labels = array();
332 $repeater_fields = array();
333 $repeater_accumulator = array();
334 foreach ( $fields[ $column_id ]['value_raw'] as $field_value ) {
335 foreach ( $field_value as $key => $val ) {
336 $repeater_field_value = '';
337 if ( isset( $repeater_fields[ $val['id'] ] ) ) {
338 $repeater_field_type = isset( $repeater_fields[ $val['id'] ]['type'] ) ? $repeater_fields[ $val['id'] ]['type'] : '';
339 switch ( $repeater_field_type ) {
340 case 'checkbox':
341 case 'payment-checkbox':
342 $current_value = is_array( $val['value']['label'] ) ? implode( ', ', $val['value']['label'] ) : $val['value']['label'];
343
344 if ( ! isset( $repeater_accumulator[ $val['id'] ] ) ) {
345 $repeater_accumulator[ $val['id'] ] = array();
346 }
347
348 $repeater_accumulator[ $val['id'] ][] = $current_value;
349 $repeater_field_value = implode( ', ', $repeater_accumulator[ $val['id'] ] );
350 break;
351
352 case 'radio':
353 case 'payment-multiple':
354 $current_value = $val['value']['label'];
355
356 if ( ! isset( $repeater_accumulator[ $val['id'] ] ) ) {
357 $repeater_accumulator[ $val['id'] ] = array();
358 }
359
360 $repeater_accumulator[ $val['id'] ][] = $current_value;
361 $repeater_field_value = implode( ', ', $repeater_accumulator[ $val['id'] ] );
362 break;
363
364 case 'select':
365 $current_value = $val['value'];
366 if ( is_array( $current_value ) ) {
367 $current_value = implode( ', ', $current_value );
368 }
369
370 if ( ! isset( $repeater_accumulator[ $val['id'] ] ) ) {
371 $repeater_accumulator[ $val['id'] ] = array();
372 }
373
374 $repeater_accumulator[ $val['id'] ][] = $current_value;
375 $repeater_field_value = implode( ', ', $repeater_accumulator[ $val['id'] ] );
376 break;
377
378 default:
379 $current_value = $val['value'];
380
381 if ( ! isset( $repeater_accumulator[ $val['id'] ] ) ) {
382 $repeater_accumulator[ $val['id'] ] = array();
383 }
384
385 $repeater_accumulator[ $val['id'] ][] = $current_value;
386 $repeater_field_value = implode( ', ', $repeater_accumulator[ $val['id'] ] );
387 break;
388 }
389 } else {
390 $repeater_fields[ $val['id'] ] = $val;
391
392 $current_value = is_array( $val['value'] ) && isset( $val['value']['label'] )
393 ? $val['value']['label']
394 : $val['value'];
395
396 if ( is_array( $current_value ) ) {
397 $current_value = implode( ', ', $current_value );
398 }
399
400 $repeater_accumulator[ $val['id'] ][] = $current_value;
401 $repeater_field_value = $current_value;
402 }
403
404 $fields[ $key ]['value'] = $repeater_field_value;
405
406 $labels[] = isset( $val['name'] )
407 ? $val['name']
408 : ( is_array( $val['value'] ) && isset( $val['value']['name'] )
409 ? $val['value']['name']
410 : '' );
411 }
412 }
413
414 $labels = array_unique( $labels );
415
416 $value = implode( ', ', array_filter( $labels ) );
417 $fields[ $column_id ]['value'] = $value;
418 break;
419 case 'likert':
420 $form = evf()->form->get( $entry->form_id );
421 $form_data = evf_decode( $form->post_content );
422 $form_fields = $form_data['form_fields'];
423 $form_field = '';
424 $selected_likert = array();
425 if ( array_key_exists( $column_id, $form_fields ) ) {
426 $form_field = $form_fields[ $column_id ];
427 $likert_columns = $form_field['likert_columns'];
428 $likert_rows = $form_field['likert_rows'];
429 if ( ! empty( $fields[ $column_id ]['value_raw'] ) ) {
430 foreach ( $fields[ $column_id ]['value_raw'] as $likert_key ) {
431 $selected_likert[] = $likert_columns[ $likert_key ];
432 }
433 } else {
434 foreach ( $likert_rows as $likert_rows ) {
435 $selected_likert[] = '';
436 }
437 }
438 }
439 $value = $selected_likert;
440 break;
441 default:
442 $value = apply_filters( 'everest_forms_html_field_value', $fields[ $column_id ]['value'], $fields[ $column_id ], $entry, 'export-csv' );
443 break;
444 }
445 } elseif ( is_callable( array( $this, "get_column_value_{$column_id}" ) ) ) {
446 // Handle special columns which don't map 1:1 to entry data.
447 $value = $this->{"get_column_value_{$column_id}"}( $entry );
448 $raw_value = $value;
449 }
450 $column_type = $this->get_entry_type( $column_id, $entry );
451 if ( is_array( $value ) && isset( $fields[ $column_id ], $fields[ $column_id ]['type'] ) && in_array( $fields[ $column_id ]['type'], array( 'likert' ), true ) ) {
452 foreach ( $value as $key => $val ) {
453 $key = $key + 1;
454 $col_row_key = "$column_id-likert-$key";
455 $row[ $col_row_key ] = $val;
456 }
457 } else {
458 // It is done to display the currencies symbol instead of its HTML entities values.
459 $clean_value = html_entity_decode(
460 preg_match( '/textarea/', $column_type ) ? sanitize_textarea_field( $value ) : sanitize_text_field( $value ),
461 ENT_QUOTES,
462 'UTF-8'
463 );
464
465 $row[ $column_id ] = apply_filters(
466 'everest_forms_format_csv_field_data',
467 $clean_value,
468 $raw_value,
469 $column_id,
470 $column_name,
471 $columns,
472 $entry
473 );
474
475 }
476 if ( empty( $this->request_data ) ) {
477 $row['status'] = (
478 isset( $entry->meta['status'] ) && ! empty( $entry->meta['status'] )
479 ? $entry->meta['status']
480 : ( isset( $row['status'] ) ? $row['status'] : '' )
481 );
482 }
483 }
484
485 return apply_filters( 'everest_forms_entry_export_row_data', $row, $entry, $this->request_data );
486 }
487
488 /**
489 * Get entry type.
490 *
491 * @param string $column_id meta key of the column.
492 * @param object $entry Entry being exported.
493 * @return string
494 */
495 protected function get_entry_type( $column_id, $entry ) {
496 $fields = json_decode( $entry->fields, 1 );
497 if ( is_null( $fields ) || ! is_array( $fields ) ) {
498 return false; // Conditional false with fake values.
499 }
500 foreach ( $fields as $field ) {
501 if ( $column_id === $field['id'] ) {
502 return $field['type'];
503 }
504 }
505 return false;
506 }
507
508 /**
509 * Get entry id value.
510 *
511 * @param object $entry Entry being exported.
512 * @return int
513 */
514 protected function get_column_value_entry_id( $entry ) {
515 return absint( $entry->entry_id );
516 }
517
518 /**
519 * Get entry status value.
520 *
521 * @param object $entry Entry being exported.
522 * @return string
523 */
524 protected function get_column_value_status( $entry ) {
525 $statuses = evf_get_entry_statuses();
526
527 if ( isset( $statuses[ $entry->status ] ) ) {
528 return $statuses[ $entry->status ];
529 }
530
531 return $entry->status;
532 }
533
534 /**
535 * Get date created value.
536 *
537 * @param object $entry Entry being exported.
538 * @return string
539 */
540 protected function get_column_value_date_created( $entry ) {
541 $timestamp = false;
542
543 if ( isset( $entry->date_created ) ) {
544 $timestamp = strtotime( $entry->date_created );
545 }
546
547 /* translators: 1: entry date 2: entry time */
548 return sprintf( esc_html__( '%1$s %2$s', 'everest-forms' ), date_i18n( evf_date_format(), $timestamp ), date_i18n( evf_time_format(), $timestamp ) );
549 }
550
551 /**
552 * Get GMT date created value.
553 *
554 * @param object $entry Entry being exported.
555 * @return string
556 */
557 protected function get_column_value_date_created_gmt( $entry ) {
558 $timestamp = false;
559
560 if ( isset( $entry->date_created ) ) {
561 $timestamp = strtotime( $entry->date_created ) + ( get_option( 'gmt_offset' ) * 3600 );
562 }
563
564 /* translators: 1: entry date 2: entry time */
565 return sprintf( esc_html__( '%1$s %2$s', 'everest-forms' ), date_i18n( evf_date_format(), $timestamp ), date_i18n( evf_time_format(), $timestamp ) );
566 }
567
568 /**
569 * Get entry user device value.
570 *
571 * @param object $entry Entry being exported.
572 * @return string
573 */
574 protected function get_column_value_user_device( $entry ) {
575 return sanitize_text_field( $entry->user_device );
576 }
577
578 /**
579 * Get entry user IP address value.
580 *
581 * @param object $entry Entry being exported.
582 * @return string
583 */
584 protected function get_column_value_user_ip_address( $entry ) {
585 return sanitize_text_field( $entry->user_ip_address );
586 }
587 }
588