PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.29
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.29
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / controllers / FrmEntriesController.php

FrmEntriesController.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.29, at classes/controllers/FrmEntriesController.php

981 lines 26.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmEntriesController {
7
8 /**
9 * @return void
10 */
11 public static function menu() {
12 FrmAppHelper::force_capability( 'frm_view_entries' );
13
14 add_submenu_page( 'formidable', 'Formidable | ' . __( 'Entries', 'formidable' ), __( 'Entries', 'formidable' ), 'frm_view_entries', 'formidable-entries', 'FrmEntriesController::route' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
15
16 $views_installed = is_callable( 'FrmProAppHelper::views_is_installed' ) && FrmProAppHelper::views_is_installed();
17
18 if ( $views_installed ) {
19 self::maybe_redirect_to_views_index();
20 } else {
21 add_submenu_page( 'formidable', 'Formidable | ' . __( 'Views', 'formidable' ), __( 'Views', 'formidable' ), 'frm_view_entries', 'formidable-views', 'FrmFormsController::no_views' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
22 self::maybe_redirect_to_views_upsell();
23 }
24
25 if ( FrmAppHelper::is_admin_page( 'formidable-entries' ) ) {
26 self::load_manage_entries_hooks();
27 }
28 }
29
30 /**
31 * This function is called when views is installed.
32 * The Views add-on uses a different URL for the Views tab than the upsell page.
33 * If the user is on the upsell page, instead of showing a permission error on reload,
34 * redirect to the views index page.
35 *
36 * @since 6.14.1
37 *
38 * @return void
39 */
40 private static function maybe_redirect_to_views_index() {
41 if ( ! FrmAppHelper::is_admin_page( 'formidable-views' ) ) {
42 return;
43 }
44
45 $query_args = array(
46 'post_type' => 'frm_display',
47 );
48 $query_args = self::add_url_params_to_views_redirect_query_args( $query_args );
49
50 wp_safe_redirect( add_query_arg( $query_args, admin_url( 'edit.php' ) ) );
51 die();
52 }
53
54 /**
55 * This function is called when views is inactive.
56 * A user may deactivate views but then try to reload the views index.
57 * Instead of showing a permission error, redirect to the views upsell page.
58 *
59 * @since 6.14.1
60 *
61 * @return void
62 */
63 private static function maybe_redirect_to_views_upsell() {
64 global $pagenow;
65
66 if ( 'edit.php' !== $pagenow || 'frm_display' !== FrmAppHelper::simple_get( 'post_type' ) ) {
67 return;
68 }
69
70 $query_args = array(
71 'page' => 'formidable-views',
72 );
73 $query_args = self::add_url_params_to_views_redirect_query_args( $query_args );
74
75 wp_safe_redirect( add_query_arg( $query_args, admin_url( 'admin.php' ) ) );
76 die();
77 }
78
79 /**
80 * @since 6.14.1
81 *
82 * @param array $query_args
83 *
84 * @return array
85 */
86 private static function add_url_params_to_views_redirect_query_args( $query_args ) {
87 $query_args['show_nav'] = FrmAppHelper::simple_get( 'show_nav', 'absint', 0 );
88 $form_id = FrmAppHelper::simple_get( 'form', 'absint', 0 );
89
90 if ( $form_id ) {
91 $query_args['form'] = $form_id;
92 }
93
94 return $query_args;
95 }
96
97 /**
98 * @since 2.05.07
99 *
100 * @return void
101 */
102 private static function load_manage_entries_hooks() {
103 if ( in_array( FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' ), array( 'edit', 'show', 'new', 'duplicate' ), true ) ) {
104 add_filter( 'screen_options_show_screen', self::class . '::remove_screen_options', 10, 2 );
105 return;
106 }
107
108 $menu_name = FrmAppHelper::get_menu_name();
109 $base = self::base_column_key( $menu_name );
110
111 add_filter( 'manage_' . $base . '_columns', 'FrmEntriesController::manage_columns' );
112 add_filter( 'get_user_option_' . self::hidden_column_key( $menu_name ), 'FrmEntriesController::hidden_columns' );
113 add_filter( 'manage_' . $base . '_sortable_columns', 'FrmEntriesController::sortable_columns' );
114 }
115
116 /**
117 * Display in Back End.
118 *
119 * @return mixed
120 */
121 public static function route() {
122 $action = FrmAppHelper::get_param( 'frm_action', '', 'get', 'sanitize_title' );
123 FrmAppHelper::include_svg();
124
125 switch ( $action ) {
126 case 'show':
127 case 'destroy':
128 return self::$action();
129
130 default:
131 do_action( 'frm_entry_action_route', $action );
132
133 if ( apply_filters( 'frm_entry_stop_action_route', false, $action ) ) {
134 return null;
135 }
136
137 self::display_list();
138 return null;
139 }
140 }
141
142 /**
143 * Prevent the "screen options" tab from showing when
144 * editing or creating an entry
145 *
146 * @since 3.0
147 *
148 * @param bool $show_screen Whether to show the screen options tab.
149 * @param object $screen The current screen object.
150 *
151 * @return bool
152 */
153 public static function remove_screen_options( $show_screen, $screen ) {
154 $menu_name = sanitize_title( FrmAppHelper::get_menu_name() );
155 $unread_count = FrmEntriesHelper::get_visible_unread_inbox_count();
156
157 if ( $screen->id === $menu_name . ( $unread_count ? '-' . $unread_count : '' ) . '_page_formidable-entries' ) {
158 return false;
159 }
160
161 return $show_screen;
162 }
163
164 /**
165 * @param array $columns
166 *
167 * @return array
168 */
169 public static function manage_columns( $columns ) {
170 global $frm_vars;
171 $form_id = FrmForm::get_current_form_id();
172
173 $columns[ $form_id . '_id' ] = 'ID';
174 $columns[ $form_id . '_item_key' ] = esc_html__( 'Entry Key', 'formidable' );
175
176 if ( $form_id ) {
177 self::get_columns_for_form( $form_id, $columns );
178 } else {
179 $columns[ $form_id . '_form_id' ] = esc_html__( 'Form', 'formidable' );
180 $columns[ $form_id . '_name' ] = esc_html__( 'Entry Name', 'formidable' );
181 $columns[ $form_id . '_user_id' ] = esc_html__( 'Created By', 'formidable' );
182 }
183
184 $columns[ $form_id . '_is_draft' ] = esc_html__( 'Entry Status', 'formidable' );
185 $columns[ $form_id . '_created_at' ] = esc_html__( 'Entry creation date', 'formidable' );
186 $columns[ $form_id . '_updated_at' ] = esc_html__( 'Entry update date', 'formidable' );
187 self::maybe_add_ip_col( $form_id, $columns );
188
189 $frm_vars['cols'] = $columns;
190 $action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
191
192 if ( FrmAppHelper::is_admin_page( 'formidable-entries' ) && in_array( $action, array( '', 'list', 'destroy' ), true ) ) {
193 add_screen_option(
194 'per_page',
195 array(
196 'label' => esc_html__( 'Entries', 'formidable' ),
197 'default' => 20,
198 'option' => 'formidable_page_formidable_entries_per_page',
199 )
200 );
201 }
202
203 return $columns;
204 }
205
206 /**
207 * @param int|string $form_id
208 * @param array $columns
209 *
210 * @return void
211 */
212 private static function get_columns_for_form( $form_id, &$columns ) {
213 $form_cols = FrmField::get_all_for_form( $form_id, '', 'include' );
214
215 /**
216 * Allows changing fields in the Entries list table heading.
217 *
218 * @since 5.0.04
219 *
220 * @param array $fields Array of fields.
221 * @param array $args The arguments. Contains `form_id`.
222 */
223 $form_cols = apply_filters( 'frm_fields_in_entries_list_table', $form_cols, compact( 'form_id' ) );
224
225 foreach ( $form_cols as $form_col ) {
226 if ( FrmField::is_no_save_field( $form_col->type ) ) {
227 continue;
228 }
229
230 $has_child_fields = $form_col->type === 'form' && ! empty( $form_col->field_options['form_select'] );
231
232 if ( $has_child_fields ) {
233 self::add_subform_cols( $form_col, $form_id, $columns );
234 } else {
235 self::add_field_cols( $form_col, $form_id, $columns );
236 }
237 }
238 }
239
240 /**
241 * @since 3.01
242 *
243 * @param object $field The field object.
244 * @param int|string $form_id The form ID.
245 * @param array $columns The columns array.
246 *
247 * @return void
248 */
249 private static function add_subform_cols( $field, $form_id, &$columns ) {
250 $sub_form_cols = FrmField::get_all_for_form( $field->field_options['form_select'] );
251
252 if ( ! $sub_form_cols ) {
253 return;
254 }
255
256 foreach ( $sub_form_cols as $k => $sub_form_col ) {
257 if ( FrmField::is_no_save_field( $sub_form_col->type ) ) {
258 unset( $sub_form_cols[ $k ] );
259 continue;
260 }
261
262 $columns[ $form_id . '_' . $sub_form_col->field_key . '-_-' . $field->id ] = FrmAppHelper::truncate( $sub_form_col->name, 35 );
263 unset( $sub_form_col );
264 }
265 }
266
267 /**
268 * @since 3.01
269 *
270 * @param object $field The field object.
271 * @param int|string $form_id The form ID.
272 * @param array $columns The columns array.
273 *
274 * @return void
275 */
276 private static function add_field_cols( $field, $form_id, &$columns ) {
277 $col_id = $field->field_key;
278
279 if ( (int) $field->form_id !== (int) $form_id ) {
280 $col_id .= '-_-form' . $field->form_id;
281 }
282
283 $has_separate_value = ! FrmField::is_option_empty( $field, 'separate_value' );
284 $is_post_status = FrmField::is_option_true( $field, 'post_field' ) && $field->field_options['post_field'] === 'post_status';
285 $include_column_for_sep_val = $has_separate_value && ! $is_post_status;
286
287 if ( $include_column_for_sep_val ) {
288 $columns[ $form_id . '_frmsep_' . $col_id ] = self::maybe_format_field_name_for_column_title( $field, $include_column_for_sep_val );
289 }
290
291 $columns[ $form_id . '_' . $col_id ] = self::maybe_format_field_name_for_column_title( $field, $include_column_for_sep_val, false );
292 }
293
294 /**
295 * Appends "(Value)" or "(Label)" to the field name if it's an option field that has a separate value/label.
296 *
297 * @since 6.25.1
298 *
299 * @param object $field
300 * @param bool $include_column_for_sep_val
301 * @param bool $is_value
302 *
303 * @return string
304 */
305 private static function maybe_format_field_name_for_column_title( $field, $include_column_for_sep_val, $is_value = true ) {
306 $field_name = FrmAppHelper::truncate( $field->name, 35 );
307
308 if ( ! $include_column_for_sep_val || ! in_array( $field->type, array( 'select', 'radio', 'checkbox' ), true ) ) {
309 return $field_name;
310 }
311
312 $append_text = $is_value ? esc_html__( 'value', 'formidable' ) : esc_html__( 'label', 'formidable' );
313
314 return sprintf( '%s (%s)', $field_name, $append_text );
315 }
316
317 /**
318 * @param int|string $form_id The form ID.
319 * @param array $columns The columns array.
320 *
321 * @return void
322 */
323 private static function maybe_add_ip_col( $form_id, &$columns ) {
324 if ( FrmAppHelper::ips_saved() ) {
325 $columns[ $form_id . '_ip' ] = 'IP';
326 }
327 }
328
329 /**
330 * @param bool $check The check value.
331 * @param int $object_id The object ID.
332 * @param string $meta_key The meta key.
333 * @param mixed $meta_value The meta value.
334 * @param mixed $prev_value The previous value.
335 *
336 * @return bool
337 */
338 public static function check_hidden_cols( $check, $object_id, $meta_key, $meta_value, $prev_value ) {
339 $this_page_name = self::hidden_column_key();
340
341 // phpcs:ignore Universal.Operators.StrictComparisons
342 if ( $meta_key != $this_page_name || $meta_value == $prev_value ) {
343 return $check;
344 }
345
346 if ( ! $prev_value ) {
347 $prev_value = get_metadata( 'user', $object_id, $meta_key, true );
348 }
349
350 global $frm_vars;
351 // Add a check so we don't create a loop.
352 $frm_vars['prev_hidden_cols'] = ! empty( $frm_vars['prev_hidden_cols'] ) ? false : $prev_value;
353
354 return $check;
355 }
356
357 /**
358 * Add hidden columns back from other forms
359 *
360 * @param int $meta_id The meta ID.
361 * @param int $object_id The object ID.
362 * @param string $meta_key The meta key.
363 * @param array $meta_value The meta value.
364 *
365 * @return void
366 */
367 public static function update_hidden_cols( $meta_id, $object_id, $meta_key, $meta_value ) {
368 $this_page_name = self::hidden_column_key();
369
370 // phpcs:ignore Universal.Operators.StrictComparisons
371 if ( $meta_key != $this_page_name ) {
372 return;
373 }
374
375 global $frm_vars;
376
377 if ( empty( $frm_vars['prev_hidden_cols'] ) ) {
378 // Don't continue if there's no previous value.
379 return;
380 }
381
382 foreach ( $meta_value as $mk => $mv ) {
383 // Remove blank values.
384 if ( ! $mv ) {
385 unset( $meta_value[ $mk ] );
386 }
387 }
388
389 $cur_form_prefix = reset( $meta_value );
390 $cur_form_prefix = explode( '_', $cur_form_prefix );
391 $cur_form_prefix = $cur_form_prefix[0];
392 $save = false;
393
394 foreach ( (array) $frm_vars['prev_hidden_cols'] as $prev_hidden ) {
395 // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
396 if ( ! $prev_hidden || in_array( $prev_hidden, $meta_value ) ) {
397 // Don't add blank cols or process included cols.
398 continue;
399 }
400
401 $form_prefix = explode( '_', $prev_hidden );
402 $form_prefix = $form_prefix[0];
403
404 if ( $form_prefix === $cur_form_prefix ) {
405 // Don't add back columns that are meant to be hidden.
406 continue;
407 }
408
409 $meta_value[] = $prev_hidden;
410 $save = true;
411 unset( $form_prefix );
412 }
413
414 if ( ! $save ) {
415 return;
416 }
417
418 $user_id = get_current_user_id();
419 update_user_option( $user_id, $this_page_name, $meta_value, true );
420 }
421
422 /**
423 * @since 2.05.07
424 *
425 * @param string $menu_name
426 *
427 * @return string
428 */
429 private static function hidden_column_key( $menu_name = '' ) {
430 $base = self::base_column_key( $menu_name );
431 return 'manage' . $base . 'columnshidden';
432 }
433
434 /**
435 * @since 2.05.07
436 *
437 * @param string $menu_name
438 *
439 * @return string
440 */
441 private static function base_column_key( $menu_name = '' ) {
442 if ( ! $menu_name ) {
443 $menu_name = FrmAppHelper::get_menu_name();
444 }
445
446 $unread_count = FrmEntriesHelper::get_visible_unread_inbox_count();
447
448 return sanitize_title( $menu_name ) . ( $unread_count ? '-' . $unread_count : '' ) . '_page_formidable-entries';
449 }
450
451 /**
452 * @param int $save
453 * @param string $option
454 * @param string $value
455 *
456 * @return int
457 */
458 public static function save_per_page( $save, $option, $value ) {
459 if ( $option === 'formidable_page_formidable_entries_per_page' ) {
460 return (int) $value;
461 }
462
463 return $save;
464 }
465
466 /**
467 * @return array
468 */
469 public static function sortable_columns() {
470 $form_id = FrmForm::get_current_form_id();
471 $fields = FrmField::get_all_for_form( $form_id );
472
473 $columns = array(
474 $form_id . '_id' => 'id',
475 $form_id . '_created_at' => 'created_at',
476 $form_id . '_updated_at' => 'updated_at',
477 $form_id . '_ip' => 'ip',
478 $form_id . '_item_key' => 'item_key',
479 $form_id . '_is_draft' => 'is_draft',
480 );
481
482 if ( ! $form_id ) {
483 $columns[ $form_id . '_user_id' ] = 'user_id';
484 $columns[ $form_id . '_name' ] = 'name';
485 $columns[ $form_id . '_form_id' ] = 'form_id';
486 }
487
488 foreach ( $fields as $field ) {
489 if ( self::field_supports_sorting( $field ) ) {
490 $columns[ $form_id . '_' . $field->field_key ] = 'meta_' . $field->id;
491 }
492 }
493
494 return $columns;
495 }
496
497 /**
498 * Can't sort on checkboxes because they are sorted serialized.
499 * Some post content can be sorted but not everything.
500 *
501 * @param stdClass $field
502 *
503 * @return bool
504 */
505 private static function field_supports_sorting( $field ) {
506 $is_sortable = 'checkbox' !== $field->type && empty( $field->field_options['post_field'] );
507 return apply_filters( 'frm_field_column_is_sortable', $is_sortable, $field );
508 }
509
510 /**
511 * @param mixed $result Option value from database for hidden columns in entries table.
512 *
513 * @return array
514 */
515 public static function hidden_columns( $result ) {
516 global $frm_vars;
517
518 if ( ! is_array( $result ) ) {
519 // Force an unexpected value to be an array.
520 // Since $result is a filtered option and gets saved to the database, it's possible it could be a string.
521 // Since this code expects an array it would break with a "Uncaught Error: [] operator not supported for strings" error.
522 $result = array();
523 }
524
525 $form_id = FrmForm::get_current_form_id();
526 $hidden = self::user_hidden_columns_for_form( $form_id, $result );
527 $i = isset( $frm_vars['cols'] ) ? count( $frm_vars['cols'] ) : 0;
528 $max_columns = 11;
529
530 if ( $hidden ) {
531 $result = $hidden;
532 $i = $i - count( $result );
533 }
534
535 if ( $i <= $max_columns ) {
536 return $result;
537 }
538
539 self::remove_excess_cols( compact( 'i', 'max_columns', 'form_id' ), $result );
540
541 return $result;
542 }
543
544 /**
545 * @since 2.05.07
546 *
547 * @param int|string $form_id
548 * @param mixed $result
549 *
550 * @return array
551 */
552 private static function user_hidden_columns_for_form( $form_id, $result ) {
553 $hidden = array();
554
555 foreach ( (array) $result as $r ) {
556 if ( ! $r ) {
557 continue;
558 }
559
560 list( $form_prefix, $field_key ) = explode( '_', $r );
561
562 if ( (int) $form_prefix === (int) $form_id ) {
563 $hidden[] = $r;
564 }
565
566 unset( $form_prefix );
567 }
568
569 return $hidden;
570 }
571
572 /**
573 * Remove some columns by default when there are too many
574 *
575 * @since 2.05.07
576 *
577 * @param array $atts
578 * @param array $result
579 *
580 * @return void
581 */
582 private static function remove_excess_cols( $atts, &$result ) {
583 global $frm_vars;
584
585 $remove_first = array(
586 $atts['form_id'] . '_item_key' => '',
587 $atts['form_id'] . '_id' => '',
588 );
589 $cols = $remove_first + array_reverse( $frm_vars['cols'], true );
590 $i = $atts['i'];
591
592 foreach ( $cols as $col_key => $col ) {
593 if ( $i <= $atts['max_columns'] ) {
594 break;
595 }
596
597 if ( ! $result || ! in_array( $col_key, $result, true ) ) {
598 $result[] = $col_key;
599 --$i;
600 }
601
602 unset( $col_key, $col );
603 }
604 }
605
606 /**
607 * @param string $message
608 * @param array $errors
609 *
610 * @return void
611 */
612 public static function display_list( $message = '', $errors = array() ) {
613 global $wpdb, $frm_vars;
614
615 $form = FrmForm::maybe_get_current_form();
616 $params = FrmForm::get_admin_params( $form );
617
618 if ( $form ) {
619 $params['form'] = $form->id;
620 $frm_vars['current_form'] = $form;
621
622 self::get_delete_form_time( $form, $errors );
623 }
624
625 $table_class = apply_filters( 'frm_entries_list_class', 'FrmEntriesListHelper' );
626 $wp_list_table = new $table_class( array( 'params' => $params ) );
627 $pagenum = $wp_list_table->get_pagenum();
628
629 $wp_list_table->prepare_items();
630
631 $total_pages = $wp_list_table->get_pagination_arg( 'total_pages' );
632
633 if ( $pagenum > $total_pages && $total_pages > 0 ) {
634 $url = add_query_arg( 'paged', $total_pages );
635
636 if ( headers_sent() ) {
637 FrmAppHelper::js_redirect( $url, true );
638 } else {
639 wp_safe_redirect( esc_url_raw( $url ) );
640 }
641
642 die();
643 }
644
645 if ( ! $message && isset( $_GET['import-message'] ) ) {
646 $message = __( 'Your import is complete', 'formidable' );
647 }
648
649 require FrmAppHelper::plugin_path() . '/classes/views/frm-entries/list.php';
650 }
651
652 /**
653 * @param object $form
654 * @param array $errors
655 *
656 * @return void
657 */
658 private static function get_delete_form_time( $form, &$errors ) {
659 if ( 'trash' !== $form->status ) {
660 return;
661 }
662
663 $delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
664 $time_to_delete = FrmAppHelper::human_time_diff( $delete_timestamp, $form->options['trash_time'] ?? time() );
665
666 /* translators: %1$s: Time string */
667 $errors['trash'] = sprintf( __( 'This form is in the trash and is scheduled to be deleted permanently in %s along with any entries.', 'formidable' ), $time_to_delete );
668 }
669
670 /**
671 * Back End CRUD.
672 *
673 * @param int $id
674 *
675 * @return void
676 */
677 public static function show( $id = 0 ) {
678 FrmAppHelper::permission_check( 'frm_view_entries' );
679
680 if ( ! $id ) {
681 $id = FrmAppHelper::get_param( 'id', 0, 'get', 'absint' );
682
683 if ( ! $id ) {
684 $id = FrmAppHelper::get_param( 'item_id', 0, 'get', 'absint' );
685 }
686 }
687
688 $entry = FrmEntry::getOne( $id, true );
689
690 if ( ! $entry ) {
691 FrmAppController::show_error_modal(
692 array(
693 'title' => __( 'You can\'t view the entry', 'formidable' ),
694 'body' => __( 'You are trying to view an entry that does not exist', 'formidable' ),
695 'cancel_url' => admin_url( 'admin.php?page=formidable' ),
696 )
697 );
698 return;
699 }
700
701 $data = $entry->description;
702
703 if ( ! is_array( $data ) || ! isset( $data['referrer'] ) ) {
704 $data = array( 'referrer' => $data );
705 }
706
707 $fields = FrmField::get_all_for_form( $entry->form_id, '', 'include' );
708 $form = FrmForm::getOne( $entry->form_id );
709
710 include FrmAppHelper::plugin_path() . '/classes/views/frm-entries/show.php';
711 }
712
713 /**
714 * Destroy an entry from the admin page.
715 * This is triggered from the entries list from the "Delete" row action, and also from the "Delete Entry" trigger in the view/edit entry sidebar.
716 *
717 * @return void
718 */
719 public static function destroy() {
720 $permission_error = FrmAppHelper::permission_nonce_error( 'frm_delete_entries', '_wpnonce', -1 );
721
722 if ( false !== $permission_error ) {
723 $error_args = array(
724 'title' => __( 'Verification failed', 'formidable' ),
725 'body' => $permission_error,
726 'cancel_url' => admin_url( 'admin.php?page=formidable-entries' ),
727 );
728 FrmAppController::show_error_modal( $error_args );
729 return;
730 }
731
732 $params = FrmForm::get_admin_params();
733
734 if ( ! empty( $params['keep_post'] ) ) {
735 self::unlink_post( $params['id'] );
736 }
737
738 $message = '';
739
740 if ( FrmEntry::destroy( $params['id'] ) ) {
741 $message = __( 'Entry was successfully deleted', 'formidable' );
742 }
743
744 self::display_list( $message );
745 }
746
747 /**
748 * @param array|string $errors
749 * @param bool $ajax
750 *
751 * @return void
752 */
753 public static function process_entry( $errors = '', $ajax = false ) {
754 $form_id = FrmAppHelper::get_post_param( 'form_id', '', 'absint' );
755
756 if ( FrmAppHelper::is_admin() || empty( $_POST ) || ! $form_id || ! isset( $_POST['item_key'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
757 return;
758 }
759
760 global $frm_vars;
761
762 $form = FrmForm::getOne( $form_id );
763
764 if ( ! $form ) {
765 return;
766 }
767
768 $is_preview = 'frm_forms_preview' === FrmAppHelper::simple_get( 'action' );
769
770 if ( $is_preview && FrmFormsHelper::should_block_preview( $form->form_key ) ) {
771 return;
772 }
773
774 $params = FrmForm::get_params( $form );
775
776 if ( ! isset( $frm_vars['form_params'] ) ) {
777 $frm_vars['form_params'] = array();
778 }
779 $frm_vars['form_params'][ $form->id ] = $params;
780
781 if ( isset( $frm_vars['created_entries'][ $form_id ] ) ) {
782 return;
783 }
784
785 // phpcs:ignore Universal.Operators.StrictComparisons
786 if ( $errors == '' && ! $ajax ) {
787 $errors = FrmEntryValidate::validate( wp_unslash( $_POST ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
788 }
789
790 /**
791 * Use this filter to add trigger actions and add errors after
792 * all other errors have been processed
793 *
794 * @since 2.0.6
795 */
796 $errors = apply_filters( 'frm_entries_before_create', $errors, $form );
797
798 $frm_vars['created_entries'][ $form_id ] = array( 'errors' => $errors );
799
800 if ( $errors ) {
801 return;
802 }
803
804 $_POST['frm_skip_cookie'] = 1;
805 $do_success = false;
806
807 if ( $params['action'] === 'create' && apply_filters( 'frm_continue_to_create', true, $form_id ) && ! isset( $frm_vars['created_entries'][ $form_id ]['entry_id'] ) ) {
808 $frm_vars['created_entries'][ $form_id ]['entry_id'] = FrmEntry::create( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
809
810 $params['id'] = $frm_vars['created_entries'][ $form_id ]['entry_id'];
811 $do_success = true;
812 }
813
814 do_action( 'frm_process_entry', $params, $errors, $form, array( 'ajax' => $ajax ) );
815
816 if ( $do_success ) {
817 FrmFormsController::maybe_trigger_redirect( $form, $params, array( 'ajax' => $ajax ) );
818 }
819 unset( $_POST['frm_skip_cookie'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
820 }
821
822 /**
823 * Escape url entities before redirect
824 *
825 * @since 3.0
826 *
827 * @param string $url
828 *
829 * @return string
830 */
831 public static function prepare_redirect_url( $url ) {
832 return str_replace( array( ' ', '[', ']', '|', '@' ), array( '%20', '%5B', '%5D', '%7C', '%40' ), $url );
833 }
834
835 /**
836 * Delete entry if redirected.
837 *
838 * @param string $url
839 * @param object $form
840 * @param array $atts
841 *
842 * @return string
843 */
844 public static function delete_entry_before_redirect( $url, $form, $atts ) {
845 self::_delete_entry( $atts['id'], $form );
846 return $url;
847 }
848
849 /**
850 * Delete entry if not redirected.
851 *
852 * @param array $atts
853 *
854 * @return void
855 */
856 public static function delete_entry_after_save( $atts ) {
857 self::_delete_entry( $atts['entry_id'], $atts['form'] );
858 }
859
860 /**
861 * Delete entry if not redirected.
862 *
863 * @param int $entry_id
864 * @param object $form
865 *
866 * @return void
867 */
868 private static function _delete_entry( $entry_id, $form ) {
869 if ( ! $form ) {
870 return;
871 }
872
873 FrmAppHelper::unserialize_or_decode( $form->options );
874
875 if ( empty( $form->options['no_save'] ) ) {
876 return;
877 }
878
879 self::unlink_post( $entry_id );
880 FrmEntry::destroy( $entry_id );
881 }
882
883 /**
884 * Unlink entry from post
885 *
886 * @param int $entry_id
887 *
888 * @return void
889 */
890 private static function unlink_post( $entry_id ) {
891 global $wpdb;
892 $wpdb->update( $wpdb->prefix . 'frm_items', array( 'post_id' => '' ), array( 'id' => $entry_id ) );
893 FrmEntry::clear_cache();
894 }
895
896 /**
897 * @param array $atts
898 *
899 * @return array|string
900 */
901 public static function show_entry_shortcode( $atts ) {
902 $defaults = array(
903 'id' => false,
904 'entry' => false,
905 'fields' => false,
906 'plain_text' => false,
907 'user_info' => false,
908 'include_blank' => false,
909 'default_email' => false,
910 'form_id' => false,
911 'format' => 'text',
912 'array_key' => 'key',
913 'direction' => 'ltr',
914 'font_size' => '',
915 'text_color' => '',
916 'border_width' => '',
917 'border_color' => '',
918 'bg_color' => '',
919 'alt_bg_color' => '',
920 'class' => '',
921 'clickable' => false,
922 'exclude_fields' => '',
923 'include_fields' => '',
924 'include_extras' => '',
925 'inline_style' => 1,
926 'table_style' => '',
927 // Return embedded fields as nested array.
928 'child_array' => false,
929 'line_breaks' => true,
930 'array_separator' => ', ',
931 );
932 $defaults = apply_filters( 'frm_show_entry_defaults', $defaults );
933 $atts = shortcode_atts( $defaults, $atts );
934
935 if ( $atts['default_email'] ) {
936 $shortcode_atts = array(
937 'format' => $atts['format'],
938 'plain_text' => $atts['plain_text'],
939 );
940 $entry_formatter = FrmEntryFactory::entry_shortcode_formatter_instance( $atts['form_id'], $shortcode_atts );
941 return $entry_formatter->content();
942 }
943
944 $entry_formatter = FrmEntryFactory::entry_formatter_instance( $atts );
945
946 return $entry_formatter->get_formatted_entry_values();
947 }
948
949 /**
950 * @param false|object $entry
951 *
952 * @return void
953 */
954 public static function entry_sidebar( $entry = false ) {
955 $data = array();
956 $id = 0;
957 $date_format = get_option( 'date_format' );
958 $time_format = get_option( 'time_format' );
959
960 if ( $entry ) {
961 $id = $entry->id;
962 $data = $entry->description;
963
964 if ( isset( $data['browser'] ) ) {
965 $browser = FrmEntriesHelper::get_browser( $data['browser'] );
966 }
967 /**
968 * Add or remove information in the entry sidebar.
969 *
970 * @since 5.5.2
971 *
972 * @param array $data
973 * @param array{entry:\stdClass} $entry
974 */
975 $data = apply_filters( 'frm_sidebar_data', $data, compact( 'entry' ) );
976 }
977
978 include FrmAppHelper::plugin_path() . '/classes/views/frm-entries/sidebar-shared.php';
979 }
980 }
981