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

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