PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.27
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.27
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 / FrmAppController.php

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

1,688 lines 45.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmAppController {
7
8 /**
9 * @return void
10 */
11 public static function menu() {
12 FrmAppHelper::maybe_add_permissions();
13
14 if ( ! current_user_can( 'frm_view_forms' ) ) {
15 return;
16 }
17
18 $menu_name = FrmAppHelper::get_menu_name();
19
20 if ( in_array( $menu_name, array( 'Formidable', 'Forms' ), true ) ) {
21 $menu_name .= wp_kses_post( FrmInboxController::get_notice_count() );
22 }
23
24 add_menu_page( 'Formidable', $menu_name, 'frm_view_forms', 'formidable', 'FrmFormsController::route', self::menu_icon(), self::get_menu_position() );
25 }
26
27 /**
28 * @return int
29 */
30 private static function get_menu_position() {
31 return (int) apply_filters( 'frm_menu_position', 29 );
32 }
33
34 /**
35 * @since 3.05
36 *
37 * @return string
38 */
39 private static function menu_icon() {
40 $icon = FrmAppHelper::svg_logo(
41 array(
42 'fill' => '#a0a5aa',
43 'orange' => '#a0a5aa',
44 )
45 );
46 $icon = 'data:image/svg+xml;base64,' . base64_encode( $icon );
47
48 return apply_filters( 'frm_icon', $icon );
49 }
50
51 /**
52 * @since 3.0
53 *
54 * @param string $classes
55 *
56 * @return string
57 */
58 public static function add_admin_class( $classes ) {
59 if ( self::is_white_page() ) {
60 $classes .= ' frm-white-body ';
61 $classes .= self::get_os();
62
63 $page = str_replace( 'formidable-', '', FrmAppHelper::simple_get( 'page', 'sanitize_title' ) );
64
65 if ( ! $page || $page === 'formidable' ) {
66 $action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
67
68 if ( in_array( $action, array( 'settings', 'edit', 'list' ), true ) ) {
69 $page .= $action;
70 } else {
71 $page = $action;
72 }
73 }
74
75 if ( $page ) {
76 $classes .= ' frm-admin-page-' . $page;
77 }
78 }
79
80 if ( self::is_grey_page() ) {
81 $classes .= ' frm-grey-body ';
82 }
83
84 if ( FrmAppHelper::is_full_screen() ) {
85 $full_screen_on = self::get_full_screen_setting();
86 $add_class = '';
87
88 if ( $full_screen_on ) {
89 $add_class = ' frm-full-screen is-fullscreen-mode';
90
91 // Load the CSS for .is-fullscreen-mode.
92 wp_enqueue_style( 'wp-edit-post' );
93 }
94
95 $classes .= apply_filters( 'frm_admin_full_screen_class', $add_class );
96 }
97
98 if ( ! FrmAppHelper::pro_is_installed() ) {
99 $classes .= ' frm-lite ';
100 }
101
102 if ( get_user_setting( 'unfold' ) && 'f' !== get_user_setting( 'mfold' ) ) {
103 $classes .= ' frm-unfold ';
104 }
105
106 return $classes;
107 }
108
109 /**
110 * Get the full screen mode setting from the block editor.
111 *
112 * @since 6.1
113 *
114 * @return bool
115 */
116 private static function get_full_screen_setting() {
117 global $wpdb;
118 $meta_key = $wpdb->get_blog_prefix() . 'persisted_preferences';
119 $prefs = get_user_meta( get_current_user_id(), $meta_key, true );
120
121 if ( $prefs && isset( $prefs['core/edit-post']['fullscreenMode'] ) ) {
122 return $prefs['core/edit-post']['fullscreenMode'];
123 }
124
125 return true;
126 }
127
128 /**
129 * @since 4.0
130 *
131 * @return string
132 */
133 private static function get_os() {
134 $agent = strtolower( FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' ) );
135 $os = '';
136
137 if ( str_contains( $agent, 'mac' ) ) {
138 $os = ' osx';
139 } elseif ( str_contains( $agent, 'linux' ) ) {
140 $os = ' linux';
141 } elseif ( str_contains( $agent, 'windows' ) ) {
142 $os = ' windows';
143 }
144
145 return $os;
146 }
147
148 /**
149 * @since 3.0
150 *
151 * @return bool
152 */
153 private static function is_white_page() {
154 $white_pages = array(
155 'formidable',
156 'formidable-entries',
157 'formidable-views',
158 'formidable-views-editor',
159 'formidable-addons',
160 'formidable-import',
161 'formidable-settings',
162 'formidable-styles',
163 'formidable-styles2',
164 'formidable-inbox',
165 FrmFormTemplatesController::PAGE_SLUG,
166 FrmOnboardingWizardController::PAGE_SLUG,
167 );
168
169 if ( self::is_white_payments_page() ) {
170 $white_pages[] = 'formidable-payments';
171 }
172
173 $is_white_page = self::is_page_in_list( $white_pages ) || self::is_grey_page() || FrmAppHelper::is_view_builder_page();
174
175 /**
176 * Allow another add on to style a page as a Formidable "white page", which adds a white background color.
177 *
178 * @since 5.3
179 *
180 * @param bool $is_white_page
181 */
182 return apply_filters( 'frm_is_white_page', $is_white_page );
183 }
184
185 /**
186 * Check if the payments page should be styled as a white page.
187 * Fallback to the Stripe, Authorize.Net, or PayPal add on for the "edit" action since
188 * Stripe Lite does not have an edit view. Also fallback for bulk deleting, since that
189 * isn't built into Lite. The pages we fall back to should not be styled as white pages.
190 *
191 * @since 6.27
192 *
193 * @return bool
194 */
195 private static function is_white_payments_page() {
196 $action = FrmAppHelper::simple_get( 'action', 'sanitize_title' );
197 $on_edit_page = in_array( $action, array( 'edit', 'new' ), true );
198 return ! $on_edit_page && 'bulk_delete' !== $action;
199 }
200
201 /**
202 * Add a grey bg instead of white.
203 *
204 * @since 6.8
205 *
206 * @return bool
207 */
208 private static function is_grey_page() {
209 $grey_pages = array(
210 'formidable-applications',
211 'formidable-dashboard',
212 'formidable-views',
213 );
214
215 $is_grey_page = self::is_page_in_list( $grey_pages );
216
217 /**
218 * Filter to change FF wrapper background to grey.
219 *
220 * @since 6.8
221 *
222 * @param bool $is_grey_page
223 *
224 * @return bool
225 */
226 return apply_filters( 'frm_is_grey_page', $is_grey_page );
227 }
228
229 /**
230 * @since 6.8
231 *
232 * @param array $pages A list of page names to check.
233 *
234 * @return bool
235 */
236 private static function is_page_in_list( $pages ) {
237 $get_page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
238 return in_array( $get_page, $pages, true );
239 }
240
241 /**
242 * @return void
243 */
244 public static function load_wp_admin_style() {
245 FrmAppHelper::load_font_style();
246 }
247
248 /**
249 * @param int|object $form
250 * @param bool $show_nav
251 * @param string $title
252 *
253 * @psalm-param 'hide'|'show' $title
254 *
255 * @return void
256 */
257 public static function get_form_nav( $form, $show_nav = false, $title = 'show' ) {
258 $show_nav = FrmAppHelper::get_param( 'show_nav', $show_nav, 'get', 'absint' );
259
260 if ( ! $show_nav || ! $form ) {
261 return;
262 }
263
264 FrmForm::maybe_get_form( $form );
265
266 if ( ! is_object( $form ) ) {
267 return;
268 }
269
270 $id = $form->id;
271 $current_page = self::get_current_page();
272 $nav_items = self::get_form_nav_items( $form );
273
274 include FrmAppHelper::plugin_path() . '/classes/views/shared/form-nav.php';
275 }
276
277 /**
278 * @return string
279 */
280 private static function get_current_page() {
281 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
282 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title', 'None' );
283
284 if ( FrmAppHelper::is_view_builder_page() ) {
285 return 'frm_display';
286 }
287
288 return isset( $_GET['page'] ) ? $page : $post_type;
289 }
290
291 /**
292 * @param object $form
293 *
294 * @return array
295 */
296 private static function get_form_nav_items( $form ) {
297 $id = $form->parent_form_id ? $form->parent_form_id : $form->id;
298
299 $nav_items = array(
300 array(
301 'link' => FrmForm::get_edit_link( $id ),
302 'label' => __( 'Build', 'formidable' ),
303 'current' => array( 'edit', 'new', 'duplicate' ),
304 'page' => 'formidable',
305 'permission' => 'frm_edit_forms',
306 ),
307 array(
308 'link' => FrmStylesHelper::get_list_url( $id ),
309 'label' => __( 'Style', 'formidable' ),
310 'current' => array(),
311 'page' => 'formidable-styles',
312 'permission' => 'frm_edit_forms',
313 ),
314 array(
315 'link' => admin_url( 'admin.php?page=formidable&frm_action=settings&id=' . absint( $id ) ),
316 'label' => __( 'Settings', 'formidable' ),
317 'current' => array( 'settings' ),
318 'page' => 'formidable',
319 'permission' => 'frm_edit_forms',
320 ),
321 array(
322 'link' => admin_url( 'admin.php?page=formidable-entries&frm_action=list&form=' . absint( $id ) ),
323 'label' => __( 'Entries', 'formidable' ),
324 'current' => array(),
325 'page' => 'formidable-entries',
326 'permission' => 'frm_view_entries',
327 ),
328 );
329
330 $views_installed = is_callable( 'FrmProAppHelper::views_is_installed' ) && FrmProAppHelper::views_is_installed();
331
332 if ( ! $views_installed ) {
333 $nav_items[] = array(
334 'link' => admin_url( 'admin.php?page=formidable-views&form=' . absint( $id ) ),
335 'label' => __( 'Views', 'formidable' ),
336 'current' => array(),
337 'page' => 'formidable-views',
338 'permission' => 'frm_view_entries',
339 'atts' => array(
340 'class' => 'frm_noallow',
341 ),
342 );
343 }
344
345 // Let people know reports and views exist.
346 if ( ! FrmAppHelper::pro_is_installed() ) {
347 $nav_items[] = array(
348 'link' => admin_url( 'admin.php?page=formidable&frm_action=lite-reports&form=' . absint( $id ) ),
349 'label' => __( 'Reports', 'formidable' ),
350 'current' => array( 'reports' ),
351 'page' => 'formidable',
352 'permission' => 'frm_view_entries',
353 'atts' => array(
354 'class' => 'frm_noallow',
355 ),
356 );
357 }
358
359 $nav_args = array(
360 'form_id' => $id,
361 'form' => $form,
362 );
363
364 return (array) apply_filters( 'frm_form_nav_list', $nav_items, $nav_args );
365 }
366
367 /**
368 * Adds a settings link to the plugins page
369 *
370 * @param array $links
371 *
372 * @return array
373 */
374 public static function settings_link( $links ) {
375 $settings = array();
376
377 if ( ! FrmAppHelper::pro_is_installed() ) {
378 if ( FrmAddonsController::is_license_expired() ) {
379 $label = __( 'Renew', 'formidable' );
380 } else {
381 $label = FrmSalesApi::get_best_sale_value( 'plugin_page_cta_text' );
382
383 if ( ! $label ) {
384 $label = __( 'Upgrade to Pro', 'formidable' );
385 }
386 }
387
388 $upgrade_link = FrmSalesApi::get_best_sale_value( 'plugin_page_cta_link' );
389
390 if ( $upgrade_link ) {
391 $upgrade_link = FrmAppHelper::maybe_add_missing_utm( $upgrade_link, array( 'medium' => 'plugin-row' ) );
392 } else {
393 $upgrade_link = FrmAppHelper::admin_upgrade_link( 'plugin-row' );
394 }
395
396 $settings[] = '<a href="' . esc_url( $upgrade_link ) . '" target="_blank" rel="noopener"><b style="color:#1da867;font-weight:700;">' . esc_html( $label ) . '</b></a>';
397 }//end if
398
399 $settings[] = '<a href="' . esc_url( admin_url( 'admin.php?page=formidable' ) ) . '">' . __( 'Build a Form', 'formidable' ) . '</a>';
400
401 return array_merge( $settings, $links );
402 }
403
404 /**
405 * @return void
406 */
407 public static function pro_get_started_headline() {
408 self::review_request();
409 FrmAppHelper::min_pro_version_notice( '6.20' );
410 }
411
412 /**
413 * Add admin notices as needed for reviews
414 *
415 * @since 3.04.03
416 *
417 * @return void
418 */
419 private static function review_request() {
420 $reviews = new FrmReviews();
421 $reviews->review_request();
422 }
423
424 /**
425 * Save the request to hide the review
426 *
427 * @since 3.04.03
428 *
429 * @return void
430 */
431 public static function dismiss_review() {
432 FrmAppHelper::permission_check( 'frm_change_settings' );
433 check_ajax_referer( 'frm_ajax', 'nonce' );
434
435 $reviews = new FrmReviews();
436 $reviews->dismiss_review();
437 }
438
439 /**
440 * @since 3.04.02
441 *
442 * @return void
443 */
444 public static function include_upgrade_overlay() {
445 self::enqueue_dialog_assets();
446 add_action( 'admin_footer', 'FrmAppController::upgrade_overlay_html' );
447 }
448
449 /**
450 * Enqueue scripts and styles required for modals.
451 *
452 * @since 5.3
453 *
454 * @return void
455 */
456 public static function enqueue_dialog_assets() {
457 wp_enqueue_script( 'jquery-ui-dialog' );
458 wp_enqueue_style( 'jquery-ui-dialog' );
459 }
460
461 /**
462 * @since 3.06.03
463 *
464 * @return void
465 */
466 public static function upgrade_overlay_html() {
467 $is_pro = FrmAppHelper::pro_is_installed();
468 $upgrade_link = array(
469 'medium' => 'builder',
470 'content' => 'upgrade',
471 );
472 $default_link = FrmAppHelper::admin_upgrade_link( $upgrade_link );
473 $plugin_path = FrmAppHelper::plugin_path();
474 $shared_path = $plugin_path . '/classes/views/shared/';
475
476 include $shared_path . 'upgrade_overlay.php';
477 include $shared_path . 'confirm-overlay.php';
478 }
479
480 /**
481 * Create a basic form with an email field.
482 *
483 * @param string $form_key
484 * @param string $title
485 * @param string $description
486 *
487 * @return void
488 */
489 public static function api_email_form( $form_key, $title = '', $description = '' ) {
490 $user = wp_get_current_user();
491 $args = array(
492 'api_url' => 'https://sandbox.formidableforms.com/api/wp-json/frm/v2/forms/' . $form_key . '?return=html&exclude_script=jquery&exclude_style=formidable-css',
493 'title' => $title,
494 'description' => $description,
495 );
496 require FrmAppHelper::plugin_path() . '/classes/views/form-templates/modals/leave-email-modal.php';
497 }
498
499 /**
500 * @return void
501 */
502 public static function include_info_overlay() {
503 self::enqueue_dialog_assets();
504 add_action( 'admin_footer', 'FrmAppController::info_overlay_html' );
505 }
506
507 /**
508 * @return void
509 */
510 public static function info_overlay_html() {
511 include FrmAppHelper::plugin_path() . '/classes/views/shared/info-overlay.php';
512 }
513
514 /**
515 * @since 3.04.02
516 *
517 * @return void
518 */
519 public static function remove_upsells() {
520 remove_action( 'frm_before_settings', 'FrmSettingsController::license_box' );
521 remove_action( 'frm_after_settings_tabs', 'FrmSettingsController::settings_cta' );
522 remove_action( 'frm_after_field_options', 'FrmFormsController::logic_tip' );
523 }
524
525 /**
526 * If there are CURL problems on this server, wp_remote_post won't work for installing
527 * Use a javascript fallback instead.
528 *
529 * @since 2.0.3
530 *
531 * @return void
532 */
533 public static function install_js_fallback() {
534 FrmAppHelper::load_admin_wide_js();
535 ?>
536 <div id="frm_install_message"></div>
537 <script>jQuery(document).ready( frm_install_now );</script>
538 <?php
539 }
540
541 /**
542 * Check if the database is outdated
543 *
544 * @since 2.0.1
545 *
546 * @return bool
547 */
548 public static function needs_update() {
549 $needs_upgrade = self::compare_for_update(
550 array(
551 'option' => 'frm_db_version',
552 'new_db_version' => FrmAppHelper::$db_version,
553 'new_plugin_version' => FrmAppHelper::plugin_version(),
554 )
555 );
556
557 if ( ! $needs_upgrade ) {
558 $needs_upgrade = apply_filters( 'frm_db_needs_upgrade', $needs_upgrade );
559 }
560
561 return $needs_upgrade;
562 }
563
564 /**
565 * Check both version number and DB number for changes
566 *
567 * @since 3.0.04
568 *
569 * @param array $atts
570 *
571 * @return bool
572 */
573 public static function compare_for_update( $atts ) {
574 $db_version = get_option( $atts['option'] );
575
576 if ( ! str_contains( $db_version, '-' ) ) {
577 return true;
578 }
579
580 $last_upgrade = explode( '-', $db_version );
581 $needs_db_upgrade = (int) $last_upgrade[1] < (int) $atts['new_db_version'];
582 $new_version = version_compare( $last_upgrade[0], $atts['new_plugin_version'], '<' );
583
584 return $needs_db_upgrade || $new_version;
585 }
586
587 /**
588 * Check for database update and trigger js loading
589 *
590 * @since 2.0.1
591 *
592 * @return void
593 */
594 public static function admin_init() {
595 if ( FrmAppHelper::get_param( 'delete_all' ) && FrmAppHelper::is_admin_page( 'formidable' ) && 'trash' === FrmAppHelper::get_param( 'form_type' ) ) {
596 FrmFormsController::delete_all();
597 }
598
599 if ( FrmAppHelper::is_admin_page( 'formidable' ) && 'duplicate' === FrmAppHelper::get_param( 'frm_action' ) ) {
600 FrmFormsController::duplicate();
601 }
602
603 if ( FrmAppHelper::is_admin_page( 'formidable' ) && FrmAppHelper::simple_get( 'frm_add_tables' ) ) {
604 self::add_missing_tables();
605 }
606
607 if ( FrmAppHelper::is_style_editor_page() && 'save' === FrmAppHelper::get_param( 'frm_action' ) ) {
608 // Hook in earlier than FrmStylesController::route so we can redirect before the headers have been sent.
609 FrmStylesController::save_style();
610 }
611
612 if ( 'formidable-pro-upgrade' === FrmAppHelper::get_param( 'page' ) && ! FrmAppHelper::pro_is_installed() && current_user_can( 'frm_view_forms' ) ) {
613 $redirect = FrmSalesApi::get_best_sale_value( 'menu_cta_link' );
614 $utm = array(
615 'campaign' => 'upgrade',
616 'content' => 'submenu-upgrade',
617 );
618
619 $redirect = $redirect ? FrmAppHelper::maybe_add_missing_utm( $redirect, $utm ) : FrmAppHelper::admin_upgrade_link( $utm );
620
621 wp_redirect( $redirect );
622 die();
623 }
624
625 // Register personal data hooks.
626 new FrmPersonalData();
627
628 if ( ! FrmAppHelper::doing_ajax() && self::needs_update() ) {
629 self::network_upgrade_site();
630 }
631
632 if ( ! FrmAppHelper::doing_ajax() ) {
633 // don't continue during ajax calls
634 self::admin_js();
635 }
636
637 self::trigger_page_load_hooks();
638
639 if ( FrmAppHelper::is_admin_page( 'formidable' ) ) {
640 // Redirect to the "Form Templates" page if the 'frm_action' parameter matches specific actions.
641 // This provides backward compatibility for old addons that use legacy modal templates.
642 $action = FrmAppHelper::get_param( 'frm_action' );
643 $trigger_name_modal = FrmAppHelper::get_param( 'triggerNewFormModal' );
644
645 if ( $trigger_name_modal || in_array( $action, array( 'add_new', 'list_templates' ), true ) ) {
646 $application_id = FrmAppHelper::simple_get( 'applicationId', 'absint' );
647 $url_param = $application_id ? '&applicationId=' . $application_id : '';
648
649 wp_safe_redirect( admin_url( 'admin.php?page=' . FrmFormTemplatesController::PAGE_SLUG . $url_param ) );
650 exit;
651 }
652
653 FrmInbox::maybe_disable_screen_options();
654 }
655 }
656
657 /**
658 * Get the current page and check for a possible function to trigger.
659 * If a class name matches the page name, and the class has a load_page() method, trigger it.
660 *
661 * @since 6.8
662 *
663 * @return void
664 */
665 private static function trigger_page_load_hooks() {
666 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
667
668 if ( ! str_starts_with( $page, 'formidable-' ) ) {
669 // Only trigger hooks on Formidable pages.
670 return;
671 }
672
673 $page = str_replace( array( 'formidable-', '-' ), array( '', ' ' ), $page );
674 $page = str_replace( ' ', '', ucwords( $page ) );
675 $class = 'Frm' . $page . 'Controller';
676
677 if ( class_exists( $class ) && method_exists( $class, 'load_page' ) ) {
678 call_user_func( array( $class, 'load_page' ) );
679 }
680 }
681
682 /**
683 * @return void
684 */
685 public static function admin_js() {
686 $plugin_url = FrmAppHelper::plugin_url();
687 $version = FrmAppHelper::plugin_version();
688
689 FrmAppHelper::load_admin_wide_js();
690
691 // Register component assets early to ensure they can be enqueued later in controllers.
692 wp_register_style( 'formidable-animations', $plugin_url . '/css/admin/animations.css', array(), $version );
693
694 if ( class_exists( 'FrmOverlayController' ) ) {
695 // This should always exist.
696 // But it may not have loaded properly when updating the plugin.
697 FrmOverlayController::register_assets();
698 }
699
700 wp_register_style( 'formidable_admin_global', $plugin_url . '/css/admin/frm_admin_global.css', array(), $version );
701 wp_enqueue_style( 'formidable_admin_global' );
702
703 wp_register_style( 'formidable-admin', $plugin_url . '/css/frm_admin.css', array(), $version );
704 wp_register_style( 'formidable-grids', $plugin_url . '/css/frm_grids.css', array(), $version );
705
706 wp_register_script( 'formidable_dom', $plugin_url . '/js/admin/dom.js', array( 'jquery', 'jquery-ui-dialog', 'wp-i18n' ), $version, true );
707 wp_register_script( 'formidable_embed', $plugin_url . '/js/admin/embed.js', array( 'formidable_dom', 'jquery-ui-autocomplete' ), $version, true );
708 self::register_popper2();
709 wp_register_script( 'bootstrap_tooltip', $plugin_url . '/js/bootstrap.min.js', array( 'jquery', 'popper' ), '5.0.2', true );
710
711 $settings_js_vars = array(
712 'currencies' => FrmCurrencyHelper::get_currencies(),
713 );
714 wp_register_script( 'formidable_settings', $plugin_url . '/js/admin/settings.js', array(), $version, true );
715 wp_localize_script( 'formidable_settings', 'frmSettings', $settings_js_vars );
716
717 wp_register_script( 'formidable-web-components', $plugin_url . '/js/formidable-web-components.js', array( 'formidable_admin' ), $version, true );
718
719 if ( self::should_show_floating_links() ) {
720 self::enqueue_floating_links( $plugin_url, $version );
721 }
722
723 wp_register_script( 'formidable_admin', $plugin_url . '/js/formidable_admin.js', self::get_admin_js_dependencies(), $version, true );
724
725 if ( FrmAppHelper::on_form_listing_page() ) {
726 // For the existing page dropdown in the Form embed modal.
727 wp_enqueue_script( 'jquery-ui-autocomplete' );
728 }
729
730 wp_register_script( 'bootstrap-multiselect', $plugin_url . '/js/bootstrap-multiselect.js', array( 'jquery', 'bootstrap_tooltip', 'popper' ), '2.0', true );
731
732 if ( ! class_exists( 'FrmTransHooksController', false ) ) {
733 /**
734 * Gateway fields are included for add-on compatibility but we do not want it to be visible.
735 * They do however need to be visible when the payments submodule is active.
736 */
737 wp_add_inline_style(
738 'formidable-admin',
739 '#frm_builder_page li[data-ftype="gateway"] { display: none; }'
740 );
741 }
742
743 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
744 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
745
746 global $pagenow;
747
748 if ( str_starts_with( $page, 'formidable' ) || ( $pagenow === 'edit.php' && $post_type === 'frm_display' ) ) {
749 self::enqueue_global_settings_scripts( $page );
750
751 wp_enqueue_script( 'admin-widgets' );
752 wp_enqueue_style( 'widgets' );
753 self::maybe_deregister_popper1();
754 wp_enqueue_script( 'formidable_admin' );
755 wp_set_script_translations( 'formidable_admin', 'formidable' );
756 wp_enqueue_script( 'formidable_embed' );
757 wp_set_script_translations( 'formidable_embed', 'formidable' );
758 FrmAppHelper::localize_script( 'admin' );
759
760 wp_enqueue_style( 'formidable-animations' );
761 wp_enqueue_style( 'formidable-admin' );
762
763 if ( 'formidable-styles' !== $page && 'formidable-styles2' !== $page ) {
764 wp_enqueue_style( 'formidable-grids' );
765 self::maybe_enqueue_dropzone_css( $page );
766 } else {
767 wp_enqueue_style( 'formidable-grids' );
768 }
769
770 if ( 'formidable-entries' === $page ) {
771 // Load front end js for entries.
772 wp_enqueue_script( 'formidable' );
773
774 // Registers and enqueues the entries page scripts.
775 wp_register_script( 'formidable_entries', $plugin_url . '/js/admin/entries.js', array( 'formidable_admin', 'wp-dom-ready' ), $version, true );
776 wp_enqueue_script( 'formidable_entries' );
777 }
778
779 do_action( 'frm_enqueue_builder_scripts' );
780 self::include_upgrade_overlay();
781 self::include_info_overlay();
782 } elseif ( FrmAppHelper::is_view_builder_page() ) {
783 if ( isset( $_REQUEST['post_type'] ) ) {
784 $post_type = sanitize_title( wp_unslash( $_REQUEST['post_type'] ) );
785 } elseif ( isset( $_REQUEST['post'] ) && absint( $_REQUEST['post'] ) ) {
786 $post = get_post( absint( wp_unslash( $_REQUEST['post'] ) ) );
787
788 if ( ! $post ) {
789 return;
790 }
791
792 $post_type = $post->post_type;
793 } else {
794 return;
795 }
796
797 if ( $post_type === 'frm_display' ) {
798 self::enqueue_legacy_views_assets();
799 }
800 }//end if
801
802 if ( 'formidable-addons' === $page ) {
803 wp_register_script( 'formidable_addons', $plugin_url . '/js/admin/addons.js', array( 'formidable_admin', 'wp-dom-ready' ), $version, true );
804 wp_enqueue_script( 'formidable_addons' );
805 }
806
807 self::enqueue_builder_assets( $plugin_url, $version );
808 }
809
810 /**
811 * @since 6.27
812 *
813 * @return array
814 */
815 private static function get_admin_js_dependencies() {
816 $dependencies = array(
817 'formidable_admin_global',
818 'jquery',
819 'jquery-ui-core',
820 'jquery-ui-draggable',
821 'jquery-ui-sortable',
822 'bootstrap_tooltip',
823 'bootstrap-multiselect',
824 'wp-i18n',
825 // Required in WP versions older than 5.7
826 'wp-hooks',
827 'formidable_dom',
828 'formidable_embed',
829 );
830
831 if ( FrmAppHelper::is_style_editor_page( 'edit' ) ) {
832 // We only need to load the color picker when editing styles.
833 $dependencies[] = 'wp-color-picker';
834 }
835
836 return $dependencies;
837 }
838
839 /**
840 * Enqueue the Form Builder assets.
841 *
842 * @since 6.24
843 *
844 * @param string $plugin_url The plugin URL.
845 * @param string $version The plugin version.
846 *
847 * @return void
848 */
849 private static function enqueue_builder_assets( $plugin_url, $version ) {
850 wp_register_style( 'formidable-settings-components', $plugin_url . '/css/admin/frm-settings-components.css', array( 'formidable-admin', 'formidable-grids' ), $version );
851 wp_register_script( 'formidable-settings-components', $plugin_url . '/js/formidable-settings-components.js', array( 'formidable_admin' ), $version, true );
852
853 if ( ! FrmAppHelper::is_form_builder_page() ) {
854 return;
855 }
856
857 wp_enqueue_style( 'formidable-settings-components' );
858 wp_enqueue_script( 'formidable-settings-components' );
859 }
860
861 /**
862 * Enqueues global settings scripts.
863 *
864 * @param string $page The `page` param in URL.
865 *
866 * @return void
867 */
868 private static function enqueue_global_settings_scripts( $page ) {
869 if ( 'formidable-settings' === $page ) {
870 wp_enqueue_style( 'wp-color-picker' );
871 wp_enqueue_script( 'formidable_settings' );
872 }
873 }
874
875 /**
876 * Avoid loading dropzone CSS on the form list page. It isn't required there.
877 *
878 * @since 6.11
879 *
880 * @param string $page
881 *
882 * @return void
883 */
884 private static function maybe_enqueue_dropzone_css( $page ) {
885 if ( ! FrmAppHelper::pro_is_installed() ) {
886 return;
887 }
888
889 $should_avoid_loading_dropzone = 'formidable' === $page && ! FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
890
891 if ( ! $should_avoid_loading_dropzone ) {
892 wp_enqueue_style( 'formidable-dropzone' );
893 }
894 }
895
896 /**
897 * The floating links are not shown on every page.
898 * They are also not shown if white labeling is being used.
899 *
900 * @since 6.8.4
901 *
902 * @return bool
903 */
904 private static function should_show_floating_links() {
905 if ( ! FrmAppHelper::is_formidable_branding() ) {
906 return false;
907 }
908
909 $should_show = FrmAppHelper::is_formidable_admin() &&
910 ! FrmAppHelper::is_style_editor_page() &&
911 ! FrmAppHelper::is_admin_page( 'formidable-views-editor' ) &&
912 ! FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
913
914 /**
915 * Filters whether the floating links should be displayed.
916 *
917 * @since 6.25.1
918 *
919 * @param bool $should_show Whether the floating links should be shown.
920 */
921 return apply_filters( 'frm_should_show_floating_links', $should_show );
922 }
923
924 /**
925 * @since 6.3.2
926 *
927 * @return void
928 */
929 public static function admin_enqueue_scripts() {
930 self::load_wp_admin_style();
931 self::maybe_force_formidable_block_on_gutenberg_page();
932
933 if ( FrmAppHelper::is_admin_page( 'formidable-settings' ) ) {
934 wp_enqueue_style( FrmDashboardController::PAGE_SLUG, FrmAppHelper::plugin_url() . '/css/admin/dashboard.css', array(), FrmAppHelper::plugin_version() );
935 }
936
937 FrmUsageController::load_scripts();
938 }
939
940 /**
941 * Enqueue required assets for the Legacy Views editor (Views v4.x).
942 *
943 * @since 6.1.2
944 *
945 * @return void
946 */
947 private static function enqueue_legacy_views_assets() {
948 wp_enqueue_style( 'formidable-grids' );
949 wp_enqueue_script( 'jquery-ui-draggable' );
950 self::maybe_deregister_popper1();
951 wp_enqueue_script( 'formidable_admin' );
952 wp_add_inline_style(
953 'formidable-admin',
954 '
955 .frm-white-body.post-type-frm_display .columns-2 {
956 display: block;
957 overflow: visible;
958 }
959
960 .frm-white-body.post-type-frm_display .columns-2 > div {
961 overflow-y: hidden;
962 }
963
964 .frm-white-body.post-type-frm_display #titlediv #title-prompt-text {
965 padding: 3px 0 0 10px;
966 }
967
968 .post-type-frm_display #field-search-input,
969 .post-type-frm_display #advanced-search-input {
970 flex: 1;
971 }
972 '
973 );
974 wp_enqueue_style( 'formidable-admin' );
975 wp_enqueue_script( 'formidable_legacy_views', FrmAppHelper::plugin_url() . '/js/admin/legacy-views.js', array( 'jquery', 'formidable_admin' ), FrmAppHelper::plugin_version() ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
976 FrmAppHelper::localize_script( 'admin' );
977 self::include_info_overlay();
978 }
979
980 /**
981 * Unregister Popper if the registered version is outdated.
982 *
983 * @since 6.26
984 *
985 * @return void
986 */
987 private static function maybe_deregister_popper1() {
988 global $wp_scripts;
989
990 if ( ! array_key_exists( 'popper', $wp_scripts->registered ) ) {
991 return;
992 }
993
994 $popper = $wp_scripts->registered['popper'];
995
996 if ( version_compare( $popper->ver, '2.0', '<' ) ) {
997 wp_deregister_script( 'popper' );
998 self::register_popper2();
999 }
1000 }
1001
1002 /**
1003 * Register Popper required for Bootstrap 5.
1004 *
1005 * @since 6.26
1006 *
1007 * @return void
1008 */
1009 private static function register_popper2() {
1010 if ( ! self::should_register_popper() ) {
1011 return;
1012 }
1013 wp_register_script( 'popper', FrmAppHelper::plugin_url() . '/js/popper.min.js', array(), '2.11.8', true );
1014 }
1015
1016 /**
1017 * Only register popper on Formidable pages.
1018 * This helps to avoid popper conflicts on other plugin pages, including the WP Bakery page editor.
1019 *
1020 * @since 6.11.1
1021 *
1022 * @return bool
1023 */
1024 private static function should_register_popper() {
1025 global $pagenow;
1026
1027 $post_id = FrmAppHelper::simple_get( 'post', 'absint' );
1028
1029 if ( 'post.php' === $pagenow && $post_id && 'frm_display' === get_post_type( $post_id ) ) {
1030 return true;
1031 }
1032
1033 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
1034 $is_views_post_type = 'frm_display' === $post_type;
1035
1036 if ( in_array( $pagenow, array( 'post-new.php', 'edit.php' ), true ) && $is_views_post_type ) {
1037 return true;
1038 }
1039
1040 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
1041
1042 if ( str_starts_with( $page, 'formidable' ) ) {
1043 return true;
1044 }
1045
1046 return in_array( $pagenow, array( 'term.php', 'edit-tags.php' ), true ) && FrmAppHelper::simple_get( 'taxonomy' ) === 'frm_application';
1047 }
1048
1049 /**
1050 * Automatically insert a Formidable block when loading Gutenberg when $_GET['frmForm' is set.
1051 *
1052 * @since 5.2
1053 *
1054 * @return void
1055 */
1056 private static function maybe_force_formidable_block_on_gutenberg_page() {
1057 global $pagenow;
1058
1059 if ( 'post.php' !== $pagenow ) {
1060 return;
1061 }
1062
1063 $form_id = FrmAppHelper::simple_get( 'frmForm', 'absint' );
1064
1065 if ( ! $form_id ) {
1066 return;
1067 }
1068
1069 self::add_js_to_inject_gutenberg_block( 'formidable/simple-form', 'formId', $form_id );
1070 }
1071
1072 /**
1073 * @since 5.3
1074 *
1075 * @param string $block_name
1076 * @param string $object_key
1077 * @param array|string $object_id
1078 *
1079 * @return void
1080 */
1081 public static function add_js_to_inject_gutenberg_block( $block_name, $object_key, $object_id ) {
1082 require FrmAppHelper::plugin_path() . '/classes/views/shared/edit-page-js.php';
1083 }
1084
1085 /**
1086 * @return void
1087 */
1088 public static function load_lang() {
1089 load_plugin_textdomain( 'formidable', false, FrmAppHelper::plugin_folder() . '/languages/' );
1090 }
1091
1092 /**
1093 * Check if the styles are updated when a form is loaded on the front-end
1094 *
1095 * @since 3.0.1
1096 *
1097 * @return void
1098 */
1099 public static function maybe_update_styles() {
1100 if ( self::needs_update() ) {
1101 self::network_upgrade_site();
1102 }
1103 }
1104
1105 /**
1106 * @since 3.0
1107 *
1108 * @return void
1109 */
1110 public static function create_rest_routes() {
1111 $args = array(
1112 'methods' => 'GET',
1113 'callback' => 'FrmAppController::api_install',
1114 'permission_callback' => self::class . '::can_update_db',
1115 );
1116
1117 register_rest_route( 'frm-admin/v1', '/install', $args );
1118
1119 $args = array(
1120 'methods' => 'GET',
1121 'callback' => 'FrmAddonsController::install_addon_api',
1122 'permission_callback' => 'FrmAddonsController::can_install_addon_api',
1123 );
1124
1125 register_rest_route( 'frm-admin/v1', '/install-addon', $args );
1126 }
1127
1128 /**
1129 * Make sure the install is only being run when we tell it to.
1130 * We don't want to run manually by people calling the API.
1131 *
1132 * @since 4.06.02
1133 *
1134 * @return bool
1135 */
1136 public static function can_update_db() {
1137 return get_transient( 'frm_updating_api' );
1138 }
1139
1140 /**
1141 * Run silent upgrade on each site in the network during a network upgrade.
1142 * Update database settings for all sites in a network during network upgrade process.
1143 *
1144 * @since 2.0.1
1145 *
1146 * @param int $blog_id Blog ID.
1147 *
1148 * @return void
1149 */
1150 public static function network_upgrade_site( $blog_id = 0 ) {
1151 // Flag to check if install is happening as intended.
1152 set_transient( 'frm_updating_api', true, MINUTE_IN_SECONDS );
1153 $request = new WP_REST_Request( 'GET', '/frm-admin/v1/install' );
1154
1155 self::maybe_add_wp_site_health();
1156
1157 if ( $blog_id ) {
1158 switch_to_blog( $blog_id );
1159 $response = rest_do_request( $request );
1160 restore_current_blog();
1161 } else {
1162 $response = rest_do_request( $request );
1163 }
1164
1165 if ( $response->is_error() ) {
1166 // if the remove post fails, use javascript instead
1167 add_action( 'admin_notices', 'FrmAppController::install_js_fallback' );
1168 }
1169 }
1170
1171 /**
1172 * Make sure WP_Site_Health has been included because it is required when calling rest_do_request.
1173 * Check first that the file exists because WP_Site_Health was only introduced in WordPress 5.2.
1174 *
1175 * @return void
1176 */
1177 private static function maybe_add_wp_site_health() {
1178 if ( ! class_exists( 'WP_Site_Health' ) ) {
1179 $wp_site_health_path = ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
1180
1181 if ( file_exists( $wp_site_health_path ) ) {
1182 require_once $wp_site_health_path;
1183 }
1184 }
1185 }
1186
1187 /**
1188 * @since 3.0
1189 *
1190 * @return true
1191 */
1192 public static function api_install() {
1193 delete_transient( 'frm_updating_api' );
1194
1195 if ( self::needs_update() ) {
1196 $running = get_option( 'frm_install_running' );
1197
1198 if ( false === $running || $running < strtotime( '-5 minutes' ) ) {
1199 update_option( 'frm_install_running', time(), 'no' );
1200 self::install();
1201 delete_option( 'frm_install_running' );
1202 }
1203 }
1204
1205 return true;
1206 }
1207
1208 /**
1209 * Silent database upgrade (no redirect).
1210 * Called via ajax request during network upgrade process.
1211 *
1212 * @since 2.0.1
1213 *
1214 * @return void
1215 */
1216 public static function ajax_install() {
1217 FrmAppHelper::permission_check( 'frm_change_settings' );
1218 check_ajax_referer( 'frm_ajax', 'nonce' );
1219 self::api_install();
1220 wp_die();
1221 }
1222
1223 /**
1224 * @return void
1225 */
1226 public static function install() {
1227 $frmdb = new FrmMigrate();
1228 $frmdb->upgrade();
1229 }
1230
1231 /**
1232 * @return void
1233 */
1234 public static function uninstall() {
1235 FrmAppHelper::permission_check( 'administrator' );
1236 check_ajax_referer( 'frm_ajax', 'nonce' );
1237
1238 $frmdb = new FrmMigrate();
1239 $frmdb->uninstall();
1240
1241 // Disable the plugin and redirect after uninstall so the tables don't get added right back.
1242 $plugins = array( FrmAppHelper::plugin_folder() . '/formidable.php', 'formidable-pro/formidable-pro.php' );
1243 deactivate_plugins( $plugins, false, false );
1244 echo esc_url_raw( admin_url( 'plugins.php?deactivate=true' ) );
1245
1246 wp_die();
1247 }
1248
1249 /**
1250 * @param array $tables
1251 *
1252 * @return array
1253 */
1254 public static function drop_tables( $tables ) {
1255 global $wpdb;
1256 $tables[] = $wpdb->prefix . 'frm_fields';
1257 $tables[] = $wpdb->prefix . 'frm_forms';
1258 $tables[] = $wpdb->prefix . 'frm_items';
1259 $tables[] = $wpdb->prefix . 'frm_item_metas';
1260
1261 return $tables;
1262 }
1263
1264 /**
1265 * @return void
1266 */
1267 public static function deauthorize() {
1268 FrmAppHelper::permission_check( 'frm_change_settings' );
1269 check_ajax_referer( 'frm_ajax', 'nonce' );
1270
1271 delete_option( 'frmpro-credentials' );
1272 delete_option( 'frmpro-authorized' );
1273 delete_site_option( 'frmpro-credentials' );
1274 delete_site_option( 'frmpro-authorized' );
1275 wp_die();
1276 }
1277
1278 /**
1279 * This is triggered when Formidable is activated.
1280 *
1281 * @return void
1282 */
1283 public static function handle_activation() {
1284 self::maybe_activate_payment_cron();
1285 }
1286
1287 /**
1288 * The payment cron is unscheduled when Formidable is deactivated.
1289 * We need to add it back again on activation if Stripe is configured.
1290 *
1291 * @since 6.5
1292 *
1293 * @return void
1294 */
1295 private static function maybe_activate_payment_cron() {
1296 if ( ! FrmStrpLiteConnectHelper::stripe_connect_is_setup() ) {
1297 return;
1298 }
1299
1300 FrmTransLiteAppController::maybe_schedule_cron();
1301 }
1302
1303 /**
1304 * @param string $text
1305 *
1306 * @return string
1307 */
1308 public static function set_footer_text( $text ) {
1309 if ( FrmAppHelper::is_formidable_admin() ) {
1310 $text = '';
1311 }
1312
1313 return $text;
1314 }
1315
1316 /**
1317 * Add admin footer links.
1318 *
1319 * @since 6.4.1
1320 *
1321 * @return void
1322 */
1323 public static function add_admin_footer_links() {
1324 FrmFormsController::include_device_too_small_message();
1325
1326 if ( self::should_show_footer_links() ) {
1327 include FrmAppHelper::plugin_path() . '/classes/views/shared/admin-footer-links.php';
1328 }
1329 }
1330
1331 /**
1332 * Check if the footer links should be shown.
1333 *
1334 * @since 6.7
1335 *
1336 * @return bool
1337 */
1338 private static function should_show_footer_links() {
1339 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
1340 $is_formidable_page = FrmAppHelper::is_formidable_admin() || 'frm_logs' === $post_type;
1341 $show_footer_links = $is_formidable_page;
1342
1343 if ( FrmAppHelper::is_full_screen() || ! FrmAppHelper::is_formidable_branding() ) {
1344 $show_footer_links = false;
1345 }
1346
1347 /**
1348 * Filter whether to show the Formidable footer links.
1349 *
1350 * @since 6.7
1351 *
1352 * @param bool $show_footer_links
1353 *
1354 * @return bool
1355 */
1356 return apply_filters( 'frm_show_footer_links', $show_footer_links );
1357 }
1358
1359 /**
1360 * Show an error modal and terminate the script execution.
1361 *
1362 * @since 6.7
1363 *
1364 * @param array $error_args Arguments that control the behavior of the error modal.
1365 *
1366 * @return void
1367 */
1368 public static function show_error_modal( $error_args ) {
1369 add_filter( 'frm_show_footer_links', '__return_false' );
1370
1371 $defaults = array(
1372 'title' => '',
1373 'body' => '',
1374 'cancel_url' => '',
1375 'cancel_classes' => '',
1376 'continue_url' => '',
1377 'continue_classes' => '',
1378 'icon' => 'frm_lock_simple',
1379 );
1380
1381 $error_args = wp_parse_args( $error_args, $defaults );
1382
1383 if ( ! isset( $error_args['cancel_text'] ) && ! empty( $error_args['cancel_url'] ) ) {
1384 $error_args['cancel_text'] = __( 'Cancel', 'formidable' );
1385 }
1386
1387 if ( ! isset( $error_args['continue_text'] ) && ! empty( $error_args['continue_url'] ) ) {
1388 $error_args['continue_text'] = __( 'Continue', 'formidable' );
1389 }
1390
1391 include FrmAppHelper::plugin_path() . '/classes/views/frm-forms/error-modal.php';
1392 }
1393
1394 /**
1395 * Handles Floating Links' scripts and styles enqueueing.
1396 *
1397 * @since 6.4
1398 *
1399 * @param string $plugin_url URL of the plugin.
1400 * @param string $version Current version of the plugin.
1401 *
1402 * @return void
1403 */
1404 private static function enqueue_floating_links( $plugin_url, $version ) {
1405 if ( ! $plugin_url || ! $version ) {
1406 // If any required parameters are missing, exit early.
1407 return;
1408 }
1409
1410 // Enqueue the Floating Links styles.
1411 wp_enqueue_style( 's11-floating-links', $plugin_url . '/css/packages/s11-floating-links.css', array(), $version );
1412
1413 // Enqueue the Floating Links script.
1414 wp_enqueue_script( 's11-floating-links', $plugin_url . '/js/packages/floating-links/s11-floating-links.js', array( 'formidable_admin' ), $version, true );
1415
1416 // Enqueue the config script.
1417 wp_enqueue_script( 's11-floating-links-config', $plugin_url . '/js/packages/floating-links/config.js', array( 'wp-i18n' ), $version, true );
1418
1419 if ( function_exists( 'wp_set_script_translations' ) ) {
1420 wp_set_script_translations( 's11-floating-links-config', 's11-' );
1421 }
1422
1423 $upgrade_utm = array(
1424 'campaign' => 'floating-links',
1425 'content' => 'floating-links-upgrade',
1426 );
1427 $docs_utm = array(
1428 'campaign' => 'floating-links',
1429 'content' => 'floating-links-docs',
1430 );
1431 $floating_links_data = array(
1432 'proIsInstalled' => FrmAppHelper::pro_is_installed(),
1433 'upgradeUrl' => FrmAppHelper::admin_upgrade_link( $upgrade_utm ),
1434 'documentationUrl' => FrmAppHelper::admin_upgrade_link( $docs_utm, 'knowledgebase/' ),
1435 );
1436 wp_localize_script( 's11-floating-links-config', 's11FloatingLinksData', $floating_links_data );
1437
1438 /**
1439 * Prompt Pro to load additional floating links scripts.
1440 * This is used to include images in the Inbox SlideIn when Pro is active.
1441 *
1442 * @since 6.8.4
1443 */
1444 do_action( 'frm_enqueue_floating_links' );
1445 }
1446
1447 /**
1448 * Check if we are in our admin pages.
1449 *
1450 * @return bool
1451 */
1452 private static function in_our_pages() {
1453 global $current_screen, $pagenow;
1454
1455 if ( FrmAppHelper::is_formidable_admin() ) {
1456 return true;
1457 }
1458
1459 if ( ! empty( $current_screen->post_type ) && 'frm_logs' === $current_screen->post_type ) {
1460 return true;
1461 }
1462
1463 return in_array( $pagenow, array( 'term.php', 'edit-tags.php' ), true ) && 'frm_application' === FrmAppHelper::simple_get( 'taxonomy' );
1464 }
1465
1466 /**
1467 * Handles actions related to the current screen.
1468 *
1469 * @since 6.19
1470 *
1471 * @return void
1472 */
1473 public static function handle_current_screen() {
1474 if ( ! self::in_our_pages() ) {
1475 return;
1476 }
1477
1478 self::filter_admin_notices();
1479 self::remember_custom_sort();
1480 }
1481
1482 /**
1483 * Hide all third-parties admin notices only in our admin pages.
1484 *
1485 * @return void
1486 */
1487 public static function filter_admin_notices() {
1488 $actions = array(
1489 'admin_notices',
1490 'network_admin_notices',
1491 'user_admin_notices',
1492 'all_admin_notices',
1493 );
1494
1495 global $wp_filter;
1496
1497 foreach ( $actions as $action ) {
1498 if ( empty( $wp_filter[ $action ]->callbacks ) ) {
1499 continue;
1500 }
1501
1502 foreach ( $wp_filter[ $action ]->callbacks as $priority => $callbacks ) {
1503 foreach ( $callbacks as $callback_name => $callback ) {
1504 if ( self::is_our_callback_string( $callback_name ) || self::is_our_callback_array( $callback ) ) {
1505 continue;
1506 }
1507 unset( $wp_filter[ $action ]->callbacks[ $priority ][ $callback_name ] );
1508 }
1509 }
1510 }
1511 }
1512
1513 /**
1514 * Remembers and applies user-specific sorting preferences.
1515 *
1516 * @return void
1517 */
1518 private static function remember_custom_sort() {
1519 $meta_key = self::get_sort_pref_user_meta_key();
1520
1521 if ( false === $meta_key ) {
1522 return;
1523 }
1524
1525 $is_form_list = FrmAppHelper::is_admin_list_page();
1526 $is_entry_list = FrmAppHelper::is_admin_list_page( 'formidable-entries' );
1527
1528 if ( ! $is_form_list && ! $is_entry_list ) {
1529 return;
1530 }
1531
1532 $orderby = FrmAppHelper::get_param( 'orderby' );
1533
1534 if ( ! $orderby ) {
1535 return;
1536 }
1537
1538 $user_id = get_current_user_id();
1539 $order = FrmAppHelper::get_param( 'order' );
1540 $new_sort = array(
1541 'orderby' => $orderby,
1542 'order' => $order,
1543 );
1544 $previous_meta = get_user_meta( $user_id, $meta_key, true );
1545 $current_sort = $previous_meta;
1546 $form_id = $is_entry_list ? FrmAppHelper::simple_get( 'form', 'absint' ) : 0;
1547
1548 if ( is_array( $current_sort ) && $form_id && is_int( $form_id ) && isset( $current_sort[ $form_id ] ) ) {
1549 $current_sort = $current_sort[ $form_id ];
1550 }
1551
1552 if ( $new_sort !== $current_sort ) {
1553 $new_meta = $new_sort;
1554
1555 if ( $is_entry_list && $form_id && is_int( $form_id ) ) {
1556 // Index meta by form ID.
1557 $temp_meta = is_array( $previous_meta ) ? $previous_meta : array();
1558 $temp_meta[ $form_id ] = $new_meta;
1559 $new_meta = $temp_meta;
1560 unset( $temp_meta );
1561 }
1562
1563 update_user_meta( $user_id, $meta_key, $new_meta );
1564 }
1565 }
1566
1567 /**
1568 * Retrieve and apply any saved sorting preferences for the current screen.
1569 *
1570 * @since 6.19
1571 *
1572 * @param string &$orderby Reference to the current 'orderby' parameter.
1573 * @param string &$order Reference to the current 'order' parameter.
1574 *
1575 * @return void
1576 */
1577 public static function apply_saved_sort_preference( &$orderby, &$order ) {
1578 $meta_key = self::get_sort_pref_user_meta_key();
1579
1580 if ( false === $meta_key ) {
1581 return;
1582 }
1583
1584 $user_id = get_current_user_id();
1585 $preferred_list_sort = get_user_meta( $user_id, $meta_key, true );
1586 $form_id = FrmAppHelper::simple_get( 'form', 'absint' );
1587
1588 if ( is_array( $preferred_list_sort ) && $form_id && is_int( $form_id ) && isset( $preferred_list_sort[ $form_id ] ) ) {
1589 $preferred_list_sort = $preferred_list_sort[ $form_id ];
1590 }
1591
1592 if ( is_array( $preferred_list_sort ) && ! empty( $preferred_list_sort['orderby'] ) ) {
1593 $orderby = $preferred_list_sort['orderby'];
1594
1595 if ( ! empty( $preferred_list_sort['order'] ) ) {
1596 $order = $preferred_list_sort['order'];
1597 }
1598 }
1599 }
1600
1601 /**
1602 * Get a simple user meta key that only includes the screen ID.
1603 *
1604 * @since 6.25.1
1605 *
1606 * @return false|string
1607 */
1608 private static function get_sort_pref_user_meta_key() {
1609 if ( ! function_exists( 'get_current_screen' ) ) {
1610 return false;
1611 }
1612
1613 $screen = get_current_screen();
1614 return $screen ? 'frm_preferred_list_sort_' . $screen->id : false;
1615 }
1616
1617 /**
1618 * Validate that the callback name is ours not from third-party.
1619 *
1620 * @param string $callback_name WordPress callback name.
1621 *
1622 * @return bool
1623 */
1624 private static function is_our_callback_string( $callback_name ) {
1625 return 0 === stripos( $callback_name, 'frm' );
1626 }
1627
1628 /**
1629 * Validate that the callback array is ours not from third-party.
1630 *
1631 * @param array $callback WordPress callback array.
1632 *
1633 * @return bool
1634 */
1635 private static function is_our_callback_array( $callback ) {
1636 return ! empty( $callback['function'] ) &&
1637 is_array( $callback['function'] ) &&
1638 ! empty( $callback['function'][0] ) &&
1639 self::is_our_callback_string( is_object( $callback['function'][0] ) ? get_class( $callback['function'][0] ) : $callback['function'][0] );
1640 }
1641
1642 /**
1643 * In some cases, the DB tables may fail to install.
1644 * This function tries to add them again when the user clicks the link to try again
1645 * from the given inbox notice.
1646 *
1647 * @since 6.19
1648 */
1649 private static function add_missing_tables() {
1650 FrmAppHelper::permission_check( 'frm_view_forms' );
1651
1652 $error = FrmInbox::check_for_error();
1653
1654 if ( ! $error || 'failed-to-create-tables' !== $error['key'] ) {
1655 // Confirm the inbox item with this CTA exists.
1656 wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
1657 exit;
1658 }
1659
1660 global $wpdb;
1661 $exists = $wpdb->get_results( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->prefix . 'frm_forms' ) );
1662
1663 if ( $exists ) {
1664 // Exit early if the table already exists.
1665 wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
1666 exit;
1667 }
1668
1669 delete_option( 'frm_db_version' );
1670 wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
1671 exit;
1672 }
1673
1674 /**
1675 * Handles the small screen proceed action.
1676 *
1677 * @since 6.21
1678 *
1679 * @return void
1680 */
1681 public static function small_screen_proceed() {
1682 FrmAppHelper::permission_check( 'frm_view_forms' );
1683 check_ajax_referer( 'frm_ajax', 'nonce' );
1684 update_user_option( get_current_user_id(), 'frm_ignore_small_screen_warning', true );
1685 wp_send_json_success();
1686 }
1687 }
1688