PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.2.07
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.2.07
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 / FrmFormsController.php

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

2,462 lines 71.1 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 FrmFormsController {
7
8 public static function menu() {
9 $menu_label = __( 'Forms', 'formidable' );
10 if ( ! FrmAppHelper::pro_is_installed() ) {
11 $menu_label .= ' (Lite)';
12 }
13 add_submenu_page( 'formidable', 'Formidable | ' . $menu_label, $menu_label, 'frm_view_forms', 'formidable', 'FrmFormsController::route' );
14
15 self::maybe_load_listing_hooks();
16 }
17
18 public static function maybe_load_listing_hooks() {
19 $action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
20 if ( ! empty( $action ) && ! in_array( $action, array( 'list', 'trash', 'untrash', 'destroy' ) ) ) {
21 return;
22 }
23
24 add_filter( 'get_user_option_managetoplevel_page_formidablecolumnshidden', 'FrmFormsController::hidden_columns' );
25
26 add_filter( 'manage_toplevel_page_formidable_columns', 'FrmFormsController::get_columns', 0 );
27 add_filter( 'manage_toplevel_page_formidable_sortable_columns', 'FrmFormsController::get_sortable_columns' );
28 }
29
30 public static function head() {
31 if ( wp_is_mobile() ) {
32 wp_enqueue_script( 'jquery-touch-punch' );
33 }
34 }
35
36 public static function register_widgets() {
37 require_once( FrmAppHelper::plugin_path() . '/classes/widgets/FrmShowForm.php' );
38 register_widget( 'FrmShowForm' );
39 }
40
41 /**
42 * Show a message about conditional logic
43 *
44 * @since 4.06.03
45 */
46 public static function logic_tip() {
47 $images_url = FrmAppHelper::plugin_url() . '/images/';
48 $data_message = __( 'Only show the fields you need and create branching forms. Upgrade to get conditional logic and question branching.', 'formidable' );
49 $data_message .= ' <img src="' . esc_attr( $images_url ) . '/survey-logic.png" srcset="' . esc_attr( $images_url ) . 'survey-logic@2x.png 2x" alt="' . esc_attr__( 'Conditional Logic options', 'formidable' ) . '"/>';
50 echo '<a href="javascript:void(0)" class="frm_noallow frm_show_upgrade frm_add_logic_link" data-upgrade="' . esc_attr__( 'Conditional Logic options', 'formidable' ) . '" data-message="' . esc_attr( $data_message ) . '" data-medium="builder" data-content="logic">';
51 FrmAppHelper::icon_by_class( 'frmfont frm_swap_icon' );
52 esc_html_e( 'Add Conditional Logic', 'formidable' );
53 echo '</a>';
54 }
55
56 /**
57 * By default, Divi processes form shortcodes on the edit post page.
58 * Now that won't do.
59 *
60 * @since 3.01
61 */
62 public static function prevent_divi_conflict( $shortcodes ) {
63 $shortcodes[] = 'formidable';
64
65 return $shortcodes;
66 }
67
68 public static function list_form() {
69 FrmAppHelper::permission_check( 'frm_view_forms' );
70
71 $message = '';
72 $params = FrmForm::list_page_params();
73 $errors = self::process_bulk_form_actions( array() );
74 if ( isset( $errors['message'] ) ) {
75 $message = $errors['message'];
76 unset( $errors['message'] );
77 }
78 $errors = apply_filters( 'frm_admin_list_form_action', $errors );
79
80 return self::display_forms_list( $params, $message, $errors );
81 }
82
83 /**
84 * Create the default email action
85 *
86 * @since 2.02.11
87 *
88 * @param object|int $form
89 */
90 private static function create_default_email_action( $form ) {
91 FrmForm::maybe_get_form( $form );
92 $create_email = apply_filters( 'frm_create_default_email_action', true, $form );
93
94 if ( $create_email ) {
95 $action_control = FrmFormActionsController::get_form_actions( 'email' );
96 $action_control->create( $form->id );
97 }
98 }
99
100 public static function edit( $values = false ) {
101 FrmAppHelper::permission_check( 'frm_edit_forms' );
102
103 $id = isset( $values['id'] ) ? absint( $values['id'] ) : FrmAppHelper::get_param( 'id', '', 'get', 'absint' );
104
105 return self::get_edit_vars( $id );
106 }
107
108 public static function settings( $id = false, $message = '' ) {
109 FrmAppHelper::permission_check( 'frm_edit_forms' );
110
111 if ( ! $id || ! is_numeric( $id ) ) {
112 $id = FrmAppHelper::get_param( 'id', '', 'get', 'absint' );
113 }
114
115 return self::get_settings_vars( $id, array(), $message );
116 }
117
118 public static function update_settings() {
119 FrmAppHelper::permission_check( 'frm_edit_forms' );
120
121 $id = FrmAppHelper::get_param( 'id', '', 'get', 'absint' );
122
123 $errors = FrmForm::validate( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
124 $warnings = FrmFormsHelper::check_for_warnings( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
125
126 if ( count( $errors ) > 0 ) {
127 return self::get_settings_vars( $id, $errors, compact( 'warnings' ) );
128 }
129
130 do_action( 'frm_before_update_form_settings', $id );
131
132 $antispam_was_on = self::antispam_was_on( $id );
133
134 FrmForm::update( $id, $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
135
136 $antispam_is_on = ! empty( $_POST['options']['antispam'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
137 if ( $antispam_is_on !== $antispam_was_on ) {
138 FrmAntiSpam::clear_caches();
139 }
140
141 $message = __( 'Settings Successfully Updated', 'formidable' );
142
143 return self::get_settings_vars( $id, array(), compact( 'message', 'warnings' ) );
144 }
145
146 /**
147 * @param int $form_id
148 * @return bool
149 */
150 private static function antispam_was_on( $form_id ) {
151 $form = FrmForm::getOne( $form_id );
152 return ! empty( $form->options['antispam'] );
153 }
154
155 public static function update( $values = array() ) {
156 if ( empty( $values ) ) {
157 $values = $_POST; // phpcs:ignore WordPress.Security.NonceVerification.Missing
158 }
159
160 // Set radio button and checkbox meta equal to "other" value.
161 if ( FrmAppHelper::pro_is_installed() ) {
162 $values = FrmProEntry::mod_other_vals( $values, 'back' );
163 }
164
165 $errors = FrmForm::validate( $values );
166 $permission_error = FrmAppHelper::permission_nonce_error( 'frm_edit_forms', 'frm_save_form', 'frm_save_form_nonce' );
167 if ( $permission_error !== false ) {
168 $errors['form'] = $permission_error;
169 }
170
171 $id = isset( $values['id'] ) ? absint( $values['id'] ) : FrmAppHelper::get_param( 'id', '', 'get', 'absint' );
172
173 if ( count( $errors ) > 0 ) {
174 return self::get_edit_vars( $id, $errors );
175 } else {
176 FrmForm::update( $id, $values );
177 $message = __( 'Form was successfully updated.', 'formidable' );
178
179 if ( self::is_too_long( $values ) ) {
180 $message .= '<br/> ' . sprintf(
181 /* translators: %1$s: Start link HTML, %2$s: end link HTML */
182 __( 'However, your form is very long and may be %1$sreaching server limits%2$s.', 'formidable' ),
183 '<a href="https://formidableforms.com/knowledgebase/i-have-a-long-form-why-did-the-options-at-the-end-of-the-form-stop-saving/?utm_source=WordPress&utm_medium=builder&utm_campaign=liteplugin" target="_blank" rel="noopener">',
184 '</a>'
185 );
186 }
187
188 if ( defined( 'DOING_AJAX' ) ) {
189 wp_die( FrmAppHelper::kses( $message, array( 'a' ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
190 }
191
192 return self::get_edit_vars( $id, array(), $message );
193 }
194 }
195
196 /**
197 * Check if the value at the end of the form was included.
198 * If it's missing, it means other values at the end of the form
199 * were likely not saved either.
200 *
201 * @since 3.06.01
202 */
203 private static function is_too_long( $values ) {
204 return ( ! isset( $values['frm_end'] ) ) || empty( $values['frm_end'] );
205 }
206
207 /**
208 * Redirect to the url for creating from a template
209 * Also delete the current form
210 *
211 * @since 2.0
212 * @deprecated 3.06
213 */
214 public static function _create_from_template() {
215 _deprecated_function( __FUNCTION__, '3.06' );
216
217 FrmAppHelper::permission_check( 'frm_edit_forms' );
218 check_ajax_referer( 'frm_ajax', 'nonce' );
219
220 $current_form = FrmAppHelper::get_param( 'this_form', '', 'get', 'absint' );
221 $template_id = FrmAppHelper::get_param( 'id', '', 'get', 'absint' );
222
223 if ( $current_form ) {
224 FrmForm::destroy( $current_form );
225 }
226
227 echo esc_url_raw( admin_url( 'admin.php?page=formidable&frm_action=duplicate&id=' . absint( $template_id ) ) );
228 wp_die();
229 }
230
231 public static function duplicate() {
232 FrmAppHelper::permission_check( 'frm_edit_forms' );
233
234 $params = FrmForm::list_page_params();
235 $form = FrmForm::duplicate( $params['id'], $params['template'], true );
236 $message = $params['template'] ? __( 'Form template was Successfully Created', 'formidable' ) : __( 'Form was Successfully Copied', 'formidable' );
237 if ( $form ) {
238 return self::get_edit_vars( $form, array(), $message, true );
239 } else {
240 return self::display_forms_list( $params, __( 'There was a problem creating the new template.', 'formidable' ) );
241 }
242 }
243
244 /**
245 * @return string
246 */
247 public static function page_preview() {
248 $params = FrmForm::list_page_params();
249 if ( ! $params['form'] ) {
250 return;
251 }
252
253 $form = FrmForm::getOne( $params['form'] );
254 if ( $form ) {
255 return self::show_form( $form->id, '', 'auto', 'auto' );
256 }
257 }
258
259 /**
260 * @since 3.0
261 */
262 public static function show_page_preview() {
263 echo self::page_preview(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
264 }
265
266 /**
267 * @return void
268 */
269 public static function preview() {
270 do_action( 'frm_wp' );
271 FrmAppHelper::set_current_screen_and_hook_suffix();
272
273 global $frm_vars;
274 $frm_vars['preview'] = true;
275
276 $include_theme = FrmAppHelper::get_param( 'theme', '', 'get', 'absint' );
277 if ( $include_theme ) {
278 self::set_preview_query();
279 self::load_theme_preview();
280 } else {
281 self::load_direct_preview();
282 }
283
284 wp_die();
285 }
286
287 private static function set_preview_query() {
288 $random_page = get_posts(
289 array(
290 'numberposts' => 1,
291 'orderby' => 'date',
292 'order' => 'ASC',
293 'post_type' => 'page',
294 )
295 );
296
297 if ( ! empty( $random_page ) ) {
298 $random_page = reset( $random_page );
299 query_posts(
300 array(
301 'post_type' => 'page',
302 'page_id' => $random_page->ID,
303 )
304 );
305 }
306 }
307
308 /**
309 * @since 3.0
310 */
311 private static function load_theme_preview() {
312 add_filter( 'wp_title', 'FrmFormsController::preview_title', 9999 );
313 add_filter( 'the_title', 'FrmFormsController::preview_page_title', 9999 );
314 add_filter( 'the_content', 'FrmFormsController::preview_content', 9999 );
315 add_action( 'loop_no_results', 'FrmFormsController::show_page_preview' );
316 add_filter( 'is_active_sidebar', '__return_false' );
317 FrmStylesController::enqueue_css( 'enqueue', true );
318
319 if ( false === get_template_part( 'page' ) ) {
320 self::fallback_when_page_template_part_is_not_supported_by_theme();
321 }
322 }
323
324 /**
325 * Not every theme supports get_template_part( 'page' ).
326 * When this is not supported, false is returned, and we can handle a fallback.
327 */
328 private static function fallback_when_page_template_part_is_not_supported_by_theme() {
329 if ( have_posts() ) {
330 the_post();
331 get_header( '' );
332 // add some generic class names to the container to add some natural padding to the content.
333 // .entry-content catches the WordPress TwentyTwenty theme.
334 // .container catches Customizr content.
335 echo '<div class="container entry-content">';
336 the_content();
337 echo '</div>';
338 get_footer();
339 }
340 }
341
342 /**
343 * Set the page title for the theme preview page
344 *
345 * @since 3.0
346 */
347 public static function preview_page_title( $title ) {
348 if ( in_the_loop() ) {
349 $title = self::preview_title( $title );
350 }
351
352 return $title;
353 }
354
355 /**
356 * Set the page title for the theme preview page
357 *
358 * @since 3.0
359 */
360 public static function preview_title( $title ) {
361 return __( 'Form Preview', 'formidable' );
362 }
363
364 /**
365 * Set the page content for the theme preview page
366 *
367 * @since 3.0
368 */
369 public static function preview_content( $content ) {
370 if ( in_the_loop() ) {
371 $content = self::show_page_preview();
372 }
373
374 return $content;
375 }
376
377 /**
378 * @since 3.0
379 */
380 private static function load_direct_preview() {
381 header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );
382
383 $key = FrmAppHelper::simple_get( 'form', 'sanitize_title' );
384 if ( $key == '' ) {
385 $key = FrmAppHelper::get_post_param( 'form', '', 'sanitize_title' );
386 }
387
388 $form = FrmForm::getAll( array( 'form_key' => $key ), '', 1 );
389 if ( empty( $form ) ) {
390 $form = FrmForm::getAll( array(), '', 1 );
391 }
392
393 require( FrmAppHelper::plugin_path() . '/classes/views/frm-entries/direct.php' );
394 }
395
396 public static function untrash() {
397 self::change_form_status( 'untrash' );
398 }
399
400 public static function bulk_untrash( $ids ) {
401 FrmAppHelper::permission_check( 'frm_edit_forms' );
402
403 $count = FrmForm::set_status( $ids, 'published' );
404
405 /* translators: %1$s: Number of forms */
406 $message = sprintf( _n( '%1$s form restored from the Trash.', '%1$s forms restored from the Trash.', $count, 'formidable' ), 1 );
407
408 return $message;
409 }
410
411 /**
412 * @since 3.06
413 */
414 public static function ajax_trash() {
415 FrmAppHelper::permission_check( 'frm_delete_forms' );
416 check_ajax_referer( 'frm_ajax', 'nonce' );
417 $form_id = FrmAppHelper::get_param( 'id', '', 'post', 'absint' );
418 FrmForm::set_status( $form_id, 'trash' );
419 wp_die();
420 }
421
422 public static function trash() {
423 self::change_form_status( 'trash' );
424 }
425
426 /**
427 * @param string $status
428 *
429 * @return void
430 */
431 public static function change_form_status( $status ) {
432 $available_status = array(
433 'untrash' => array(
434 'permission' => 'frm_edit_forms',
435 'new_status' => 'published',
436 ),
437 'trash' => array(
438 'permission' => 'frm_delete_forms',
439 'new_status' => 'trash',
440 ),
441 );
442
443 if ( ! isset( $available_status[ $status ] ) ) {
444 return;
445 }
446
447 FrmAppHelper::permission_check( $available_status[ $status ]['permission'] );
448
449 $params = FrmForm::list_page_params();
450
451 //check nonce url
452 check_admin_referer( $status . '_form_' . $params['id'] );
453
454 $count = 0;
455 if ( FrmForm::set_status( $params['id'], $available_status[ $status ]['new_status'] ) ) {
456 $count ++;
457 }
458
459 $form_type = FrmAppHelper::get_simple_request(
460 array(
461 'param' => 'form_type',
462 'type' => 'request',
463 )
464 );
465
466 /* translators: %1$s: Number of forms */
467 $available_status['untrash']['message'] = sprintf( _n( '%1$s form restored from the Trash.', '%1$s forms restored from the Trash.', $count, 'formidable' ), $count );
468
469 /* translators: %1$s: Number of forms, %2$s: Start link HTML, %3$s: End link HTML */
470 $available_status['trash']['message'] = sprintf( _n( '%1$s form moved to the Trash. %2$sUndo%3$s', '%1$s forms moved to the Trash. %2$sUndo%3$s', $count, 'formidable' ), $count, '<a href="' . esc_url( wp_nonce_url( '?page=formidable&frm_action=untrash&form_type=' . $form_type . '&id=' . $params['id'], 'untrash_form_' . $params['id'] ) ) . '">', '</a>' );
471
472 $message = $available_status[ $status ]['message'];
473
474 self::display_forms_list( $params, $message );
475 }
476
477 public static function bulk_trash( $ids ) {
478 FrmAppHelper::permission_check( 'frm_delete_forms' );
479
480 $count = 0;
481 foreach ( $ids as $id ) {
482 if ( FrmForm::trash( $id ) ) {
483 $count ++;
484 }
485 }
486
487 $current_page = FrmAppHelper::get_simple_request(
488 array(
489 'param' => 'form_type',
490 'type' => 'request',
491 )
492 );
493 $message = sprintf(
494 /* translators: %1$s: Number of forms, %2$s: Start link HTML, %3$s: End link HTML */
495 _n( '%1$s form moved to the Trash. %2$sUndo%3$s', '%1$s forms moved to the Trash. %2$sUndo%3$s', $count, 'formidable' ),
496 $count,
497 '<a href="' . esc_url( wp_nonce_url( '?page=formidable&frm_action=list&action=bulk_untrash&form_type=' . $current_page . '&item-action=' . implode( ',', $ids ), 'bulk-toplevel_page_formidable' ) ) . '">',
498 '</a>'
499 );
500
501 return $message;
502 }
503
504 public static function destroy() {
505 FrmAppHelper::permission_check( 'frm_delete_forms' );
506
507 $params = FrmForm::list_page_params();
508
509 // Check nonce url.
510 check_admin_referer( 'destroy_form_' . $params['id'] );
511
512 $count = 0;
513 if ( FrmForm::destroy( $params['id'] ) ) {
514 $count ++;
515 }
516
517 /* translators: %1$s: Number of forms */
518 $message = sprintf( _n( '%1$s Form Permanently Deleted', '%1$s Forms Permanently Deleted', $count, 'formidable' ), $count );
519
520 self::display_forms_list( $params, $message );
521 }
522
523 public static function bulk_destroy( $ids ) {
524 FrmAppHelper::permission_check( 'frm_delete_forms' );
525
526 $count = 0;
527 foreach ( $ids as $id ) {
528 $d = FrmForm::destroy( $id );
529 if ( $d ) {
530 $count ++;
531 }
532 }
533
534 /* translators: %1$s: Number of forms */
535 $message = sprintf( _n( '%1$s form permanently deleted.', '%1$s forms permanently deleted.', $count, 'formidable' ), $count );
536
537 return $message;
538 }
539
540 private static function delete_all() {
541 // Check nonce url.
542 $permission_error = FrmAppHelper::permission_nonce_error( 'frm_delete_forms', '_wpnonce', 'bulk-toplevel_page_formidable' );
543 if ( $permission_error !== false ) {
544 self::display_forms_list( array(), '', array( $permission_error ) );
545
546 return;
547 }
548
549 $count = FrmForm::scheduled_delete( time() );
550
551 /* translators: %1$s: Number of forms */
552 $message = sprintf( _n( '%1$s form permanently deleted.', '%1$s forms permanently deleted.', $count, 'formidable' ), $count );
553
554 self::display_forms_list( array(), $message );
555 }
556
557 /**
558 * Create a new form from the modal.
559 *
560 * @since 4.0
561 */
562 public static function build_new_form() {
563 global $wpdb;
564
565 FrmAppHelper::permission_check( 'frm_edit_forms' );
566 check_ajax_referer( 'frm_ajax', 'nonce' );
567
568 $new_values = self::get_modal_values();
569 $new_values['form_key'] = $new_values['name'];
570 $new_values['options'] = array(
571 'antispam' => 1,
572 );
573
574 $form_id = FrmForm::create( $new_values );
575
576 self::create_default_email_action( $form_id );
577
578 $response = array(
579 'redirect' => FrmForm::get_edit_link( $form_id ),
580 );
581
582 echo wp_json_encode( $response );
583 wp_die();
584 }
585
586 /**
587 * Create a custom template from a form
588 *
589 * @since 3.06
590 */
591 public static function build_template() {
592 global $wpdb;
593
594 FrmAppHelper::permission_check( 'frm_edit_forms' );
595 check_ajax_referer( 'frm_ajax', 'nonce' );
596
597 $form_id = FrmAppHelper::get_param( 'xml', '', 'post', 'absint' );
598 $new_form_id = FrmForm::duplicate( $form_id, 1, true );
599 if ( ! $new_form_id ) {
600 $response = array(
601 'message' => __( 'There was an error creating a template.', 'formidable' ),
602 );
603 } else {
604 $new_values = self::get_modal_values();
605 $query_results = $wpdb->update( $wpdb->prefix . 'frm_forms', $new_values, array( 'id' => $new_form_id ) );
606 if ( $query_results ) {
607 FrmForm::clear_form_cache();
608 }
609
610 $response = array(
611 'redirect' => admin_url( 'admin.php?page=formidable&frm_action=duplicate&id=' . $new_form_id ),
612 );
613 }
614
615 echo wp_json_encode( $response );
616 wp_die();
617 }
618
619 /**
620 * Before creating a new form, get the name and description from the modal.
621 *
622 * @since 4.0
623 */
624 private static function get_modal_values() {
625 $name = FrmAppHelper::get_param( 'name', '', 'post', 'sanitize_text_field' );
626 $desc = FrmAppHelper::get_param( 'desc', '', 'post', 'sanitize_textarea_field' );
627
628 return array(
629 'name' => $name,
630 'description' => $desc,
631 );
632 }
633
634 /**
635 * Inserts Formidable button
636 * Hook exists since 2.5.0
637 *
638 * @since 2.0.15
639 */
640 public static function insert_form_button() {
641 if ( current_user_can( 'frm_view_forms' ) ) {
642 FrmAppHelper::load_admin_wide_js();
643 $menu_name = FrmAppHelper::get_menu_name();
644 $icon = apply_filters( 'frm_media_icon', FrmAppHelper::svg_logo() );
645 echo '<a href="#TB_inline?width=50&height=50&inlineId=frm_insert_form" class="thickbox button add_media frm_insert_form" title="' . esc_attr__( 'Add forms and content', 'formidable' ) . '">' .
646 FrmAppHelper::kses( $icon, 'all' ) . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
647 ' ' . esc_html( $menu_name ) . '</a>';
648 }
649 }
650
651 /**
652 * @return void
653 */
654 public static function insert_form_popup() {
655 if ( ! self::should_insert_form_popup() ) {
656 return;
657 }
658
659 FrmAppHelper::load_admin_wide_js();
660
661 $shortcodes = array(
662 'formidable' => array(
663 'name' => __( 'Form', 'formidable' ),
664 'label' => __( 'Insert a Form', 'formidable' ),
665 ),
666 );
667 $shortcodes = apply_filters( 'frm_popup_shortcodes', $shortcodes );
668
669 include FrmAppHelper::plugin_path() . '/classes/views/frm-forms/insert_form_popup.php';
670
671 if ( FrmAppHelper::is_form_builder_page() && ! class_exists( '_WP_Editors', false ) ) {
672 // initialize a wysiwyg so we have usable settings defined in tinyMCEPreInit.mceInit
673 require ABSPATH . WPINC . '/class-wp-editor.php';
674 ?>
675 <div class="frm_hidden">
676 <?php wp_editor( '', 'frm_description_placeholder', array() ); ?>
677 </div>
678 <?php
679 }
680 }
681
682 /**
683 * Check the page being loaded, determine if this is a page that should include the form popup.
684 *
685 * @since 5.0.14
686 *
687 * @return bool
688 */
689 private static function should_insert_form_popup() {
690 if ( FrmAppHelper::is_form_builder_page() ) {
691 return true;
692 }
693 $page = basename( FrmAppHelper::get_server_value( 'PHP_SELF' ) );
694 return in_array( $page, array( 'post.php', 'page.php', 'page-new.php', 'post-new.php' ), true );
695 }
696
697 public static function get_shortcode_opts() {
698 FrmAppHelper::permission_check( 'frm_view_forms' );
699 check_ajax_referer( 'frm_ajax', 'nonce' );
700
701 $shortcode = FrmAppHelper::get_post_param( 'shortcode', '', 'sanitize_text_field' );
702 if ( empty( $shortcode ) ) {
703 wp_die();
704 }
705
706 echo '<div id="sc-opts-' . esc_attr( $shortcode ) . '" class="frm_shortcode_option">';
707 echo '<input type="radio" name="frmsc" value="' . esc_attr( $shortcode ) . '" id="sc-' . esc_attr( $shortcode ) . '" class="frm_hidden" />';
708
709 $form_id = '';
710 $opts = array();
711 switch ( $shortcode ) {
712 case 'formidable':
713 $opts = array(
714 'form_id' => 'id',
715 'title' => array(
716 'val' => 1,
717 'label' => __( 'Display form title', 'formidable' ),
718 ),
719 'description' => array(
720 'val' => 1,
721 'label' => __( 'Display form description', 'formidable' ),
722 ),
723 'minimize' => array(
724 'val' => 1,
725 'label' => __( 'Minimize form HTML', 'formidable' ),
726 ),
727 );
728 }
729 $opts = apply_filters( 'frm_sc_popup_opts', $opts, $shortcode );
730
731 if ( isset( $opts['form_id'] ) && is_string( $opts['form_id'] ) ) {
732 // allow other shortcodes to use the required form id option
733 $form_id = $opts['form_id'];
734 unset( $opts['form_id'] );
735 }
736
737 include( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/shortcode_opts.php' );
738
739 echo '</div>';
740
741 wp_die();
742 }
743
744 public static function display_forms_list( $params = array(), $message = '', $errors = array() ) {
745 FrmAppHelper::permission_check( 'frm_view_forms' );
746
747 global $wpdb, $frm_vars;
748
749 if ( empty( $params ) ) {
750 $params = FrmForm::list_page_params();
751 }
752
753 $wp_list_table = new FrmFormsListHelper( compact( 'params' ) );
754
755 $pagenum = $wp_list_table->get_pagenum();
756
757 $wp_list_table->prepare_items();
758
759 $total_pages = $wp_list_table->get_pagination_arg( 'total_pages' );
760 if ( $pagenum > $total_pages && $total_pages > 0 ) {
761 wp_redirect( esc_url_raw( add_query_arg( 'paged', $total_pages ) ) );
762 die();
763 }
764
765 require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/list.php' );
766 }
767
768 public static function get_columns( $columns ) {
769 $columns['cb'] = '<input type="checkbox" />';
770 $columns['id'] = 'ID';
771
772 $type = FrmAppHelper::get_simple_request(
773 array(
774 'param' => 'form_type',
775 'type' => 'request',
776 'default' => 'published',
777 )
778 );
779
780 if ( 'template' == $type ) {
781 $columns['name'] = __( 'Template Name', 'formidable' );
782 $columns['type'] = __( 'Type', 'formidable' );
783 $columns['form_key'] = __( 'Key', 'formidable' );
784 } else {
785 $columns['name'] = __( 'Form Title', 'formidable' );
786 $columns['entries'] = __( 'Entries', 'formidable' );
787 $columns['form_key'] = __( 'Key', 'formidable' );
788 $columns['shortcode'] = __( 'Actions', 'formidable' );
789 }
790
791 $columns['created_at'] = __( 'Date', 'formidable' );
792
793 add_screen_option(
794 'per_page',
795 array(
796 'label' => __( 'Forms', 'formidable' ),
797 'default' => 20,
798 'option' => 'formidable_page_formidable_per_page',
799 )
800 );
801
802 return $columns;
803 }
804
805 public static function get_sortable_columns() {
806 return array(
807 'id' => 'id',
808 'name' => 'name',
809 'description' => 'description',
810 'form_key' => 'form_key',
811 'created_at' => 'created_at',
812 );
813 }
814
815 public static function hidden_columns( $hidden_columns ) {
816 $type = FrmAppHelper::get_simple_request(
817 array(
818 'param' => 'form_type',
819 'type' => 'request',
820 )
821 );
822
823 if ( $type === 'template' ) {
824 $hidden_columns[] = 'id';
825 $hidden_columns[] = 'form_key';
826 }
827
828 return $hidden_columns;
829 }
830
831 public static function save_per_page( $save, $option, $value ) {
832 if ( $option == 'formidable_page_formidable_per_page' ) {
833 $save = (int) $value;
834 }
835
836 return $save;
837 }
838
839 /**
840 * @return bool
841 */
842 public static function expired() {
843 global $frm_expired;
844 return $frm_expired;
845 }
846
847 /**
848 * Get data from api before rendering it so that we can flag the modal as expired
849 */
850 public static function before_list_templates() {
851 global $frm_templates;
852 global $frm_expired;
853 global $frm_license_type;
854
855 $api = new FrmFormTemplateApi();
856 $frm_templates = $api->get_api_info();
857 $expired = false;
858 $license_type = '';
859 if ( isset( $frm_templates['error'] ) ) {
860 $error = $frm_templates['error']['message'];
861 $error = str_replace( 'utm_medium=addons', 'utm_medium=form-templates', $error );
862 $expired = 'expired' === $frm_templates['error']['code'];
863 $license_type = isset( $frm_templates['error']['type'] ) ? $frm_templates['error']['type'] : '';
864 unset( $frm_templates['error'] );
865 }
866
867 $frm_expired = $expired;
868 $frm_license_type = $license_type;
869 }
870
871 public static function list_templates() {
872 global $frm_templates;
873 global $frm_license_type;
874
875 $templates = $frm_templates;
876 $custom_templates = array();
877 $templates_by_category = array();
878
879 self::add_user_templates( $custom_templates );
880
881 foreach ( $templates as $template ) {
882 if ( ! isset( $template['categories'] ) ) {
883 continue;
884 }
885
886 foreach ( $template['categories'] as $category ) {
887 if ( ! isset( $templates_by_category[ $category ] ) ) {
888 $templates_by_category[ $category ] = array();
889 }
890
891 $templates_by_category[ $category ][] = $template;
892 }
893 }
894 unset( $template );
895
896 // Subcategories that are included elsewhere.
897 $redundant_cats = array( 'PayPal', 'Stripe', 'Twilio' );
898
899 $categories = array_keys( $templates_by_category );
900 $categories = array_diff( $categories, FrmFormsHelper::ignore_template_categories() );
901 $categories = array_diff( $categories, $redundant_cats );
902 sort( $categories );
903
904 array_walk(
905 $custom_templates,
906 function( &$template ) {
907 $template['custom'] = true;
908 }
909 );
910
911 $my_templates_translation = __( 'My Templates', 'formidable' );
912 $categories = array_merge( array( $my_templates_translation ), $categories );
913 $pricing = FrmAppHelper::admin_upgrade_link( 'form-templates' );
914 $license_type = $frm_license_type;
915 $args = compact( 'pricing', 'license_type' );
916 $where = apply_filters( 'frm_forms_dropdown', array(), '' );
917 $forms = FrmForm::get_published_forms( $where );
918 $view_path = FrmAppHelper::plugin_path() . '/classes/views/frm-forms/';
919
920 $templates_by_category[ $my_templates_translation ] = $custom_templates;
921
922 unset( $pricing, $license_type, $where );
923 wp_enqueue_script( 'accordion' ); // register accordion for template groups
924 require $view_path . 'list-templates.php';
925 }
926
927 /**
928 * @since 4.03.01
929 */
930 private static function get_template_categories( $templates ) {
931 $categories = array();
932 foreach ( $templates as $template ) {
933 if ( isset( $template['categories'] ) ) {
934 $categories = array_merge( $categories, $template['categories'] );
935 }
936 }
937 $exclude_cats = FrmFormsHelper::ignore_template_categories();
938 $categories = array_unique( $categories );
939 $categories = array_diff( $categories, $exclude_cats );
940 sort( $categories );
941 return $categories;
942 }
943
944 private static function add_user_templates( &$templates ) {
945 $user_templates = array(
946 'is_template' => 1,
947 'default_template' => 0,
948 );
949 $user_templates = FrmForm::getAll( $user_templates, 'name' );
950 foreach ( $user_templates as $template ) {
951 $template = array(
952 'id' => $template->id,
953 'name' => $template->name,
954 'key' => $template->form_key,
955 'description' => $template->description,
956 'url' => admin_url( 'admin.php?page=formidable&frm_action=duplicate&id=' . absint( $template->id ) ),
957 'released' => $template->created_at,
958 'installed' => 1,
959 );
960 array_unshift( $templates, $template );
961 unset( $template );
962 }
963 }
964
965 private static function get_edit_vars( $id, $errors = array(), $message = '', $create_link = false ) {
966 global $frm_vars;
967
968 $form = FrmForm::getOne( $id );
969 if ( ! $form ) {
970 wp_die( esc_html__( 'You are trying to edit a form that does not exist.', 'formidable' ) );
971 }
972
973 if ( $form->parent_form_id ) {
974 /* translators: %1$s: Start link HTML, %2$s: End link HTML */
975 wp_die( sprintf( esc_html__( 'You are trying to edit a child form. Please edit from %1$shere%2$s', 'formidable' ), '<a href="' . esc_url( FrmForm::get_edit_link( $form->parent_form_id ) ) . '">', '</a>' ) );
976 }
977
978 $frm_field_selection = FrmField::field_selection();
979
980 $fields = FrmField::get_all_for_form( $form->id );
981
982 // Automatically add end section fields if they don't exist (2.0 migration).
983 $reset_fields = false;
984 FrmFormsHelper::auto_add_end_section_fields( $form, $fields, $reset_fields );
985
986 if ( $reset_fields ) {
987 $fields = FrmField::get_all_for_form( $form->id, '', 'exclude' );
988 }
989
990 unset( $reset_fields );
991
992 $args = array( 'parent_form_id' => $form->id );
993 $values = FrmAppHelper::setup_edit_vars( $form, 'forms', '', true, array(), $args );
994
995 /**
996 * Allows modifying the list of fields in the form builder.
997 *
998 * @since 5.0.04
999 *
1000 * @param object[] $fields Array of fields.
1001 * @param array $args The arguments. Contains `form`.
1002 */
1003 $values['fields'] = apply_filters( 'frm_fields_in_form_builder', $fields, compact( 'form' ) );
1004
1005 $edit_message = __( 'Form was successfully updated.', 'formidable' );
1006 if ( $form->is_template && $message == $edit_message ) {
1007 $message = __( 'Template was successfully updated.', 'formidable' );
1008 }
1009
1010 $all_templates = FrmForm::getAll( array( 'is_template' => 1 ), 'name' );
1011 $has_fields = isset( $values['fields'] ) && ! empty( $values['fields'] );
1012
1013 if ( defined( 'DOING_AJAX' ) ) {
1014 wp_die();
1015 } else {
1016 require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/edit.php' );
1017 }
1018 }
1019
1020 public static function get_settings_vars( $id, $errors = array(), $args = array() ) {
1021 FrmAppHelper::permission_check( 'frm_edit_forms' );
1022
1023 global $frm_vars;
1024
1025 if ( ! is_array( $args ) ) {
1026 // For reverse compatibility.
1027 $args = array(
1028 'message' => $args,
1029 );
1030 }
1031
1032 $defaults = array(
1033 'message' => '',
1034 'warnings' => array(),
1035 );
1036 $args = array_merge( $defaults, $args );
1037 $message = $args['message'];
1038 $warnings = $args['warnings'];
1039
1040 $form = FrmForm::getOne( $id );
1041 $fields = FrmField::get_all_for_form( $id );
1042 $values = FrmAppHelper::setup_edit_vars( $form, 'forms', $fields, true );
1043
1044 /**
1045 * Allows changing fields in the form settings.
1046 *
1047 * @since 5.0.04
1048 *
1049 * @param array $fields Array of fields.
1050 * @param array $args The arguments. Contains `form`.
1051 */
1052 $values['fields'] = apply_filters( 'frm_fields_in_settings', $values['fields'], compact( 'form' ) );
1053
1054 self::clean_submit_html( $values );
1055
1056 $sections = self::get_settings_tabs( $values );
1057 $current = FrmAppHelper::simple_get( 't', 'sanitize_title', 'advanced_settings' );
1058
1059 require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/settings.php' );
1060 }
1061
1062 /**
1063 * @since 4.0
1064 */
1065 public static function form_publish_button( $atts ) {
1066 $values = $atts['values'];
1067 include( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/_publish_box.php' );
1068 }
1069
1070 /**
1071 * Get a list of all the settings tabs for the form settings page.
1072 *
1073 * @since 4.0
1074 *
1075 * @param array $values
1076 * @return array
1077 */
1078 private static function get_settings_tabs( $values ) {
1079 $sections = array(
1080 'advanced' => array(
1081 'name' => __( 'General', 'formidable' ),
1082 'title' => __( 'General Form Settings', 'formidable' ),
1083 'function' => array( __CLASS__, 'advanced_settings' ),
1084 'icon' => 'frm_icon_font frm_settings_icon',
1085 ),
1086 'email' => array(
1087 'name' => __( 'Actions & Notifications', 'formidable' ),
1088 'function' => array( 'FrmFormActionsController', 'email_settings' ),
1089 'id' => 'frm_notification_settings',
1090 'icon' => 'frm_icon_font frm_mail_bulk_icon',
1091 ),
1092 'permissions' => array(
1093 'name' => __( 'Form Permissions', 'formidable' ),
1094 'icon' => 'frm_icon_font frm_lock_icon',
1095 'html_class' => 'frm_show_upgrade frm_noallow',
1096 'data' => array(
1097 'medium' => 'permissions',
1098 'upgrade' => __( 'Form Permissions', 'formidable' ),
1099 'message' => __( 'Allow editing, protect forms and files, limit entries, and save drafts. Upgrade to get form and entry permissions.', 'formidable' ),
1100 ),
1101 ),
1102 'scheduling' => array(
1103 'name' => __( 'Form Scheduling', 'formidable' ),
1104 'icon' => 'frm_icon_font frm_calendar_icon',
1105 'html_class' => 'frm_show_upgrade frm_noallow',
1106 'data' => array(
1107 'medium' => 'scheduling',
1108 'upgrade' => __( 'Form scheduling settings', 'formidable' ),
1109 ),
1110 ),
1111 'buttons' => array(
1112 'name' => __( 'Styling & Buttons', 'formidable' ),
1113 'class' => __CLASS__,
1114 'function' => 'buttons_settings',
1115 'icon' => 'frm_icon_font frm_pallet_icon',
1116 ),
1117 'landing' => array(
1118 'name' => __( 'Form Landing Page', 'formidable' ),
1119 'icon' => 'frm_icon_font frm_file_text_icon',
1120 'html_class' => 'frm_show_upgrade frm_noallow',
1121 'data' => FrmAppHelper::get_landing_page_upgrade_data_params(),
1122 ),
1123 'chat' => array(
1124 'name' => __( 'Conversational Forms', 'formidable' ),
1125 'icon' => 'frm_icon_font frm_chat_forms_icon',
1126 'html_class' => 'frm_show_upgrade frm_noallow',
1127 'data' => FrmAppHelper::get_upgrade_data_params(
1128 'chat',
1129 array(
1130 'upgrade' => __( 'Conversational Forms', 'formidable' ),
1131 'message' => __( 'Ask one question at a time for automated conversations.', 'formidable' ),
1132 )
1133 ),
1134 ),
1135 'html' => array(
1136 'name' => __( 'Customize HTML', 'formidable' ),
1137 'class' => __CLASS__,
1138 'function' => 'html_settings',
1139 'icon' => 'frm_icon_font frm_code_icon',
1140 ),
1141 );
1142
1143 foreach ( array( 'landing', 'chat' ) as $feature ) {
1144 if ( ! FrmAppHelper::show_new_feature( $feature ) ) {
1145 unset( $sections[ $feature ] );
1146 }
1147 }
1148
1149 $sections = apply_filters( 'frm_add_form_settings_section', $sections, $values );
1150
1151 if ( FrmAppHelper::pro_is_installed() && ! FrmAppHelper::meets_min_pro_version( '4.0' ) ) {
1152 // Prevent settings from showing in 2 spots.
1153 unset( $sections['permissions'], $sections['scheduling'] );
1154 }
1155
1156 foreach ( $sections as $key => $section ) {
1157 $defaults = array(
1158 'html_class' => '',
1159 'name' => ucfirst( $key ),
1160 'icon' => 'frm_icon_font frm_settings_icon',
1161 );
1162
1163 $section = array_merge( $defaults, $section );
1164
1165 if ( ! isset( $section['anchor'] ) ) {
1166 $section['anchor'] = $key;
1167 }
1168 $section['anchor'] .= '_settings';
1169
1170 if ( ! isset( $section['title'] ) ) {
1171 $section['title'] = $section['name'];
1172 }
1173
1174 if ( ! isset( $section['id'] ) ) {
1175 $section['id'] = $section['anchor'];
1176 }
1177
1178 $sections[ $key ] = $section;
1179 }
1180
1181 return $sections;
1182 }
1183
1184 /**
1185 * @since 4.0
1186 *
1187 * @param array $values
1188 */
1189 public static function advanced_settings( $values ) {
1190 $first_h3 = 'frm_first_h3';
1191
1192 include FrmAppHelper::plugin_path() . '/classes/views/frm-forms/settings-advanced.php';
1193 }
1194
1195 /**
1196 * @param array $values
1197 */
1198 private static function render_spam_settings( $values ) {
1199 if ( function_exists( 'akismet_http_post' ) ) {
1200 include FrmAppHelper::plugin_path() . '/classes/views/frm-forms/spam-settings/akismet.php';
1201 }
1202 include FrmAppHelper::plugin_path() . '/classes/views/frm-forms/spam-settings/honeypot.php';
1203 include FrmAppHelper::plugin_path() . '/classes/views/frm-forms/spam-settings/antispam.php';
1204 }
1205
1206 /**
1207 * @since 4.0
1208 *
1209 * @param array $values
1210 */
1211 public static function buttons_settings( $values ) {
1212 $styles = apply_filters( 'frm_get_style_opts', array() );
1213
1214 $frm_settings = FrmAppHelper::get_settings();
1215 $no_global_style = $frm_settings->load_style === 'none';
1216
1217 include( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/settings-buttons.php' );
1218 }
1219
1220 /**
1221 * @since 4.0
1222 *
1223 * @param array $values
1224 */
1225 public static function html_settings( $values ) {
1226 include( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/settings-html.php' );
1227 }
1228
1229 /**
1230 * Replace old Submit Button href with new href to avoid errors in Chrome
1231 *
1232 * @since 2.03.08
1233 *
1234 * @param array|boolean $values
1235 */
1236 private static function clean_submit_html( &$values ) {
1237 if ( is_array( $values ) && isset( $values['submit_html'] ) ) {
1238 $values['submit_html'] = str_replace( 'javascript:void(0)', '#', $values['submit_html'] );
1239 }
1240 }
1241
1242 public static function mb_tags_box( $form_id, $class = '' ) {
1243 $fields = FrmField::get_all_for_form( $form_id, '', 'include' );
1244
1245 /**
1246 * Allows modifying the list of fields in the tags box.
1247 *
1248 * @since 5.0.04
1249 *
1250 * @param array $fields The list of fields.
1251 * @param array $args The arguments. Contains `form_id`.
1252 */
1253 $fields = apply_filters( 'frm_fields_in_tags_box', $fields, compact( 'form_id' ) );
1254 $linked_forms = array();
1255 $col = 'one';
1256 $settings_tab = FrmAppHelper::is_admin_page( 'formidable' ) ? true : false;
1257
1258 $cond_shortcodes = apply_filters( 'frm_conditional_shortcodes', array() );
1259 $entry_shortcodes = self::get_shortcode_helpers( $settings_tab );
1260
1261 $advanced_helpers = self::advanced_helpers( compact( 'fields', 'form_id' ) );
1262
1263 include( FrmAppHelper::plugin_path() . '/classes/views/shared/mb_adv_info.php' );
1264 }
1265
1266 /**
1267 * @since 3.04.01
1268 */
1269 private static function advanced_helpers( $atts ) {
1270 $advanced_helpers = array(
1271 'default' => array(
1272 'heading' => __( 'Customize field values with the following parameters.', 'formidable' ),
1273 'codes' => self::get_advanced_shortcodes(),
1274 ),
1275 );
1276
1277 $user_fields = self::user_shortcodes();
1278 if ( ! empty( $user_fields ) ) {
1279 $user_helpers = array();
1280 foreach ( $user_fields as $uk => $uf ) {
1281 $user_helpers[ '|user_id| show="' . $uk . '"' ] = $uf;
1282 unset( $uk, $uf );
1283 }
1284
1285 $advanced_helpers['user_id'] = array(
1286 'codes' => $user_helpers,
1287 );
1288 }
1289
1290 /**
1291 * Add extra helper shortcodes on the Advanced tab in form settings and views
1292 *
1293 * @since 3.04.01
1294 *
1295 * @param array $advanced_helpers
1296 * @param array $atts - Includes fields and form_id
1297 */
1298 return apply_filters( 'frm_advanced_helpers', $advanced_helpers, $atts );
1299 }
1300
1301 /**
1302 * Get an array of the options to display in the advanced tab
1303 * of the customization panel
1304 *
1305 * @since 2.0.6
1306 */
1307 private static function get_advanced_shortcodes() {
1308 $adv_shortcodes = array(
1309 'x sep=", "' => array(
1310 'label' => __( 'Separator', 'formidable' ),
1311 'title' => __( 'Use a different separator for checkbox fields', 'formidable' ),
1312 ),
1313 'x format="d-m-Y"' => array(
1314 'label' => __( 'Date Format', 'formidable' ),
1315 ),
1316 'x show="field_label"' => array(
1317 'label' => __( 'Field Label', 'formidable' ),
1318 ),
1319 'x wpautop=0' => array(
1320 'label' => __( 'No Auto P', 'formidable' ),
1321 'title' => __( 'Do not automatically add any paragraphs or line breaks', 'formidable' ),
1322 ),
1323 );
1324 $adv_shortcodes = apply_filters( 'frm_advanced_shortcodes', $adv_shortcodes );
1325
1326 // __( 'Leave blank instead of defaulting to User Login', 'formidable' ) : blank=1
1327
1328 return $adv_shortcodes;
1329 }
1330
1331 /**
1332 * @since 3.04.01
1333 */
1334 private static function user_shortcodes() {
1335 $options = array(
1336 'ID' => __( 'User ID', 'formidable' ),
1337 'first_name' => __( 'First Name', 'formidable' ),
1338 'last_name' => __( 'Last Name', 'formidable' ),
1339 'display_name' => __( 'Display Name', 'formidable' ),
1340 'user_login' => __( 'User Login', 'formidable' ),
1341 'user_email' => __( 'Email', 'formidable' ),
1342 'avatar' => __( 'Avatar', 'formidable' ),
1343 'author_link' => __( 'Author Link', 'formidable' ),
1344 );
1345
1346 return apply_filters( 'frm_user_shortcodes', $options );
1347 }
1348
1349 /**
1350 * Get an array of the helper shortcodes to display in the customization panel
1351 *
1352 * @since 2.0.6
1353 */
1354 private static function get_shortcode_helpers( $settings_tab ) {
1355 $entry_shortcodes = array(
1356 'id' => __( 'Entry ID', 'formidable' ),
1357 'key' => __( 'Entry Key', 'formidable' ),
1358 'post_id' => __( 'Post ID', 'formidable' ),
1359 'ip' => __( 'User IP', 'formidable' ),
1360 'created-at' => __( 'Entry created', 'formidable' ),
1361 'updated-at' => __( 'Entry updated', 'formidable' ),
1362 '' => '',
1363 'siteurl' => __( 'Site URL', 'formidable' ),
1364 'sitename' => __( 'Site Name', 'formidable' ),
1365 );
1366
1367 if ( ! FrmAppHelper::pro_is_installed() ) {
1368 unset( $entry_shortcodes['post_id'] );
1369 }
1370
1371 if ( $settings_tab ) {
1372 $entry_shortcodes['default-message'] = __( 'Default Msg', 'formidable' );
1373 $entry_shortcodes['default-html'] = __( 'Default HTML', 'formidable' );
1374 $entry_shortcodes['default-plain'] = __( 'Default Plain', 'formidable' );
1375 }
1376
1377 /**
1378 * Use this hook to add or remove buttons in the helpers section
1379 * in the customization panel
1380 *
1381 * @since 2.0.6
1382 */
1383 $entry_shortcodes = apply_filters( 'frm_helper_shortcodes', $entry_shortcodes, $settings_tab );
1384
1385 return $entry_shortcodes;
1386 }
1387
1388 /**
1389 * Insert the form class setting into the form
1390 */
1391 public static function form_classes( $form ) {
1392 if ( isset( $form->options['form_class'] ) ) {
1393 echo esc_attr( sanitize_text_field( $form->options['form_class'] ) );
1394 }
1395
1396 if ( ! empty( $form->options['js_validate'] ) ) {
1397 echo ' frm_js_validate ';
1398 self::add_js_validate_form_to_global_vars( $form );
1399 }
1400 }
1401
1402 /**
1403 * @since 5.0.03
1404 *
1405 * @param stdClass $form
1406 */
1407 public static function add_js_validate_form_to_global_vars( $form ) {
1408 global $frm_vars;
1409 if ( ! isset( $frm_vars['js_validate_forms'] ) ) {
1410 $frm_vars['js_validate_forms'] = array();
1411 }
1412 $frm_vars['js_validate_forms'][ $form->id ] = $form;
1413 }
1414
1415 public static function get_email_html() {
1416 FrmAppHelper::permission_check( 'frm_view_forms' );
1417 check_ajax_referer( 'frm_ajax', 'nonce' );
1418
1419 echo FrmEntriesController::show_entry_shortcode( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1420 array(
1421 'form_id' => FrmAppHelper::get_post_param( 'form_id', '', 'absint' ),
1422 'default_email' => true,
1423 'plain_text' => FrmAppHelper::get_post_param( 'plain_text', '', 'absint' ),
1424 )
1425 );
1426 wp_die();
1427 }
1428
1429 public static function filter_content( $content, $form, $entry = false ) {
1430 self::get_entry_by_param( $entry );
1431 if ( ! $entry ) {
1432 return $content;
1433 }
1434
1435 if ( is_object( $form ) ) {
1436 $form = $form->id;
1437 }
1438
1439 $shortcodes = FrmFieldsHelper::get_shortcodes( $content, $form );
1440 $content = apply_filters( 'frm_replace_content_shortcodes', $content, $entry, $shortcodes );
1441
1442 return $content;
1443 }
1444
1445 private static function get_entry_by_param( &$entry ) {
1446 if ( ! $entry || ! is_object( $entry ) ) {
1447 if ( ! $entry || ! is_numeric( $entry ) ) {
1448 $entry = FrmAppHelper::get_post_param( 'id', false, 'sanitize_title' );
1449 }
1450
1451 FrmEntry::maybe_get_entry( $entry );
1452 }
1453 }
1454
1455 public static function replace_content_shortcodes( $content, $entry, $shortcodes ) {
1456 return FrmFieldsHelper::replace_content_shortcodes( $content, $entry, $shortcodes );
1457 }
1458
1459 public static function process_bulk_form_actions( $errors ) {
1460 if ( ! $_REQUEST ) {
1461 return $errors;
1462 }
1463
1464 $bulkaction = FrmAppHelper::get_param( 'action', '', 'get', 'sanitize_text_field' );
1465 if ( $bulkaction == - 1 ) {
1466 $bulkaction = FrmAppHelper::get_param( 'action2', '', 'get', 'sanitize_title' );
1467 }
1468
1469 if ( ! empty( $bulkaction ) && strpos( $bulkaction, 'bulk_' ) === 0 ) {
1470 FrmAppHelper::remove_get_action();
1471
1472 $bulkaction = str_replace( 'bulk_', '', $bulkaction );
1473 }
1474
1475 $ids = FrmAppHelper::get_param( 'item-action', '', 'get', 'sanitize_text_field' );
1476 if ( empty( $ids ) ) {
1477 $errors[] = __( 'No forms were specified', 'formidable' );
1478
1479 return $errors;
1480 }
1481
1482 $permission_error = FrmAppHelper::permission_nonce_error( '', '_wpnonce', 'bulk-toplevel_page_formidable' );
1483 if ( $permission_error !== false ) {
1484 $errors[] = $permission_error;
1485
1486 return $errors;
1487 }
1488
1489 if ( ! is_array( $ids ) ) {
1490 $ids = explode( ',', $ids );
1491 }
1492
1493 switch ( $bulkaction ) {
1494 case 'delete':
1495 $message = self::bulk_destroy( $ids );
1496 break;
1497 case 'trash':
1498 $message = self::bulk_trash( $ids );
1499 break;
1500 case 'untrash':
1501 $message = self::bulk_untrash( $ids );
1502 }
1503
1504 if ( isset( $message ) && ! empty( $message ) ) {
1505 $errors['message'] = $message;
1506 }
1507
1508 return $errors;
1509 }
1510
1511 public static function route() {
1512 $action = isset( $_REQUEST['frm_action'] ) ? 'frm_action' : 'action';
1513 $vars = array();
1514 FrmAppHelper::include_svg();
1515
1516 if ( isset( $_POST['frm_compact_fields'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1517 FrmAppHelper::permission_check( 'frm_edit_forms' );
1518
1519 // Javascript needs to be allowed in some field settings.
1520 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
1521 $json_vars = htmlspecialchars_decode( nl2br( str_replace( '&quot;', '"', wp_unslash( $_POST['frm_compact_fields'] ) ) ) );
1522 $json_vars = json_decode( $json_vars, true );
1523 if ( empty( $json_vars ) ) {
1524 // json decoding failed so we should return an error message.
1525 $action = FrmAppHelper::get_param( $action, '', 'get', 'sanitize_title' );
1526 if ( 'edit' == $action ) {
1527 $action = 'update';
1528 }
1529
1530 add_filter( 'frm_validate_form', 'FrmFormsController::json_error' );
1531 } else {
1532 $vars = FrmAppHelper::json_to_array( $json_vars );
1533 $action = $vars[ $action ];
1534 unset( $_REQUEST['frm_compact_fields'], $_POST['frm_compact_fields'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1535 $_REQUEST = array_merge( $_REQUEST, $vars ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1536 $_POST = array_merge( $_POST, $_REQUEST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1537 }
1538 } else {
1539 $action = FrmAppHelper::get_param( $action, '', 'get', 'sanitize_title' );
1540 if ( isset( $_REQUEST['delete_all'] ) ) {
1541 // Override the action for this page.
1542 $action = 'delete_all';
1543 }
1544 }
1545
1546 add_action( 'frm_load_form_hooks', 'FrmHooksController::trigger_load_form_hooks' );
1547 FrmAppHelper::trigger_hook_load( 'form' );
1548
1549 switch ( $action ) {
1550 case 'new':
1551 return self::new_form( $vars );
1552 case 'create':
1553 case 'edit':
1554 case 'update':
1555 case 'duplicate':
1556 case 'trash':
1557 case 'untrash':
1558 case 'destroy':
1559 case 'delete_all':
1560 case 'settings':
1561 case 'update_settings':
1562 return self::$action( $vars );
1563 case 'lite-reports':
1564 return self::no_reports( $vars );
1565 case 'views':
1566 return self::no_views( $vars );
1567 default:
1568 do_action( 'frm_form_action_' . $action );
1569 if ( apply_filters( 'frm_form_stop_action_' . $action, false ) ) {
1570 return;
1571 }
1572
1573 $action = FrmAppHelper::get_param( 'action', '', 'get', 'sanitize_text_field' );
1574 if ( $action == - 1 ) {
1575 $action = FrmAppHelper::get_param( 'action2', '', 'get', 'sanitize_title' );
1576 }
1577
1578 if ( strpos( $action, 'bulk_' ) === 0 ) {
1579 FrmAppHelper::remove_get_action();
1580
1581 return self::list_form();
1582 }
1583
1584 return self::display_forms_list();
1585 }
1586 }
1587
1588 public static function json_error( $errors ) {
1589 $errors['json'] = __( 'Abnormal HTML characters prevented your form from saving correctly', 'formidable' );
1590
1591 return $errors;
1592 }
1593
1594 /**
1595 * Education for premium features.
1596 *
1597 * @since 4.05
1598 */
1599 public static function add_form_style_tab_options() {
1600 include( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/add_form_style_options.php' );
1601 }
1602
1603 /**
1604 * Add education about views.
1605 *
1606 * @since 4.07
1607 */
1608 public static function no_views( $values = array() ) {
1609 FrmAppHelper::include_svg();
1610 $id = FrmAppHelper::get_param( 'form', '', 'get', 'absint' );
1611 $form = $id ? FrmForm::getOne( $id ) : false;
1612
1613 include FrmAppHelper::plugin_path() . '/classes/views/shared/views-info.php';
1614 }
1615
1616 /**
1617 * Add education about reports.
1618 *
1619 * @since 4.07
1620 */
1621 public static function no_reports( $values = array() ) {
1622 $id = FrmAppHelper::get_param( 'form', '', 'get', 'absint' );
1623 $form = $id ? FrmForm::getOne( $id ) : false;
1624
1625 include FrmAppHelper::plugin_path() . '/classes/views/shared/reports-info.php';
1626 }
1627
1628 /* FRONT-END FORMS */
1629 public static function admin_bar_css() {
1630 if ( is_admin() || ! current_user_can( 'frm_edit_forms' ) ) {
1631 return;
1632 }
1633
1634 self::move_menu_to_footer();
1635
1636 add_action( 'wp_before_admin_bar_render', 'FrmFormsController::admin_bar_configure' );
1637 FrmAppHelper::load_font_style();
1638 }
1639
1640 /**
1641 * @since 4.05.02
1642 */
1643 private static function move_menu_to_footer() {
1644 $settings = FrmAppHelper::get_settings();
1645 if ( empty( $settings->admin_bar ) ) {
1646 remove_action( 'wp_body_open', 'wp_admin_bar_render', 0 );
1647 }
1648 }
1649
1650 public static function admin_bar_configure() {
1651 global $frm_vars;
1652 if ( empty( $frm_vars['forms_loaded'] ) ) {
1653 return;
1654 }
1655
1656 $actions = array();
1657 foreach ( $frm_vars['forms_loaded'] as $form ) {
1658 if ( is_object( $form ) ) {
1659 $actions[ $form->id ] = $form->name;
1660 }
1661 unset( $form );
1662 }
1663
1664 if ( empty( $actions ) ) {
1665 return;
1666 }
1667
1668 self::add_menu_to_admin_bar();
1669 self::add_forms_to_admin_bar( $actions );
1670 }
1671
1672 /**
1673 * @since 2.05.07
1674 */
1675 public static function add_menu_to_admin_bar() {
1676 global $wp_admin_bar;
1677
1678 $wp_admin_bar->add_node(
1679 array(
1680 'id' => 'frm-forms',
1681 'title' => '<span class="ab-icon"></span><span class="ab-label">' . FrmAppHelper::get_menu_name() . '</span>',
1682 'href' => admin_url( 'admin.php?page=formidable' ),
1683 'meta' => array(
1684 'title' => FrmAppHelper::get_menu_name(),
1685 ),
1686 )
1687 );
1688 }
1689
1690 /**
1691 * @since 2.05.07
1692 */
1693 private static function add_forms_to_admin_bar( $actions ) {
1694 global $wp_admin_bar;
1695
1696 asort( $actions );
1697
1698 foreach ( $actions as $form_id => $name ) {
1699
1700 $wp_admin_bar->add_node(
1701 array(
1702 'parent' => 'frm-forms',
1703 'id' => 'edit_form_' . $form_id,
1704 'title' => empty( $name ) ? __( '(no title)', 'formidable' ) : $name,
1705 'href' => FrmForm::get_edit_link( $form_id ),
1706 )
1707 );
1708 }
1709 }
1710
1711 /**
1712 * The formidable shortcode
1713 *
1714 * @param array $atts The params from the shortcode.
1715 * @return string
1716 */
1717 public static function get_form_shortcode( $atts ) {
1718 global $frm_vars;
1719 if ( isset( $frm_vars['skip_shortcode'] ) && $frm_vars['skip_shortcode'] ) {
1720 $sc = '[formidable';
1721 $sc .= FrmAppHelper::array_to_html_params( $atts );
1722 return $sc . ']';
1723 }
1724
1725 $shortcode_atts = shortcode_atts(
1726 array(
1727 'id' => '',
1728 'key' => '',
1729 'title' => 'auto',
1730 'description' => 'auto',
1731 'readonly' => false,
1732 'entry_id' => false,
1733 'fields' => array(),
1734 'exclude_fields' => array(),
1735 'minimize' => false,
1736 ),
1737 $atts
1738 );
1739 do_action( 'formidable_shortcode_atts', $shortcode_atts, $atts );
1740
1741 return self::show_form( $shortcode_atts['id'], $shortcode_atts['key'], $shortcode_atts['title'], $shortcode_atts['description'], $atts );
1742 }
1743
1744 /**
1745 * @since 5.2.01
1746 *
1747 * @param string|int|false $id
1748 * @param string|false $key
1749 * @return stdClass|false
1750 */
1751 private static function maybe_get_form_by_id_or_key( $id, $key ) {
1752 if ( ! $id ) {
1753 $id = $key;
1754 }
1755 return self::maybe_get_form_to_show( $id );
1756 }
1757
1758 /**
1759 * @param string|int|false $id
1760 * @param string|false $key
1761 * @param string|int|bool $title may be 'auto', true, false, 'true', 'false', 'yes', '1', 1, '0', 0.
1762 * @param string|int|bool $description may be 'auto', true, false, 'true', 'false', 'yes', '1', 1, '0', 0.
1763 * @param array $atts
1764 * @return string
1765 */
1766 public static function show_form( $id = '', $key = '', $title = false, $description = false, $atts = array() ) {
1767 $form = self::maybe_get_form_by_id_or_key( $id, $key );
1768
1769 if ( ! $form ) {
1770 return __( 'Please select a valid form', 'formidable' );
1771 }
1772
1773 if ( 'auto' === $title ) {
1774 $title = ! empty( $form->options['show_title'] );
1775 }
1776
1777 if ( 'auto' === $description ) {
1778 $description = ! empty( $form->options['show_description'] );
1779 }
1780
1781 FrmAppController::maybe_update_styles();
1782
1783 add_action( 'frm_load_form_hooks', 'FrmHooksController::trigger_load_form_hooks' );
1784 FrmAppHelper::trigger_hook_load( 'form', $form );
1785
1786 $form = apply_filters( 'frm_pre_display_form', $form );
1787
1788 $frm_settings = FrmAppHelper::get_settings( array( 'current_form' => $form->id ) );
1789
1790 if ( self::is_viewable_draft_form( $form ) ) {
1791 // don't show a draft form on a page
1792 $form = __( 'Please select a valid form', 'formidable' );
1793 } elseif ( ! FrmForm::is_visible_to_user( $form ) ) {
1794 $form = do_shortcode( $frm_settings->login_msg );
1795 } else {
1796 do_action( 'frm_pre_get_form', $form );
1797 $form = self::get_form( $form, $title, $description, $atts );
1798
1799 /**
1800 * Use this shortcode to check for external shortcodes that may span
1801 * across multiple fields in the customizable HTML
1802 *
1803 * @since 2.0.8
1804 */
1805 $form = apply_filters( 'frm_filter_final_form', $form );
1806 }
1807
1808 return $form;
1809 }
1810
1811 /**
1812 * @param string|int|false $id
1813 * @return stdClass|false
1814 */
1815 private static function maybe_get_form_to_show( $id ) {
1816 $form = false;
1817
1818 if ( ! empty( $id ) ) { // form id or key is set
1819 $form = FrmForm::getOne( $id );
1820 if ( ! $form || $form->parent_form_id || $form->status === 'trash' ) {
1821 $form = false;
1822 }
1823 }
1824
1825 return $form;
1826 }
1827
1828 private static function is_viewable_draft_form( $form ) {
1829 return $form->status === 'draft' && current_user_can( 'frm_edit_forms' ) && ! FrmAppHelper::is_preview_page();
1830 }
1831
1832 public static function get_form( $form, $title, $description, $atts = array() ) {
1833 ob_start();
1834
1835 do_action( 'frm_before_get_form', $atts );
1836
1837 self::get_form_contents( $form, $title, $description, $atts );
1838 self::enqueue_scripts( FrmForm::get_params( $form ) );
1839
1840 $contents = ob_get_contents();
1841 ob_end_clean();
1842
1843 self::maybe_minimize_form( $atts, $contents );
1844
1845 return $contents;
1846 }
1847
1848 public static function enqueue_scripts( $params ) {
1849 do_action( 'frm_enqueue_form_scripts', $params );
1850 }
1851
1852 public static function get_form_contents( $form, $title, $description, $atts ) {
1853 $params = FrmForm::get_params( $form );
1854 $errors = self::get_saved_errors( $form, $params );
1855 $fields = FrmFieldsHelper::get_form_fields( $form->id, $errors );
1856 $reset = false;
1857 $pass_args = compact( 'form', 'fields', 'errors', 'title', 'description', 'reset' );
1858
1859 $handle_process_here = $params['action'] === 'create' && $params['posted_form_id'] == $form->id && $_POST; // phpcs:ignore WordPress.Security.NonceVerification.Missing
1860
1861 if ( ! $handle_process_here ) {
1862 do_action( 'frm_display_form_action', $params, $fields, $form, $title, $description );
1863 if ( apply_filters( 'frm_continue_to_new', true, $form->id, $params['action'] ) ) {
1864 self::show_form_after_submit( $pass_args );
1865 }
1866 } elseif ( ! empty( $errors ) ) {
1867 self::show_form_after_submit( $pass_args );
1868
1869 } else {
1870
1871 do_action( 'frm_validate_form_creation', $params, $fields, $form, $title, $description );
1872
1873 if ( apply_filters( 'frm_continue_to_create', true, $form->id ) ) {
1874 $entry_id = self::just_created_entry( $form->id );
1875 $pass_args['entry_id'] = $entry_id;
1876 $pass_args['reset'] = true;
1877 $pass_args['conf_method'] = self::get_confirmation_method( compact( 'form', 'entry_id' ) );
1878
1879 self::run_success_action( $pass_args );
1880
1881 do_action(
1882 'frm_after_entry_processed',
1883 array(
1884 'entry_id' => $entry_id,
1885 'form' => $form,
1886 )
1887 );
1888 }
1889 }
1890 }
1891
1892 /**
1893 * If the form was processed earlier (init), get the generated errors
1894 *
1895 * @since 2.05
1896 */
1897 private static function get_saved_errors( $form, $params ) {
1898 global $frm_vars;
1899
1900 if ( $params['posted_form_id'] == $form->id && $_POST && isset( $frm_vars['created_entries'][ $form->id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1901 $errors = $frm_vars['created_entries'][ $form->id ]['errors'];
1902 } else {
1903 $errors = array();
1904 }
1905
1906 /**
1907 * Allows modifying the generated errors if the form was processed earlier.
1908 *
1909 * @since 5.2.03
1910 *
1911 * @param array $errors Errors data. Is empty array if no errors found.
1912 * @param array $params Form params. See {@see FrmForm::get_params()}.
1913 */
1914 return apply_filters( 'frm_saved_errors', $errors, $params );
1915 }
1916
1917 /**
1918 * @since 2.2.7
1919 */
1920 public static function just_created_entry( $form_id ) {
1921 global $frm_vars;
1922
1923 return ( isset( $frm_vars['created_entries'] ) && isset( $frm_vars['created_entries'][ $form_id ] ) && isset( $frm_vars['created_entries'][ $form_id ]['entry_id'] ) ) ? $frm_vars['created_entries'][ $form_id ]['entry_id'] : 0;
1924 }
1925
1926 /**
1927 * @since 3.0
1928 */
1929 private static function get_confirmation_method( $atts ) {
1930 $opt = 'success_action';
1931 $method = ( isset( $atts['form']->options[ $opt ] ) && ! empty( $atts['form']->options[ $opt ] ) ) ? $atts['form']->options[ $opt ] : 'message';
1932 $method = apply_filters( 'frm_success_filter', $method, $atts['form'], 'create' );
1933
1934 if ( $method != 'message' && ( ! $atts['entry_id'] || ! is_numeric( $atts['entry_id'] ) ) ) {
1935 $method = 'message';
1936 }
1937
1938 return $method;
1939 }
1940
1941 public static function maybe_trigger_redirect( $form, $params, $args ) {
1942 if ( ! isset( $params['id'] ) ) {
1943 global $frm_vars;
1944 $params['id'] = $frm_vars['created_entries'][ $form->id ]['entry_id'];
1945 }
1946
1947 $conf_method = self::get_confirmation_method(
1948 array(
1949 'form' => $form,
1950 'entry_id' => $params['id'],
1951 )
1952 );
1953
1954 if ( 'redirect' === $conf_method ) {
1955 self::trigger_redirect( $form, $params, $args );
1956 }
1957 }
1958
1959 public static function trigger_redirect( $form, $params, $args ) {
1960 $success_args = array(
1961 'action' => $params['action'],
1962 'conf_method' => 'redirect',
1963 'form' => $form,
1964 'entry_id' => $params['id'],
1965 );
1966
1967 if ( isset( $args['ajax'] ) ) {
1968 $success_args['ajax'] = $args['ajax'];
1969 }
1970
1971 self::run_success_action( $success_args );
1972 }
1973
1974 /**
1975 * Used when the success action is not 'message'
1976 *
1977 * @since 2.05
1978 */
1979 public static function run_success_action( $args ) {
1980 $extra_args = $args;
1981 unset( $extra_args['form'] );
1982
1983 do_action( 'frm_success_action', $args['conf_method'], $args['form'], $args['form']->options, $args['entry_id'], $extra_args );
1984
1985 $opt = ( ! isset( $args['action'] ) || $args['action'] === 'create' ) ? 'success' : 'edit';
1986
1987 $args['success_opt'] = $opt;
1988 if ( $args['conf_method'] === 'page' && is_numeric( $args['form']->options[ $opt . '_page_id' ] ) ) {
1989 self::load_page_after_submit( $args );
1990 } elseif ( $args['conf_method'] === 'redirect' ) {
1991 self::redirect_after_submit( $args );
1992 } else {
1993 self::show_message_after_save( $args );
1994 }
1995 }
1996
1997 /**
1998 * @since 3.0
1999 */
2000 private static function load_page_after_submit( $args ) {
2001 global $post;
2002 $opt = $args['success_opt'];
2003 if ( ! $post || $args['form']->options[ $opt . '_page_id' ] != $post->ID ) {
2004 $page = get_post( $args['form']->options[ $opt . '_page_id' ] );
2005 $old_post = $post;
2006 $post = $page;
2007 $content = apply_filters( 'frm_content', $page->post_content, $args['form'], $args['entry_id'] );
2008 echo apply_filters( 'the_content', $content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
2009 $post = $old_post;
2010 }
2011 }
2012
2013 /**
2014 * @since 3.0
2015 */
2016 private static function redirect_after_submit( $args ) {
2017 global $frm_vars;
2018
2019 add_filter( 'frm_use_wpautop', '__return_false' );
2020
2021 $opt = $args['success_opt'];
2022 $success_url = trim( $args['form']->options[ $opt . '_url' ] );
2023 $success_url = apply_filters( 'frm_content', $success_url, $args['form'], $args['entry_id'] );
2024 $success_url = do_shortcode( $success_url );
2025
2026 $success_msg = isset( $args['form']->options[ $opt . '_msg' ] ) ? $args['form']->options[ $opt . '_msg' ] : __( 'Please wait while you are redirected.', 'formidable' );
2027
2028 $redirect_msg = self::get_redirect_message( $success_url, $success_msg, $args );
2029
2030 $args['id'] = $args['entry_id'];
2031 FrmEntriesController::delete_entry_before_redirect( $success_url, $args['form'], $args );
2032
2033 add_filter( 'frm_redirect_url', 'FrmEntriesController::prepare_redirect_url' );
2034 $success_url = apply_filters( 'frm_redirect_url', $success_url, $args['form'], $args );
2035
2036 $doing_ajax = FrmAppHelper::doing_ajax();
2037
2038 if ( isset( $args['ajax'] ) && $args['ajax'] && $doing_ajax ) {
2039 echo json_encode( array( 'redirect' => $success_url ) );
2040 wp_die();
2041 } elseif ( ! headers_sent() ) {
2042 wp_redirect( esc_url_raw( $success_url ) );
2043 die(); // do not use wp_die or redirect fails
2044 } else {
2045 add_filter( 'frm_use_wpautop', '__return_true' );
2046 echo FrmAppHelper::maybe_kses( $redirect_msg ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
2047 echo "<script type='text/javascript'>window.onload = function(){setTimeout(window.location='" . esc_url_raw( $success_url ) . "', 8000);}</script>";
2048 }
2049 }
2050
2051 /**
2052 * @since 3.0
2053 *
2054 * @param string $success_url
2055 * @param string $success_msg
2056 * @param array $args
2057 */
2058 private static function get_redirect_message( $success_url, $success_msg, $args ) {
2059 $redirect_msg = '<div class="' . esc_attr( FrmFormsHelper::get_form_style_class( $args['form'] ) ) . '"><div class="frm-redirect-msg frm_message" role="status">' . $success_msg . '<br/>' .
2060 /* translators: %1$s: Start link HTML, %2$s: End link HTML */
2061 sprintf( __( '%1$sClick here%2$s if you are not automatically redirected.', 'formidable' ), '<a href="' . esc_url( $success_url ) . '">', '</a>' ) .
2062 '</div></div>';
2063
2064 $redirect_args = array(
2065 'entry_id' => $args['entry_id'],
2066 'form_id' => $args['form']->id,
2067 'form' => $args['form'],
2068 );
2069
2070 return apply_filters( 'frm_redirect_msg', $redirect_msg, $redirect_args );
2071 }
2072
2073 /**
2074 * Prepare to show the success message and empty form after submit
2075 *
2076 * @since 2.05
2077 */
2078 public static function show_message_after_save( $atts ) {
2079 $atts['message'] = self::prepare_submit_message( $atts['form'], $atts['entry_id'] );
2080
2081 if ( ! isset( $atts['form']->options['show_form'] ) || $atts['form']->options['show_form'] ) {
2082 self::show_form_after_submit( $atts );
2083 } else {
2084 self::show_lone_success_messsage( $atts );
2085 }
2086 }
2087
2088 /**
2089 * Show an empty form
2090 *
2091 * @since 2.05
2092 */
2093 private static function show_form_after_submit( $args ) {
2094 self::fill_atts_for_form_display( $args );
2095
2096 $errors = $args['errors'];
2097 $message = $args['message'];
2098 $form = $args['form'];
2099 $title = $args['title'];
2100 $description = $args['description'];
2101
2102 if ( empty( $args['fields'] ) ) {
2103 $values = array(
2104 'custom_style' => FrmAppHelper::custom_style_value( array() ),
2105 );
2106 } else {
2107 $values = FrmEntriesHelper::setup_new_vars( $args['fields'], $form, $args['reset'] );
2108 }
2109 unset( $args );
2110
2111 $include_form_tag = apply_filters( 'frm_include_form_tag', true, $form );
2112
2113 $frm_settings = FrmAppHelper::get_settings();
2114 $submit = isset( $form->options['submit_value'] ) ? $form->options['submit_value'] : $frm_settings->submit_value;
2115
2116 global $frm_vars;
2117 self::maybe_load_css( $form, $values['custom_style'], $frm_vars['load_css'] );
2118
2119 $message_placement = self::message_placement( $form, $message );
2120
2121 include FrmAppHelper::plugin_path() . '/classes/views/frm-entries/new.php';
2122 }
2123
2124 /**
2125 * @return string - 'before', 'after', or 'submit'
2126 *
2127 * @since 4.05.02
2128 */
2129 private static function message_placement( $form, $message ) {
2130 $place = 'before';
2131
2132 if ( $message && isset( $form->options['form_class'] ) ) {
2133 if ( strpos( $form->options['form_class'], 'frm_below_success' ) !== false ) {
2134 $place = 'after';
2135 } elseif ( strpos( $form->options['form_class'], 'frm_inline_success' ) !== false ) {
2136 $place = 'submit';
2137 }
2138 }
2139
2140 /**
2141 * @return string - 'before' or 'after'
2142 *
2143 * @since 4.05.02
2144 */
2145 return apply_filters( 'frm_message_placement', $place, compact( 'form', 'message' ) );
2146 }
2147
2148 /**
2149 * Get all the values needed on the new.php entry page
2150 *
2151 * @since 2.05
2152 */
2153 private static function fill_atts_for_form_display( &$args ) {
2154 $defaults = array(
2155 'errors' => array(),
2156 'message' => '',
2157 'fields' => array(),
2158 'form' => array(),
2159 'title' => true,
2160 'description' => false,
2161 'reset' => false,
2162 );
2163 $args = wp_parse_args( $args, $defaults );
2164 }
2165
2166 /**
2167 * Show the success message without the form
2168 *
2169 * @since 2.05
2170 */
2171 private static function show_lone_success_messsage( $atts ) {
2172 global $frm_vars;
2173 $values = FrmEntriesHelper::setup_new_vars( $atts['fields'], $atts['form'], true );
2174 self::maybe_load_css( $atts['form'], $values['custom_style'], $frm_vars['load_css'] );
2175
2176 $include_extra_container = 'frm_forms' . FrmFormsHelper::get_form_style_class( $values );
2177
2178 $errors = array();
2179 $form = $atts['form'];
2180 $message = $atts['message'];
2181
2182 include( FrmAppHelper::plugin_path() . '/classes/views/frm-entries/errors.php' );
2183 }
2184
2185 /**
2186 * Prepare the success message before it's shown
2187 *
2188 * @since 2.05
2189 */
2190 private static function prepare_submit_message( $form, $entry_id ) {
2191 $frm_settings = FrmAppHelper::get_settings( array( 'current_form' => $form->id ) );
2192
2193 if ( $entry_id && is_numeric( $entry_id ) ) {
2194 $message = isset( $form->options['success_msg'] ) ? $form->options['success_msg'] : $frm_settings->success_msg;
2195 $class = 'frm_message';
2196 } else {
2197 $message = $frm_settings->failed_msg;
2198 $class = FrmFormsHelper::form_error_class();
2199 }
2200
2201 $message = FrmFormsHelper::get_success_message( compact( 'message', 'form', 'entry_id', 'class' ) );
2202
2203 return apply_filters( 'frm_main_feedback', $message, $form, $entry_id );
2204 }
2205
2206 public static function front_head() {
2207 $version = FrmAppHelper::plugin_version();
2208 $suffix = FrmAppHelper::js_suffix();
2209
2210 if ( ! empty( $suffix ) && self::has_combo_js_file() ) {
2211 wp_register_script( 'formidable', FrmAppHelper::plugin_url() . '/js/frm.min.js', array( 'jquery' ), $version, true );
2212 } else {
2213 wp_register_script( 'formidable', FrmAppHelper::plugin_url() . "/js/formidable{$suffix}.js", array( 'jquery' ), $version, true );
2214 }
2215
2216 add_filter( 'script_loader_tag', 'FrmFormsController::defer_script_loading', 10, 2 );
2217
2218 if ( FrmAppHelper::is_admin() ) {
2219 // don't load this in back-end
2220 return;
2221 }
2222
2223 FrmAppHelper::localize_script( 'front' );
2224 FrmStylesController::enqueue_css( 'register' );
2225 }
2226
2227 /**
2228 * @since 3.0
2229 */
2230 public static function has_combo_js_file() {
2231 return is_readable( FrmAppHelper::plugin_path() . '/js/frm.min.js' );
2232 }
2233
2234 public static function maybe_load_css( $form, $this_load, $global_load ) {
2235 $load_css = FrmForm::is_form_loaded( $form, $this_load, $global_load );
2236
2237 if ( ! $load_css ) {
2238 return;
2239 }
2240
2241 global $frm_vars;
2242 self::footer_js( 'header' );
2243 $frm_vars['css_loaded'] = true;
2244
2245 self::load_late_css();
2246 }
2247
2248 /**
2249 * If css is loaded only on applicable pages, include it before the form loads
2250 * to prevent a flash of unstyled form.
2251 *
2252 * @since 4.01
2253 */
2254 private static function load_late_css() {
2255 $frm_settings = FrmAppHelper::get_settings();
2256 $late_css = $frm_settings->load_style === 'dynamic';
2257 if ( ! $late_css ) {
2258 return;
2259 }
2260
2261 global $wp_styles;
2262 if ( is_array( $wp_styles->queue ) && in_array( 'formidable', $wp_styles->queue ) ) {
2263 wp_print_styles( 'formidable' );
2264 }
2265 }
2266
2267 public static function defer_script_loading( $tag, $handle ) {
2268 if ( 'recaptcha-api' == $handle && ! strpos( $tag, 'defer' ) ) {
2269 $tag = str_replace( ' src', ' defer="defer" async="async" src', $tag );
2270 }
2271
2272 return $tag;
2273 }
2274
2275 public static function footer_js( $location = 'footer' ) {
2276 global $frm_vars;
2277
2278 FrmStylesController::enqueue_css();
2279
2280 if ( ! FrmAppHelper::is_admin() && $location != 'header' && ! empty( $frm_vars['forms_loaded'] ) ) {
2281 // load formidable js
2282 wp_enqueue_script( 'formidable' );
2283 }
2284 }
2285
2286 /**
2287 * @since 2.0.8
2288 */
2289 private static function maybe_minimize_form( $atts, &$content ) {
2290 // check if minimizing is turned on
2291 if ( self::is_minification_on( $atts ) ) {
2292 $content = str_replace( array( "\r\n", "\r", "\n", "\t", ' ' ), '', $content );
2293 }
2294 }
2295
2296 /**
2297 * @since 2.0.8
2298 * @return boolean
2299 */
2300 private static function is_minification_on( $atts ) {
2301 return isset( $atts['minimize'] ) && ! empty( $atts['minimize'] );
2302 }
2303
2304 /**
2305 * @since 5.0.16
2306 *
2307 * @return void
2308 */
2309 public static function landing_page_preview_option() {
2310 $dir = apply_filters( 'frm_landing_page_preview_option', false );
2311 if ( false === $dir || ! file_exists( $dir . 'landing-page-preview-option.php' ) ) {
2312 $dir = self::get_form_views_path();
2313 }
2314 include $dir . 'landing-page-preview-option.php';
2315 }
2316
2317 /**
2318 * @since 5.0.16
2319 *
2320 * @return string
2321 */
2322 private static function get_form_views_path() {
2323 return FrmAppHelper::plugin_path() . '/classes/views/frm-forms/';
2324 }
2325
2326 /**
2327 * Create a page with an embedded formidable Gutenberg block.
2328 *
2329 * @since 5.2
2330 *
2331 * @return never
2332 */
2333 public static function create_page_with_shortcode() {
2334 if ( ! current_user_can( 'publish_posts' ) ) {
2335 die( 0 );
2336 }
2337
2338 check_ajax_referer( 'frm_ajax', 'nonce' );
2339
2340 $form_id = FrmAppHelper::get_post_param( 'form_id', '', 'absint' );
2341 if ( ! $form_id ) {
2342 die( 0 );
2343 }
2344
2345 $postarr = array(
2346 'post_type' => 'page',
2347 'post_content' => '<!-- wp:formidable/simple-form {"formId":"' . $form_id . '"} --><div>[formidable id="' . $form_id . '"]</div><!-- /wp:formidable/simple-form -->',
2348 );
2349
2350 $name = FrmAppHelper::get_post_param( 'name', '', 'sanitize_text_field' );
2351 if ( $name ) {
2352 $postarr['post_title'] = $name;
2353 }
2354
2355 $success = wp_insert_post( $postarr );
2356 if ( ! is_numeric( $success ) || ! $success ) {
2357 die( 0 );
2358 }
2359
2360 wp_send_json(
2361 array(
2362 'redirect' => get_edit_post_link( $success, 'redirect' ),
2363 )
2364 );
2365 }
2366
2367 /**
2368 * Get page dropdown for AJAX request for embedding form in an existing page.
2369 *
2370 * @return never
2371 */
2372 public static function get_page_dropdown() {
2373 if ( ! current_user_can( 'publish_posts' ) ) {
2374 die( 0 );
2375 }
2376
2377 check_ajax_referer( 'frm_ajax', 'nonce' );
2378
2379 $html = FrmAppHelper::clip(
2380 function() {
2381 FrmAppHelper::maybe_autocomplete_pages_options(
2382 array(
2383 'field_name' => 'frm_page_dropdown',
2384 'page_id' => '',
2385 'placeholder' => __( 'Select a Page', 'formidable' ),
2386 )
2387 );
2388 }
2389 );
2390 $post_type_object = get_post_type_object( 'page' );
2391 wp_send_json(
2392 array(
2393 'html' => $html,
2394 'edit_page_url' => admin_url( sprintf( $post_type_object->_edit_link . '&action=edit', 0 ) ),
2395 )
2396 );
2397 }
2398
2399 /**
2400 * @deprecated 4.0
2401 */
2402 public static function new_form( $values = array() ) {
2403 FrmDeprecated::new_form( $values );
2404 }
2405
2406 /**
2407 * @deprecated 4.0
2408 */
2409 public static function create( $values = array() ) {
2410 _deprecated_function( __METHOD__, '4.0', 'FrmFormsController::update' );
2411 self::update( $values );
2412 }
2413
2414 /**
2415 * @deprecated 1.07.05
2416 * @codeCoverageIgnore
2417 */
2418 public static function add_default_templates( $path, $default = true, $template = true ) {
2419 FrmDeprecated::add_default_templates( $path, $default, $template );
2420 }
2421
2422 /**
2423 * @deprecated 3.0
2424 * @codeCoverageIgnore
2425 */
2426 public static function bulk_create_template( $ids ) {
2427 return FrmDeprecated::bulk_create_template( $ids );
2428 }
2429
2430 /**
2431 * @deprecated 2.03
2432 * @codeCoverageIgnore
2433 */
2434 public static function register_pro_scripts() {
2435 FrmDeprecated::register_pro_scripts();
2436 }
2437
2438 /**
2439 * @deprecated 3.0
2440 * @codeCoverageIgnore
2441 */
2442 public static function edit_key() {
2443 FrmDeprecated::edit_key();
2444 }
2445
2446 /**
2447 * @deprecated 3.0
2448 * @codeCoverageIgnore
2449 */
2450 public static function edit_description() {
2451 FrmDeprecated::edit_description();
2452 }
2453
2454 /**
2455 * @deprecated 4.08
2456 * @since 3.06
2457 */
2458 public static function add_new() {
2459 _deprecated_function( __FUNCTION__, '4.08' );
2460 }
2461 }
2462