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

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