PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.2.02
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.2.02
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.02, at classes/controllers/FrmFormsController.php

2,454 lines 70.8 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 return $errors;
1907 }
1908
1909 /**
1910 * @since 2.2.7
1911 */
1912 public static function just_created_entry( $form_id ) {
1913 global $frm_vars;
1914
1915 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;
1916 }
1917
1918 /**
1919 * @since 3.0
1920 */
1921 private static function get_confirmation_method( $atts ) {
1922 $opt = 'success_action';
1923 $method = ( isset( $atts['form']->options[ $opt ] ) && ! empty( $atts['form']->options[ $opt ] ) ) ? $atts['form']->options[ $opt ] : 'message';
1924 $method = apply_filters( 'frm_success_filter', $method, $atts['form'], 'create' );
1925
1926 if ( $method != 'message' && ( ! $atts['entry_id'] || ! is_numeric( $atts['entry_id'] ) ) ) {
1927 $method = 'message';
1928 }
1929
1930 return $method;
1931 }
1932
1933 public static function maybe_trigger_redirect( $form, $params, $args ) {
1934 if ( ! isset( $params['id'] ) ) {
1935 global $frm_vars;
1936 $params['id'] = $frm_vars['created_entries'][ $form->id ]['entry_id'];
1937 }
1938
1939 $conf_method = self::get_confirmation_method(
1940 array(
1941 'form' => $form,
1942 'entry_id' => $params['id'],
1943 )
1944 );
1945
1946 if ( 'redirect' === $conf_method ) {
1947 self::trigger_redirect( $form, $params, $args );
1948 }
1949 }
1950
1951 public static function trigger_redirect( $form, $params, $args ) {
1952 $success_args = array(
1953 'action' => $params['action'],
1954 'conf_method' => 'redirect',
1955 'form' => $form,
1956 'entry_id' => $params['id'],
1957 );
1958
1959 if ( isset( $args['ajax'] ) ) {
1960 $success_args['ajax'] = $args['ajax'];
1961 }
1962
1963 self::run_success_action( $success_args );
1964 }
1965
1966 /**
1967 * Used when the success action is not 'message'
1968 *
1969 * @since 2.05
1970 */
1971 public static function run_success_action( $args ) {
1972 $extra_args = $args;
1973 unset( $extra_args['form'] );
1974
1975 do_action( 'frm_success_action', $args['conf_method'], $args['form'], $args['form']->options, $args['entry_id'], $extra_args );
1976
1977 $opt = ( ! isset( $args['action'] ) || $args['action'] === 'create' ) ? 'success' : 'edit';
1978
1979 $args['success_opt'] = $opt;
1980 if ( $args['conf_method'] === 'page' && is_numeric( $args['form']->options[ $opt . '_page_id' ] ) ) {
1981 self::load_page_after_submit( $args );
1982 } elseif ( $args['conf_method'] === 'redirect' ) {
1983 self::redirect_after_submit( $args );
1984 } else {
1985 self::show_message_after_save( $args );
1986 }
1987 }
1988
1989 /**
1990 * @since 3.0
1991 */
1992 private static function load_page_after_submit( $args ) {
1993 global $post;
1994 $opt = $args['success_opt'];
1995 if ( ! $post || $args['form']->options[ $opt . '_page_id' ] != $post->ID ) {
1996 $page = get_post( $args['form']->options[ $opt . '_page_id' ] );
1997 $old_post = $post;
1998 $post = $page;
1999 $content = apply_filters( 'frm_content', $page->post_content, $args['form'], $args['entry_id'] );
2000 echo apply_filters( 'the_content', $content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
2001 $post = $old_post;
2002 }
2003 }
2004
2005 /**
2006 * @since 3.0
2007 */
2008 private static function redirect_after_submit( $args ) {
2009 global $frm_vars;
2010
2011 add_filter( 'frm_use_wpautop', '__return_false' );
2012
2013 $opt = $args['success_opt'];
2014 $success_url = trim( $args['form']->options[ $opt . '_url' ] );
2015 $success_url = apply_filters( 'frm_content', $success_url, $args['form'], $args['entry_id'] );
2016 $success_url = do_shortcode( $success_url );
2017
2018 $success_msg = isset( $args['form']->options[ $opt . '_msg' ] ) ? $args['form']->options[ $opt . '_msg' ] : __( 'Please wait while you are redirected.', 'formidable' );
2019
2020 $redirect_msg = self::get_redirect_message( $success_url, $success_msg, $args );
2021
2022 $args['id'] = $args['entry_id'];
2023 FrmEntriesController::delete_entry_before_redirect( $success_url, $args['form'], $args );
2024
2025 add_filter( 'frm_redirect_url', 'FrmEntriesController::prepare_redirect_url' );
2026 $success_url = apply_filters( 'frm_redirect_url', $success_url, $args['form'], $args );
2027
2028 $doing_ajax = FrmAppHelper::doing_ajax();
2029
2030 if ( isset( $args['ajax'] ) && $args['ajax'] && $doing_ajax ) {
2031 echo json_encode( array( 'redirect' => $success_url ) );
2032 wp_die();
2033 } elseif ( ! headers_sent() ) {
2034 wp_redirect( esc_url_raw( $success_url ) );
2035 die(); // do not use wp_die or redirect fails
2036 } else {
2037 add_filter( 'frm_use_wpautop', '__return_true' );
2038 echo FrmAppHelper::maybe_kses( $redirect_msg ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
2039 echo "<script type='text/javascript'>window.onload = function(){setTimeout(window.location='" . esc_url_raw( $success_url ) . "', 8000);}</script>";
2040 }
2041 }
2042
2043 /**
2044 * @since 3.0
2045 *
2046 * @param string $success_url
2047 * @param string $success_msg
2048 * @param array $args
2049 */
2050 private static function get_redirect_message( $success_url, $success_msg, $args ) {
2051 $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/>' .
2052 /* translators: %1$s: Start link HTML, %2$s: End link HTML */
2053 sprintf( __( '%1$sClick here%2$s if you are not automatically redirected.', 'formidable' ), '<a href="' . esc_url( $success_url ) . '">', '</a>' ) .
2054 '</div></div>';
2055
2056 $redirect_args = array(
2057 'entry_id' => $args['entry_id'],
2058 'form_id' => $args['form']->id,
2059 'form' => $args['form'],
2060 );
2061
2062 return apply_filters( 'frm_redirect_msg', $redirect_msg, $redirect_args );
2063 }
2064
2065 /**
2066 * Prepare to show the success message and empty form after submit
2067 *
2068 * @since 2.05
2069 */
2070 public static function show_message_after_save( $atts ) {
2071 $atts['message'] = self::prepare_submit_message( $atts['form'], $atts['entry_id'] );
2072
2073 if ( ! isset( $atts['form']->options['show_form'] ) || $atts['form']->options['show_form'] ) {
2074 self::show_form_after_submit( $atts );
2075 } else {
2076 self::show_lone_success_messsage( $atts );
2077 }
2078 }
2079
2080 /**
2081 * Show an empty form
2082 *
2083 * @since 2.05
2084 */
2085 private static function show_form_after_submit( $args ) {
2086 self::fill_atts_for_form_display( $args );
2087
2088 $errors = $args['errors'];
2089 $message = $args['message'];
2090 $form = $args['form'];
2091 $title = $args['title'];
2092 $description = $args['description'];
2093
2094 if ( empty( $args['fields'] ) ) {
2095 $values = array(
2096 'custom_style' => FrmAppHelper::custom_style_value( array() ),
2097 );
2098 } else {
2099 $values = FrmEntriesHelper::setup_new_vars( $args['fields'], $form, $args['reset'] );
2100 }
2101 unset( $args );
2102
2103 $include_form_tag = apply_filters( 'frm_include_form_tag', true, $form );
2104
2105 $frm_settings = FrmAppHelper::get_settings();
2106 $submit = isset( $form->options['submit_value'] ) ? $form->options['submit_value'] : $frm_settings->submit_value;
2107
2108 global $frm_vars;
2109 self::maybe_load_css( $form, $values['custom_style'], $frm_vars['load_css'] );
2110
2111 $message_placement = self::message_placement( $form, $message );
2112
2113 include FrmAppHelper::plugin_path() . '/classes/views/frm-entries/new.php';
2114 }
2115
2116 /**
2117 * @return string - 'before', 'after', or 'submit'
2118 *
2119 * @since 4.05.02
2120 */
2121 private static function message_placement( $form, $message ) {
2122 $place = 'before';
2123
2124 if ( $message && isset( $form->options['form_class'] ) ) {
2125 if ( strpos( $form->options['form_class'], 'frm_below_success' ) !== false ) {
2126 $place = 'after';
2127 } elseif ( strpos( $form->options['form_class'], 'frm_inline_success' ) !== false ) {
2128 $place = 'submit';
2129 }
2130 }
2131
2132 /**
2133 * @return string - 'before' or 'after'
2134 *
2135 * @since 4.05.02
2136 */
2137 return apply_filters( 'frm_message_placement', $place, compact( 'form', 'message' ) );
2138 }
2139
2140 /**
2141 * Get all the values needed on the new.php entry page
2142 *
2143 * @since 2.05
2144 */
2145 private static function fill_atts_for_form_display( &$args ) {
2146 $defaults = array(
2147 'errors' => array(),
2148 'message' => '',
2149 'fields' => array(),
2150 'form' => array(),
2151 'title' => true,
2152 'description' => false,
2153 'reset' => false,
2154 );
2155 $args = wp_parse_args( $args, $defaults );
2156 }
2157
2158 /**
2159 * Show the success message without the form
2160 *
2161 * @since 2.05
2162 */
2163 private static function show_lone_success_messsage( $atts ) {
2164 global $frm_vars;
2165 $values = FrmEntriesHelper::setup_new_vars( $atts['fields'], $atts['form'], true );
2166 self::maybe_load_css( $atts['form'], $values['custom_style'], $frm_vars['load_css'] );
2167
2168 $include_extra_container = 'frm_forms' . FrmFormsHelper::get_form_style_class( $values );
2169
2170 $errors = array();
2171 $form = $atts['form'];
2172 $message = $atts['message'];
2173
2174 include( FrmAppHelper::plugin_path() . '/classes/views/frm-entries/errors.php' );
2175 }
2176
2177 /**
2178 * Prepare the success message before it's shown
2179 *
2180 * @since 2.05
2181 */
2182 private static function prepare_submit_message( $form, $entry_id ) {
2183 $frm_settings = FrmAppHelper::get_settings( array( 'current_form' => $form->id ) );
2184
2185 if ( $entry_id && is_numeric( $entry_id ) ) {
2186 $message = isset( $form->options['success_msg'] ) ? $form->options['success_msg'] : $frm_settings->success_msg;
2187 $class = 'frm_message';
2188 } else {
2189 $message = $frm_settings->failed_msg;
2190 $class = FrmFormsHelper::form_error_class();
2191 }
2192
2193 $message = FrmFormsHelper::get_success_message( compact( 'message', 'form', 'entry_id', 'class' ) );
2194
2195 return apply_filters( 'frm_main_feedback', $message, $form, $entry_id );
2196 }
2197
2198 public static function front_head() {
2199 $version = FrmAppHelper::plugin_version();
2200 $suffix = FrmAppHelper::js_suffix();
2201
2202 if ( ! empty( $suffix ) && self::has_combo_js_file() ) {
2203 wp_register_script( 'formidable', FrmAppHelper::plugin_url() . '/js/frm.min.js', array( 'jquery' ), $version, true );
2204 } else {
2205 wp_register_script( 'formidable', FrmAppHelper::plugin_url() . "/js/formidable{$suffix}.js", array( 'jquery' ), $version, true );
2206 }
2207
2208 add_filter( 'script_loader_tag', 'FrmFormsController::defer_script_loading', 10, 2 );
2209
2210 if ( FrmAppHelper::is_admin() ) {
2211 // don't load this in back-end
2212 return;
2213 }
2214
2215 FrmAppHelper::localize_script( 'front' );
2216 FrmStylesController::enqueue_css( 'register' );
2217 }
2218
2219 /**
2220 * @since 3.0
2221 */
2222 public static function has_combo_js_file() {
2223 return is_readable( FrmAppHelper::plugin_path() . '/js/frm.min.js' );
2224 }
2225
2226 public static function maybe_load_css( $form, $this_load, $global_load ) {
2227 $load_css = FrmForm::is_form_loaded( $form, $this_load, $global_load );
2228
2229 if ( ! $load_css ) {
2230 return;
2231 }
2232
2233 global $frm_vars;
2234 self::footer_js( 'header' );
2235 $frm_vars['css_loaded'] = true;
2236
2237 self::load_late_css();
2238 }
2239
2240 /**
2241 * If css is loaded only on applicable pages, include it before the form loads
2242 * to prevent a flash of unstyled form.
2243 *
2244 * @since 4.01
2245 */
2246 private static function load_late_css() {
2247 $frm_settings = FrmAppHelper::get_settings();
2248 $late_css = $frm_settings->load_style === 'dynamic';
2249 if ( ! $late_css ) {
2250 return;
2251 }
2252
2253 global $wp_styles;
2254 if ( is_array( $wp_styles->queue ) && in_array( 'formidable', $wp_styles->queue ) ) {
2255 wp_print_styles( 'formidable' );
2256 }
2257 }
2258
2259 public static function defer_script_loading( $tag, $handle ) {
2260 if ( 'recaptcha-api' == $handle && ! strpos( $tag, 'defer' ) ) {
2261 $tag = str_replace( ' src', ' defer="defer" async="async" src', $tag );
2262 }
2263
2264 return $tag;
2265 }
2266
2267 public static function footer_js( $location = 'footer' ) {
2268 global $frm_vars;
2269
2270 FrmStylesController::enqueue_css();
2271
2272 if ( ! FrmAppHelper::is_admin() && $location != 'header' && ! empty( $frm_vars['forms_loaded'] ) ) {
2273 // load formidable js
2274 wp_enqueue_script( 'formidable' );
2275 }
2276 }
2277
2278 /**
2279 * @since 2.0.8
2280 */
2281 private static function maybe_minimize_form( $atts, &$content ) {
2282 // check if minimizing is turned on
2283 if ( self::is_minification_on( $atts ) ) {
2284 $content = str_replace( array( "\r\n", "\r", "\n", "\t", ' ' ), '', $content );
2285 }
2286 }
2287
2288 /**
2289 * @since 2.0.8
2290 * @return boolean
2291 */
2292 private static function is_minification_on( $atts ) {
2293 return isset( $atts['minimize'] ) && ! empty( $atts['minimize'] );
2294 }
2295
2296 /**
2297 * @since 5.0.16
2298 *
2299 * @return void
2300 */
2301 public static function landing_page_preview_option() {
2302 $dir = apply_filters( 'frm_landing_page_preview_option', false );
2303 if ( false === $dir || ! file_exists( $dir . 'landing-page-preview-option.php' ) ) {
2304 $dir = self::get_form_views_path();
2305 }
2306 include $dir . 'landing-page-preview-option.php';
2307 }
2308
2309 /**
2310 * @since 5.0.16
2311 *
2312 * @return string
2313 */
2314 private static function get_form_views_path() {
2315 return FrmAppHelper::plugin_path() . '/classes/views/frm-forms/';
2316 }
2317
2318 /**
2319 * Create a page with an embedded formidable Gutenberg block.
2320 *
2321 * @since 5.2
2322 *
2323 * @return never
2324 */
2325 public static function create_page_with_shortcode() {
2326 if ( ! current_user_can( 'publish_posts' ) ) {
2327 die( 0 );
2328 }
2329
2330 check_ajax_referer( 'frm_ajax', 'nonce' );
2331
2332 $form_id = FrmAppHelper::get_post_param( 'form_id', '', 'absint' );
2333 if ( ! $form_id ) {
2334 die( 0 );
2335 }
2336
2337 $postarr = array(
2338 'post_type' => 'page',
2339 'post_content' => '<!-- wp:formidable/simple-form {"formId":"' . $form_id . '"} --><div>[formidable id="' . $form_id . '"]</div><!-- /wp:formidable/simple-form -->',
2340 );
2341
2342 $name = FrmAppHelper::get_post_param( 'name', '', 'sanitize_text_field' );
2343 if ( $name ) {
2344 $postarr['post_title'] = $name;
2345 }
2346
2347 $success = wp_insert_post( $postarr );
2348 if ( ! is_numeric( $success ) || ! $success ) {
2349 die( 0 );
2350 }
2351
2352 wp_send_json(
2353 array(
2354 'redirect' => get_edit_post_link( $success, 'redirect' ),
2355 )
2356 );
2357 }
2358
2359 /**
2360 * Get page dropdown for AJAX request for embedding form in an existing page.
2361 *
2362 * @return never
2363 */
2364 public static function get_page_dropdown() {
2365 if ( ! current_user_can( 'publish_posts' ) ) {
2366 die( 0 );
2367 }
2368
2369 check_ajax_referer( 'frm_ajax', 'nonce' );
2370
2371 $html = FrmAppHelper::clip(
2372 function() {
2373 FrmAppHelper::maybe_autocomplete_pages_options(
2374 array(
2375 'field_name' => 'frm_page_dropdown',
2376 'page_id' => '',
2377 'placeholder' => __( 'Select a Page', 'formidable' ),
2378 )
2379 );
2380 }
2381 );
2382 $post_type_object = get_post_type_object( 'page' );
2383 wp_send_json(
2384 array(
2385 'html' => $html,
2386 'edit_page_url' => admin_url( sprintf( $post_type_object->_edit_link . '&action=edit', 0 ) ),
2387 )
2388 );
2389 }
2390
2391 /**
2392 * @deprecated 4.0
2393 */
2394 public static function new_form( $values = array() ) {
2395 FrmDeprecated::new_form( $values );
2396 }
2397
2398 /**
2399 * @deprecated 4.0
2400 */
2401 public static function create( $values = array() ) {
2402 _deprecated_function( __METHOD__, '4.0', 'FrmFormsController::update' );
2403 self::update( $values );
2404 }
2405
2406 /**
2407 * @deprecated 1.07.05
2408 * @codeCoverageIgnore
2409 */
2410 public static function add_default_templates( $path, $default = true, $template = true ) {
2411 FrmDeprecated::add_default_templates( $path, $default, $template );
2412 }
2413
2414 /**
2415 * @deprecated 3.0
2416 * @codeCoverageIgnore
2417 */
2418 public static function bulk_create_template( $ids ) {
2419 return FrmDeprecated::bulk_create_template( $ids );
2420 }
2421
2422 /**
2423 * @deprecated 2.03
2424 * @codeCoverageIgnore
2425 */
2426 public static function register_pro_scripts() {
2427 FrmDeprecated::register_pro_scripts();
2428 }
2429
2430 /**
2431 * @deprecated 3.0
2432 * @codeCoverageIgnore
2433 */
2434 public static function edit_key() {
2435 FrmDeprecated::edit_key();
2436 }
2437
2438 /**
2439 * @deprecated 3.0
2440 * @codeCoverageIgnore
2441 */
2442 public static function edit_description() {
2443 FrmDeprecated::edit_description();
2444 }
2445
2446 /**
2447 * @deprecated 4.08
2448 * @since 3.06
2449 */
2450 public static function add_new() {
2451 _deprecated_function( __FUNCTION__, '4.08' );
2452 }
2453 }
2454