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

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