PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.29
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.29
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.29, at classes/controllers/FrmAppController.php

1,711 lines 46.1 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 if ( FrmAppHelper::is_view_builder_page() ) {
282 return 'frm_display';
283 }
284
285 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
286 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title', 'None' );
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' ) ) . '">' . esc_html__( '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 // phpcs:disable Generic.WhiteSpace.ScopeIndent
536 ?>
537 <div id="frm_install_message"></div>
538 <script>jQuery(document).ready( frm_install_now );</script>
539 <?php
540 // phpcs:enable Generic.WhiteSpace.ScopeIndent
541 }
542
543 /**
544 * Check if the database is outdated
545 *
546 * @since 2.0.1
547 *
548 * @return bool
549 */
550 public static function needs_update() {
551 $needs_upgrade = self::compare_for_update(
552 array(
553 'option' => 'frm_db_version',
554 'new_db_version' => FrmAppHelper::$db_version,
555 'new_plugin_version' => FrmAppHelper::plugin_version(),
556 )
557 );
558
559 if ( ! $needs_upgrade ) {
560 return apply_filters( 'frm_db_needs_upgrade', $needs_upgrade );
561 }
562
563 return $needs_upgrade;
564 }
565
566 /**
567 * Check both version number and DB number for changes
568 *
569 * @since 3.0.04
570 *
571 * @param array $atts
572 *
573 * @return bool
574 */
575 public static function compare_for_update( $atts ) {
576 $db_version = get_option( $atts['option'] );
577
578 if ( ! str_contains( $db_version, '-' ) ) {
579 return true;
580 }
581
582 $last_upgrade = explode( '-', $db_version );
583 $needs_db_upgrade = (int) $last_upgrade[1] < (int) $atts['new_db_version'];
584
585 if ( $needs_db_upgrade ) {
586 return true;
587 }
588
589 // New plugin version.
590 return version_compare( $last_upgrade[0], $atts['new_plugin_version'], '<' );
591 }
592
593 /**
594 * Check for database update and trigger js loading
595 *
596 * @since 2.0.1
597 *
598 * @return void
599 */
600 public static function admin_init() {
601 if ( FrmAppHelper::get_param( 'delete_all' ) && FrmAppHelper::is_admin_page( 'formidable' ) && 'trash' === FrmAppHelper::get_param( 'form_type' ) ) {
602 FrmFormsController::delete_all();
603 }
604
605 if ( FrmAppHelper::is_admin_page( 'formidable' ) && 'duplicate' === FrmAppHelper::get_param( 'frm_action' ) ) {
606 FrmFormsController::duplicate();
607 }
608
609 if ( FrmAppHelper::is_admin_page( 'formidable' ) && FrmAppHelper::simple_get( 'frm_add_tables' ) ) {
610 self::add_missing_tables();
611 }
612
613 if ( FrmAppHelper::is_style_editor_page() && 'save' === FrmAppHelper::get_param( 'frm_action' ) ) {
614 // Hook in earlier than FrmStylesController::route so we can redirect before the headers have been sent.
615 FrmStylesController::save_style();
616 }
617
618 if ( 'formidable-pro-upgrade' === FrmAppHelper::get_param( 'page' ) && ! FrmAppHelper::pro_is_installed() && current_user_can( 'frm_view_forms' ) ) {
619 $redirect = FrmSalesApi::get_best_sale_value( 'menu_cta_link' );
620 $utm = array(
621 'campaign' => 'upgrade',
622 'content' => 'submenu-upgrade',
623 );
624
625 $redirect = $redirect ? FrmAppHelper::maybe_add_missing_utm( $redirect, $utm ) : FrmAppHelper::admin_upgrade_link( $utm );
626
627 wp_redirect( $redirect );
628 die();
629 }
630
631 // Register personal data hooks.
632 new FrmPersonalData();
633
634 if ( ! FrmAppHelper::doing_ajax() && self::needs_update() ) {
635 self::network_upgrade_site();
636 }
637
638 if ( ! FrmAppHelper::doing_ajax() ) {
639 // Don't continue during ajax calls
640 self::admin_js();
641 }
642
643 self::trigger_page_load_hooks();
644
645 if ( ! FrmAppHelper::is_admin_page( 'formidable' ) ) {
646 return;
647 }
648
649 // Redirect to the "Form Templates" page if the 'frm_action' parameter matches specific actions.
650 // This provides backward compatibility for old addons that use legacy modal templates.
651 $action = FrmAppHelper::get_param( 'frm_action' );
652 $trigger_name_modal = FrmAppHelper::get_param( 'triggerNewFormModal' );
653
654 if ( $trigger_name_modal || in_array( $action, array( 'add_new', 'list_templates' ), true ) ) {
655 $application_id = FrmAppHelper::simple_get( 'applicationId', 'absint' );
656 $url_param = $application_id ? '&applicationId=' . $application_id : '';
657
658 wp_safe_redirect( admin_url( 'admin.php?page=' . FrmFormTemplatesController::PAGE_SLUG . $url_param ) );
659 exit;
660 }
661
662 FrmInbox::maybe_disable_screen_options();
663 }
664
665 /**
666 * Get the current page and check for a possible function to trigger.
667 * If a class name matches the page name, and the class has a load_page() method, trigger it.
668 *
669 * @since 6.8
670 *
671 * @return void
672 */
673 private static function trigger_page_load_hooks() {
674 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
675
676 if ( ! str_starts_with( $page, 'formidable-' ) ) {
677 // Only trigger hooks on Formidable pages.
678 return;
679 }
680
681 $page = str_replace( array( 'formidable-', '-' ), array( '', ' ' ), $page );
682 $page = str_replace( ' ', '', ucwords( $page ) );
683 $class = 'Frm' . $page . 'Controller';
684
685 if ( class_exists( $class ) && method_exists( $class, 'load_page' ) ) {
686 call_user_func( array( $class, 'load_page' ) );
687 }
688 }
689
690 /**
691 * @return void
692 */
693 public static function admin_js() {
694 $plugin_url = FrmAppHelper::plugin_url();
695 $version = FrmAppHelper::plugin_version();
696 $is_pro_min_v6_28 = FrmAppHelper::pro_is_installed() && FrmAppHelper::meets_min_pro_version( '6.28' );
697 $frm_components_dependencies = $is_pro_min_v6_28 ? array( 'formidable_admin', 'formidable-pro-web-components' ) : array( 'formidable_admin' );
698
699 FrmAppHelper::load_admin_wide_js();
700 // Register component assets early to ensure they can be enqueued later in controllers.
701 wp_register_style( 'formidable-animations', $plugin_url . '/css/admin/animations.css', array(), $version );
702
703 if ( class_exists( 'FrmOverlayController' ) ) {
704 // This should always exist.
705 // But it may not have loaded properly when updating the plugin.
706 FrmOverlayController::register_assets();
707 }
708
709 wp_register_style( 'formidable_admin_global', $plugin_url . '/css/admin/frm_admin_global.css', array(), $version );
710 wp_enqueue_style( 'formidable_admin_global' );
711
712 wp_register_style( 'formidable-admin', $plugin_url . '/css/frm_admin.css', array(), $version );
713 wp_register_style( 'formidable-grids', $plugin_url . '/css/frm_grids.css', array(), $version );
714
715 wp_register_script( 'formidable_dom', $plugin_url . '/js/admin/dom.js', array( 'jquery', 'jquery-ui-dialog', 'wp-i18n' ), $version, true );
716 wp_register_script( 'formidable_embed', $plugin_url . '/js/admin/embed.js', array( 'formidable_dom', 'jquery-ui-autocomplete' ), $version, true );
717 self::register_popper2();
718 wp_register_script( 'bootstrap_tooltip', $plugin_url . '/js/bootstrap.min.js', array( 'jquery', 'popper' ), '5.0.2', true );
719
720 $settings_js_vars = array(
721 'currencies' => FrmCurrencyHelper::get_currencies(),
722 );
723 wp_register_script( 'formidable_settings', $plugin_url . '/js/admin/settings.js', array(), $version, true );
724 wp_localize_script( 'formidable_settings', 'frmSettings', $settings_js_vars );
725 wp_register_script( 'formidable-web-components', $plugin_url . '/js/formidable-web-components.js', $frm_components_dependencies, $version, true );
726
727 if ( self::should_show_floating_links() ) {
728 self::enqueue_floating_links( $plugin_url, $version );
729 }
730
731 wp_register_script( 'formidable_admin', $plugin_url . '/js/formidable_admin.js', self::get_admin_js_dependencies(), $version, true );
732
733 if ( FrmAppHelper::on_form_listing_page() ) {
734 // For the existing page dropdown in the Form embed modal.
735 wp_enqueue_script( 'jquery-ui-autocomplete' );
736 }
737
738 wp_register_script( 'bootstrap-multiselect', $plugin_url . '/js/bootstrap-multiselect.js', array( 'jquery', 'bootstrap_tooltip', 'popper' ), '2.0', true );
739
740 if ( ! class_exists( 'FrmTransHooksController', false ) ) {
741 /**
742 * Gateway fields are included for add-on compatibility but we do not want it to be visible.
743 * They do however need to be visible when the payments submodule is active.
744 */
745 wp_add_inline_style(
746 'formidable-admin',
747 '#frm_builder_page li[data-ftype="gateway"] { display: none; }'
748 );
749 }
750
751 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
752 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
753
754 global $pagenow;
755
756 if ( str_starts_with( $page, 'formidable' ) || ( $pagenow === 'edit.php' && $post_type === 'frm_display' ) ) {
757 self::enqueue_global_settings_scripts( $page );
758
759 wp_enqueue_script( 'admin-widgets' );
760 wp_enqueue_style( 'widgets' );
761 self::maybe_deregister_popper1();
762 wp_enqueue_script( 'formidable_admin' );
763 wp_set_script_translations( 'formidable_admin', 'formidable' );
764 wp_enqueue_script( 'formidable_embed' );
765 wp_set_script_translations( 'formidable_embed', 'formidable' );
766 FrmAppHelper::localize_script( 'admin' );
767
768 wp_enqueue_style( 'formidable-animations' );
769 wp_enqueue_style( 'formidable-admin' );
770
771 if ( 'formidable-styles' !== $page && 'formidable-styles2' !== $page ) {
772 wp_enqueue_style( 'formidable-grids' );
773 self::maybe_enqueue_dropzone_css( $page );
774 } else {
775 wp_enqueue_style( 'formidable-grids' );
776 }
777
778 if ( 'formidable-entries' === $page ) {
779 // Load front end js for entries.
780 wp_enqueue_script( 'formidable' );
781
782 // Registers and enqueues the entries page scripts.
783 wp_register_script( 'formidable_entries', $plugin_url . '/js/admin/entries.js', array( 'formidable_admin', 'wp-dom-ready' ), $version, true );
784 wp_enqueue_script( 'formidable_entries' );
785 }
786
787 do_action( 'frm_enqueue_builder_scripts' );
788 self::include_upgrade_overlay();
789 self::include_info_overlay();
790 } elseif ( FrmAppHelper::is_view_builder_page() ) {
791 if ( isset( $_REQUEST['post_type'] ) ) {
792 $post_type = sanitize_title( wp_unslash( $_REQUEST['post_type'] ) );
793 } elseif ( isset( $_REQUEST['post'] ) && absint( $_REQUEST['post'] ) ) {
794 $post = get_post( absint( wp_unslash( $_REQUEST['post'] ) ) );
795
796 if ( ! $post ) {
797 return;
798 }
799
800 $post_type = $post->post_type;
801 } else {
802 return;
803 }
804
805 if ( $post_type === 'frm_display' ) {
806 self::enqueue_legacy_views_assets();
807 }
808 }//end if
809
810 if ( 'formidable-addons' === $page ) {
811 wp_register_script( 'formidable_addons', $plugin_url . '/js/admin/addons.js', array( 'formidable_admin', 'wp-dom-ready' ), $version, true );
812 wp_enqueue_script( 'formidable_addons' );
813 }
814
815 self::enqueue_builder_assets( $plugin_url, $version );
816 }
817
818 /**
819 * @since 6.27
820 *
821 * @return array
822 */
823 private static function get_admin_js_dependencies() {
824 $dependencies = array(
825 'formidable_admin_global',
826 'jquery',
827 'jquery-ui-core',
828 'jquery-ui-draggable',
829 'jquery-ui-sortable',
830 'bootstrap_tooltip',
831 'bootstrap-multiselect',
832 'wp-i18n',
833 // Required in WP versions older than 5.7
834 'wp-hooks',
835 'formidable_dom',
836 'formidable_embed',
837 );
838
839 if ( FrmAppHelper::is_style_editor_page( 'edit' ) ) {
840 // We only need to load the color picker when editing styles.
841 $dependencies[] = 'wp-color-picker';
842 }
843
844 return $dependencies;
845 }
846
847 /**
848 * Enqueue the Form Builder assets.
849 *
850 * @since 6.24
851 *
852 * @param string $plugin_url The plugin URL.
853 * @param string $version The plugin version.
854 *
855 * @return void
856 */
857 private static function enqueue_builder_assets( $plugin_url, $version ) {
858 wp_register_style( 'formidable-settings-components', $plugin_url . '/css/admin/frm-settings-components.css', array( 'formidable-admin', 'formidable-grids' ), $version );
859 wp_register_script( 'formidable-settings-components', $plugin_url . '/js/formidable-settings-components.js', array( 'formidable_admin' ), $version, true );
860
861 if ( ! FrmAppHelper::is_form_builder_page() ) {
862 return;
863 }
864
865 wp_enqueue_style( 'formidable-settings-components' );
866 wp_enqueue_script( 'formidable-settings-components' );
867 }
868
869 /**
870 * Enqueues global settings scripts.
871 *
872 * @param string $page The `page` param in URL.
873 *
874 * @return void
875 */
876 private static function enqueue_global_settings_scripts( $page ) {
877 if ( 'formidable-settings' !== $page ) {
878 return;
879 }
880
881 wp_enqueue_style( 'wp-color-picker' );
882 wp_enqueue_script( 'formidable_settings' );
883 }
884
885 /**
886 * Avoid loading dropzone CSS on the form list page. It isn't required there.
887 *
888 * @since 6.11
889 *
890 * @param string $page
891 *
892 * @return void
893 */
894 private static function maybe_enqueue_dropzone_css( $page ) {
895 if ( ! FrmAppHelper::pro_is_installed() ) {
896 return;
897 }
898
899 $should_avoid_loading_dropzone = 'formidable' === $page && ! FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
900
901 if ( ! $should_avoid_loading_dropzone ) {
902 wp_enqueue_style( 'formidable-dropzone' );
903 }
904 }
905
906 /**
907 * The floating links are not shown on every page.
908 * They are also not shown if white labeling is being used.
909 *
910 * @since 6.8.4
911 *
912 * @return bool
913 */
914 private static function should_show_floating_links() {
915 if ( ! FrmAppHelper::is_formidable_branding() ) {
916 return false;
917 }
918
919 $should_show = FrmAppHelper::is_formidable_admin() && ! FrmAppHelper::is_style_editor_page() && ! FrmAppHelper::is_admin_page( 'formidable-views-editor' ) && ! FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
920
921 /**
922 * Filters whether the floating links should be displayed.
923 *
924 * @since 6.25.1
925 *
926 * @param bool $should_show Whether the floating links should be shown.
927 */
928 return apply_filters( 'frm_should_show_floating_links', $should_show );
929 }
930
931 /**
932 * @since 6.3.2
933 *
934 * @return void
935 */
936 public static function admin_enqueue_scripts() {
937 self::load_wp_admin_style();
938 self::maybe_force_formidable_block_on_gutenberg_page();
939
940 if ( FrmAppHelper::is_admin_page( 'formidable-settings' ) ) {
941 wp_enqueue_style( FrmDashboardController::PAGE_SLUG, FrmAppHelper::plugin_url() . '/css/admin/dashboard.css', array(), FrmAppHelper::plugin_version() );
942 }
943
944 FrmUsageController::load_scripts();
945 }
946
947 /**
948 * Enqueue required assets for the Legacy Views editor (Views v4.x).
949 *
950 * @since 6.1.2
951 *
952 * @return void
953 */
954 private static function enqueue_legacy_views_assets() {
955 wp_enqueue_style( 'formidable-grids' );
956 wp_enqueue_script( 'jquery-ui-draggable' );
957 self::maybe_deregister_popper1();
958 wp_enqueue_script( 'formidable_admin' );
959 wp_add_inline_style(
960 'formidable-admin',
961 '
962 .frm-white-body.post-type-frm_display .columns-2 {
963 display: block;
964 overflow: visible;
965 }
966
967 .frm-white-body.post-type-frm_display .columns-2 > div {
968 overflow-y: hidden;
969 }
970
971 .frm-white-body.post-type-frm_display #titlediv #title-prompt-text {
972 padding: 3px 0 0 10px;
973 }
974
975 .post-type-frm_display #field-search-input,
976 .post-type-frm_display #advanced-search-input {
977 flex: 1;
978 }
979 '
980 );
981 wp_enqueue_style( 'formidable-admin' );
982 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
983 FrmAppHelper::localize_script( 'admin' );
984 self::include_info_overlay();
985 }
986
987 /**
988 * Unregister Popper if the registered version is outdated.
989 *
990 * @since 6.26
991 *
992 * @return void
993 */
994 private static function maybe_deregister_popper1() {
995 global $wp_scripts;
996
997 if ( ! array_key_exists( 'popper', $wp_scripts->registered ) ) {
998 return;
999 }
1000
1001 $popper = $wp_scripts->registered['popper'];
1002
1003 if ( ! version_compare( $popper->ver, '2.0', '<' ) ) {
1004 return;
1005 }
1006
1007 wp_deregister_script( 'popper' );
1008 self::register_popper2();
1009 }
1010
1011 /**
1012 * Register Popper required for Bootstrap 5.
1013 *
1014 * @since 6.26
1015 *
1016 * @return void
1017 */
1018 private static function register_popper2() {
1019 if ( ! self::should_register_popper() ) {
1020 return;
1021 }
1022 wp_register_script( 'popper', FrmAppHelper::plugin_url() . '/js/popper.min.js', array(), '2.11.8', true );
1023 }
1024
1025 /**
1026 * Only register popper on Formidable pages.
1027 * This helps to avoid popper conflicts on other plugin pages, including the WP Bakery page editor.
1028 *
1029 * @since 6.11.1
1030 *
1031 * @return bool
1032 */
1033 private static function should_register_popper() {
1034 global $pagenow;
1035
1036 $post_id = FrmAppHelper::simple_get( 'post', 'absint' );
1037
1038 if ( 'post.php' === $pagenow && $post_id && 'frm_display' === get_post_type( $post_id ) ) {
1039 return true;
1040 }
1041
1042 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
1043 $is_views_post_type = 'frm_display' === $post_type;
1044
1045 if ( in_array( $pagenow, array( 'post-new.php', 'edit.php' ), true ) && $is_views_post_type ) {
1046 return true;
1047 }
1048
1049 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
1050
1051 if ( str_starts_with( $page, 'formidable' ) ) {
1052 return true;
1053 }
1054
1055 return in_array( $pagenow, array( 'term.php', 'edit-tags.php' ), true ) && FrmAppHelper::simple_get( 'taxonomy' ) === 'frm_application';
1056 }
1057
1058 /**
1059 * Automatically insert a Formidable block when loading Gutenberg when $_GET['frmForm' is set.
1060 *
1061 * @since 5.2
1062 *
1063 * @return void
1064 */
1065 private static function maybe_force_formidable_block_on_gutenberg_page() {
1066 global $pagenow;
1067
1068 if ( 'post.php' !== $pagenow ) {
1069 return;
1070 }
1071
1072 $form_id = FrmAppHelper::simple_get( 'frmForm', 'absint' );
1073
1074 if ( ! $form_id ) {
1075 return;
1076 }
1077
1078 self::add_js_to_inject_gutenberg_block( 'formidable/simple-form', 'formId', $form_id );
1079 }
1080
1081 /**
1082 * @since 5.3
1083 *
1084 * @param string $block_name
1085 * @param string $object_key
1086 * @param array|string $object_id
1087 *
1088 * @return void
1089 */
1090 public static function add_js_to_inject_gutenberg_block( $block_name, $object_key, $object_id ) {
1091 require FrmAppHelper::plugin_path() . '/classes/views/shared/edit-page-js.php';
1092 }
1093
1094 /**
1095 * @return void
1096 */
1097 public static function load_lang() {
1098 load_plugin_textdomain( 'formidable', false, FrmAppHelper::plugin_folder() . '/languages/' );
1099 }
1100
1101 /**
1102 * Check if the styles are updated when a form is loaded on the front-end
1103 *
1104 * @since 3.0.1
1105 *
1106 * @return void
1107 */
1108 public static function maybe_update_styles() {
1109 if ( self::needs_update() ) {
1110 self::network_upgrade_site();
1111 }
1112 }
1113
1114 /**
1115 * @since 3.0
1116 *
1117 * @return void
1118 */
1119 public static function create_rest_routes() {
1120 $args = array(
1121 'methods' => 'GET',
1122 'callback' => 'FrmAppController::api_install',
1123 'permission_callback' => self::class . '::can_update_db',
1124 );
1125
1126 register_rest_route( 'frm-admin/v1', '/install', $args );
1127
1128 $args = array(
1129 'methods' => 'GET',
1130 'callback' => 'FrmAddonsController::install_addon_api',
1131 'permission_callback' => 'FrmAddonsController::can_install_addon_api',
1132 );
1133
1134 register_rest_route( 'frm-admin/v1', '/install-addon', $args );
1135 }
1136
1137 /**
1138 * Make sure the install is only being run when we tell it to.
1139 * We don't want to run manually by people calling the API.
1140 *
1141 * @since 4.06.02
1142 *
1143 * @return bool
1144 */
1145 public static function can_update_db() {
1146 return get_transient( 'frm_updating_api' );
1147 }
1148
1149 /**
1150 * Run silent upgrade on each site in the network during a network upgrade.
1151 * Update database settings for all sites in a network during network upgrade process.
1152 *
1153 * @since 2.0.1
1154 *
1155 * @param int $blog_id Blog ID.
1156 *
1157 * @return void
1158 */
1159 public static function network_upgrade_site( $blog_id = 0 ) {
1160 // Flag to check if install is happening as intended.
1161 set_transient( 'frm_updating_api', true, MINUTE_IN_SECONDS );
1162 $request = new WP_REST_Request( 'GET', '/frm-admin/v1/install' );
1163
1164 self::maybe_add_wp_site_health();
1165
1166 if ( $blog_id ) {
1167 switch_to_blog( $blog_id );
1168 $response = rest_do_request( $request );
1169 restore_current_blog();
1170 } else {
1171 $response = rest_do_request( $request );
1172 }
1173
1174 if ( $response->is_error() ) {
1175 // If the remove post fails, use javascript instead
1176 add_action( 'admin_notices', 'FrmAppController::install_js_fallback' );
1177 }
1178 }
1179
1180 /**
1181 * Make sure WP_Site_Health has been included because it is required when calling rest_do_request.
1182 * Check first that the file exists because WP_Site_Health was only introduced in WordPress 5.2.
1183 *
1184 * @return void
1185 */
1186 private static function maybe_add_wp_site_health() {
1187 if ( class_exists( 'WP_Site_Health' ) ) {
1188 return;
1189 }
1190
1191 $wp_site_health_path = ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
1192
1193 if ( file_exists( $wp_site_health_path ) ) {
1194 require_once $wp_site_health_path;
1195 }
1196 }
1197
1198 /**
1199 * @since 3.0
1200 *
1201 * @return true
1202 */
1203 public static function api_install() {
1204 delete_transient( 'frm_updating_api' );
1205
1206 if ( self::needs_update() ) {
1207 $running = get_option( 'frm_install_running' );
1208
1209 if ( false === $running || $running < strtotime( '-5 minutes' ) ) {
1210 update_option( 'frm_install_running', time(), false );
1211 self::install();
1212 delete_option( 'frm_install_running' );
1213 }
1214 }
1215
1216 return true;
1217 }
1218
1219 /**
1220 * Silent database upgrade (no redirect).
1221 * Called via ajax request during network upgrade process.
1222 *
1223 * @since 2.0.1
1224 *
1225 * @return void
1226 */
1227 public static function ajax_install() {
1228 FrmAppHelper::permission_check( 'frm_change_settings' );
1229 check_ajax_referer( 'frm_ajax', 'nonce' );
1230 self::api_install();
1231 wp_die();
1232 }
1233
1234 /**
1235 * @return void
1236 */
1237 public static function install() {
1238 $frmdb = new FrmMigrate();
1239 $frmdb->upgrade();
1240 }
1241
1242 /**
1243 * @return void
1244 */
1245 public static function uninstall() {
1246 FrmAppHelper::permission_check( 'administrator' );
1247 check_ajax_referer( 'frm_ajax', 'nonce' );
1248
1249 $frmdb = new FrmMigrate();
1250 $frmdb->uninstall();
1251
1252 // Disable the plugin and redirect after uninstall so the tables don't get added right back.
1253 $plugins = array( FrmAppHelper::plugin_folder() . '/formidable.php', 'formidable-pro/formidable-pro.php' );
1254 deactivate_plugins( $plugins, false, false );
1255 echo esc_url_raw( admin_url( 'plugins.php?deactivate=true' ) );
1256
1257 wp_die();
1258 }
1259
1260 /**
1261 * @param array $tables
1262 *
1263 * @return array
1264 */
1265 public static function drop_tables( $tables ) {
1266 global $wpdb;
1267 $tables[] = $wpdb->prefix . 'frm_fields';
1268 $tables[] = $wpdb->prefix . 'frm_forms';
1269 $tables[] = $wpdb->prefix . 'frm_items';
1270 $tables[] = $wpdb->prefix . 'frm_item_metas';
1271
1272 return $tables;
1273 }
1274
1275 /**
1276 * @return void
1277 */
1278 public static function deauthorize() {
1279 FrmAppHelper::permission_check( 'frm_change_settings' );
1280 check_ajax_referer( 'frm_ajax', 'nonce' );
1281
1282 delete_option( 'frmpro-credentials' );
1283 delete_option( 'frmpro-authorized' );
1284 delete_site_option( 'frmpro-credentials' );
1285 delete_site_option( 'frmpro-authorized' );
1286 wp_die();
1287 }
1288
1289 /**
1290 * This is triggered when Formidable is activated.
1291 *
1292 * @return void
1293 */
1294 public static function handle_activation() {
1295 self::maybe_activate_payment_cron();
1296 }
1297
1298 /**
1299 * The payment cron is unscheduled when Formidable is deactivated.
1300 * We need to add it back again on activation if Stripe is configured.
1301 *
1302 * @since 6.5
1303 *
1304 * @return void
1305 */
1306 private static function maybe_activate_payment_cron() {
1307 if ( ! FrmStrpLiteConnectHelper::stripe_connect_is_setup() ) {
1308 return;
1309 }
1310
1311 FrmTransLiteAppController::maybe_schedule_cron();
1312 }
1313
1314 /**
1315 * @param string $text
1316 *
1317 * @return string
1318 */
1319 public static function set_footer_text( $text ) {
1320 return FrmAppHelper::is_formidable_admin() ? '' : $text;
1321 }
1322
1323 /**
1324 * Add admin footer links.
1325 *
1326 * @since 6.4.1
1327 *
1328 * @return void
1329 */
1330 public static function add_admin_footer_links() {
1331 FrmFormsController::include_device_too_small_message();
1332
1333 if ( self::should_show_footer_links() ) {
1334 include FrmAppHelper::plugin_path() . '/classes/views/shared/admin-footer-links.php';
1335 }
1336 }
1337
1338 /**
1339 * Check if the footer links should be shown.
1340 *
1341 * @since 6.7
1342 *
1343 * @return bool
1344 */
1345 private static function should_show_footer_links() {
1346 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
1347 $is_formidable_page = FrmAppHelper::is_formidable_admin() || 'frm_logs' === $post_type;
1348 $show_footer_links = $is_formidable_page;
1349
1350 if ( FrmAppHelper::is_full_screen() || ! FrmAppHelper::is_formidable_branding() ) {
1351 $show_footer_links = false;
1352 }
1353
1354 /**
1355 * Filter whether to show the Formidable footer links.
1356 *
1357 * @since 6.7
1358 *
1359 * @param bool $show_footer_links
1360 *
1361 * @return bool
1362 */
1363 return apply_filters( 'frm_show_footer_links', $show_footer_links );
1364 }
1365
1366 /**
1367 * Show an error modal and terminate the script execution.
1368 *
1369 * @since 6.7
1370 *
1371 * @param array $error_args Arguments that control the behavior of the error modal.
1372 *
1373 * @return void
1374 */
1375 public static function show_error_modal( $error_args ) {
1376 add_filter( 'frm_show_footer_links', '__return_false' );
1377
1378 $defaults = array(
1379 'title' => '',
1380 'body' => '',
1381 'cancel_url' => '',
1382 'cancel_classes' => '',
1383 'continue_url' => '',
1384 'continue_classes' => '',
1385 'icon' => 'frm_lock_simple',
1386 );
1387
1388 $error_args = wp_parse_args( $error_args, $defaults );
1389
1390 if ( ! isset( $error_args['cancel_text'] ) && ! empty( $error_args['cancel_url'] ) ) {
1391 $error_args['cancel_text'] = __( 'Cancel', 'formidable' );
1392 }
1393
1394 if ( ! isset( $error_args['continue_text'] ) && ! empty( $error_args['continue_url'] ) ) {
1395 $error_args['continue_text'] = __( 'Continue', 'formidable' );
1396 }
1397
1398 include FrmAppHelper::plugin_path() . '/classes/views/frm-forms/error-modal.php';
1399 }
1400
1401 /**
1402 * Handles Floating Links' scripts and styles enqueueing.
1403 *
1404 * @since 6.4
1405 *
1406 * @param string $plugin_url URL of the plugin.
1407 * @param string $version Current version of the plugin.
1408 *
1409 * @return void
1410 */
1411 private static function enqueue_floating_links( $plugin_url, $version ) {
1412 if ( ! $plugin_url || ! $version ) {
1413 // If any required parameters are missing, exit early.
1414 return;
1415 }
1416
1417 // Enqueue the Floating Links styles.
1418 wp_enqueue_style( 's11-floating-links', $plugin_url . '/css/packages/s11-floating-links.css', array(), $version );
1419
1420 // Enqueue the Floating Links script.
1421 wp_enqueue_script( 's11-floating-links', $plugin_url . '/js/packages/floating-links/s11-floating-links.js', array( 'formidable_admin' ), $version, true );
1422
1423 // Enqueue the config script.
1424 wp_enqueue_script( 's11-floating-links-config', $plugin_url . '/js/packages/floating-links/config.js', array( 'wp-i18n' ), $version, true );
1425
1426 if ( function_exists( 'wp_set_script_translations' ) ) {
1427 wp_set_script_translations( 's11-floating-links-config', 's11-' );
1428 }
1429
1430 $upgrade_utm = array(
1431 'campaign' => 'floating-links',
1432 'content' => 'floating-links-upgrade',
1433 );
1434 $docs_utm = array(
1435 'campaign' => 'floating-links',
1436 'content' => 'floating-links-docs',
1437 );
1438 $floating_links_data = array(
1439 'proIsInstalled' => FrmAppHelper::pro_is_installed(),
1440 'upgradeUrl' => FrmAppHelper::admin_upgrade_link( $upgrade_utm ),
1441 'documentationUrl' => FrmAppHelper::admin_upgrade_link( $docs_utm, 'knowledgebase/' ),
1442 );
1443 wp_localize_script( 's11-floating-links-config', 's11FloatingLinksData', $floating_links_data );
1444
1445 /**
1446 * Prompt Pro to load additional floating links scripts.
1447 * This is used to include images in the Inbox SlideIn when Pro is active.
1448 *
1449 * @since 6.8.4
1450 */
1451 do_action( 'frm_enqueue_floating_links' );
1452 }
1453
1454 /**
1455 * Check if we are in our admin pages.
1456 *
1457 * @return bool
1458 */
1459 private static function in_our_pages() {
1460 global $current_screen, $pagenow;
1461
1462 if ( FrmAppHelper::is_formidable_admin() ) {
1463 return true;
1464 }
1465
1466 if ( ! empty( $current_screen->post_type ) && 'frm_logs' === $current_screen->post_type ) {
1467 return true;
1468 }
1469
1470 return in_array( $pagenow, array( 'term.php', 'edit-tags.php' ), true ) && 'frm_application' === FrmAppHelper::simple_get( 'taxonomy' );
1471 }
1472
1473 /**
1474 * Handles actions related to the current screen.
1475 *
1476 * @since 6.19
1477 *
1478 * @return void
1479 */
1480 public static function handle_current_screen() {
1481 if ( ! self::in_our_pages() ) {
1482 return;
1483 }
1484
1485 self::filter_admin_notices();
1486 self::remember_custom_sort();
1487 }
1488
1489 /**
1490 * Hide all third-parties admin notices only in our admin pages.
1491 *
1492 * @return void
1493 */
1494 public static function filter_admin_notices() {
1495 $actions = array(
1496 'admin_notices',
1497 'network_admin_notices',
1498 'user_admin_notices',
1499 'all_admin_notices',
1500 );
1501
1502 global $wp_filter;
1503
1504 foreach ( $actions as $action ) {
1505 if ( empty( $wp_filter[ $action ]->callbacks ) ) {
1506 continue;
1507 }
1508
1509 foreach ( $wp_filter[ $action ]->callbacks as $priority => $callbacks ) {
1510 foreach ( $callbacks as $callback_name => $callback ) {
1511 if ( self::is_our_callback_string( $callback_name ) || self::is_our_callback_array( $callback ) ) {
1512 continue;
1513 }
1514 unset( $wp_filter[ $action ]->callbacks[ $priority ][ $callback_name ] );
1515 }
1516 }
1517 }
1518 }
1519
1520 /**
1521 * Remembers and applies user-specific sorting preferences.
1522 *
1523 * @return void
1524 */
1525 private static function remember_custom_sort() {
1526 $meta_key = self::get_sort_pref_user_meta_key();
1527
1528 if ( false === $meta_key ) {
1529 return;
1530 }
1531
1532 $is_form_list = FrmAppHelper::is_admin_list_page();
1533 $is_entry_list = FrmAppHelper::is_admin_list_page( 'formidable-entries' );
1534
1535 if ( ! $is_form_list && ! $is_entry_list ) {
1536 return;
1537 }
1538
1539 $orderby = FrmAppHelper::get_param( 'orderby' );
1540
1541 if ( ! $orderby ) {
1542 return;
1543 }
1544
1545 $user_id = get_current_user_id();
1546 $order = FrmAppHelper::get_param( 'order' );
1547 $new_sort = array(
1548 'orderby' => $orderby,
1549 'order' => $order,
1550 );
1551 $previous_meta = get_user_meta( $user_id, $meta_key, true );
1552 $current_sort = $previous_meta;
1553 $form_id = $is_entry_list ? FrmAppHelper::simple_get( 'form', 'absint' ) : 0;
1554
1555 if ( is_array( $current_sort ) && $form_id && is_int( $form_id ) && isset( $current_sort[ $form_id ] ) ) {
1556 $current_sort = $current_sort[ $form_id ];
1557 }
1558
1559 if ( $new_sort === $current_sort ) {
1560 return;
1561 }
1562
1563 $new_meta = $new_sort;
1564
1565 if ( $is_entry_list && $form_id && is_int( $form_id ) ) {
1566 // Index meta by form ID.
1567 $temp_meta = is_array( $previous_meta ) ? $previous_meta : array();
1568 $temp_meta[ $form_id ] = $new_meta;
1569 $new_meta = $temp_meta;
1570 unset( $temp_meta );
1571 }
1572
1573 update_user_meta( $user_id, $meta_key, $new_meta );
1574 }
1575
1576 /**
1577 * Retrieve and apply any saved sorting preferences for the current screen.
1578 *
1579 * @since 6.19
1580 *
1581 * @param string $orderby Reference to the current 'orderby' parameter.
1582 * @param string $order Reference to the current 'order' parameter.
1583 *
1584 * @return void
1585 */
1586 public static function apply_saved_sort_preference( &$orderby, &$order ) {
1587 $meta_key = self::get_sort_pref_user_meta_key();
1588
1589 if ( false === $meta_key ) {
1590 return;
1591 }
1592
1593 $user_id = get_current_user_id();
1594 $preferred_list_sort = get_user_meta( $user_id, $meta_key, true );
1595 $form_id = FrmAppHelper::simple_get( 'form', 'absint' );
1596
1597 if ( is_array( $preferred_list_sort ) && $form_id && is_int( $form_id ) && isset( $preferred_list_sort[ $form_id ] ) ) {
1598 $preferred_list_sort = $preferred_list_sort[ $form_id ];
1599 }
1600
1601 if ( ! is_array( $preferred_list_sort ) || empty( $preferred_list_sort['orderby'] ) ) {
1602 return;
1603 }
1604
1605 $orderby = $preferred_list_sort['orderby'];
1606
1607 if ( ! empty( $preferred_list_sort['order'] ) ) {
1608 $order = $preferred_list_sort['order'];
1609 }
1610 }
1611
1612 /**
1613 * Get a simple user meta key that only includes the screen ID.
1614 *
1615 * @since 6.25.1
1616 *
1617 * @return false|string
1618 */
1619 private static function get_sort_pref_user_meta_key() {
1620 if ( ! function_exists( 'get_current_screen' ) ) {
1621 return false;
1622 }
1623
1624 $screen = get_current_screen();
1625 return $screen ? 'frm_preferred_list_sort_' . $screen->id : false;
1626 }
1627
1628 /**
1629 * Validate that the callback name is ours not from third-party.
1630 *
1631 * @param string $callback_name WordPress callback name.
1632 *
1633 * @return bool
1634 */
1635 private static function is_our_callback_string( $callback_name ) {
1636 return 0 === stripos( $callback_name, 'frm' );
1637 }
1638
1639 /**
1640 * Validate that the callback array is ours not from third-party.
1641 *
1642 * @param array $callback WordPress callback array.
1643 *
1644 * @return bool
1645 */
1646 private static function is_our_callback_array( $callback ) {
1647 return ! empty( $callback['function'] ) && is_array( $callback['function'] ) && ! empty( $callback['function'][0] ) && self::is_our_callback_string( is_object( $callback['function'][0] ) ? get_class( $callback['function'][0] ) : $callback['function'][0] ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
1648 }
1649
1650 /**
1651 * In some cases, the DB tables may fail to install.
1652 * This function tries to add them again when the user clicks the link to try again
1653 * from the given inbox notice.
1654 *
1655 * @since 6.19
1656 */
1657 private static function add_missing_tables() {
1658 FrmAppHelper::permission_check( 'frm_view_forms' );
1659
1660 $error = FrmInbox::check_for_error();
1661
1662 if ( ! $error || 'failed-to-create-tables' !== $error['key'] ) {
1663 // Confirm the inbox item with this CTA exists.
1664 wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
1665 exit;
1666 }
1667
1668 global $wpdb;
1669 $exists = $wpdb->get_results( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->prefix . 'frm_forms' ) );
1670
1671 if ( $exists ) {
1672 // Exit early if the table already exists.
1673 wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
1674 exit;
1675 }
1676
1677 delete_option( 'frm_db_version' );
1678 wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
1679 exit;
1680 }
1681
1682 /**
1683 * Handles the small screen proceed action.
1684 *
1685 * @since 6.21
1686 *
1687 * @return void
1688 */
1689 public static function small_screen_proceed() {
1690 FrmAppHelper::permission_check( 'frm_view_forms' );
1691 check_ajax_referer( 'frm_ajax', 'nonce' );
1692 update_user_option( get_current_user_id(), 'frm_ignore_small_screen_warning', true );
1693 wp_send_json_success();
1694 }
1695
1696 /**
1697 * Enqueue the components scripts.
1698 *
1699 * @since 6.28
1700 *
1701 * @return void
1702 */
1703 public static function enqueue_components_scripts() {
1704 if ( is_callable( array( 'FrmProFormsController', 'enqueue_pro_web_components_script' ) ) ) {
1705 FrmProFormsController::enqueue_pro_web_components_script();
1706 }
1707
1708 wp_enqueue_script( 'formidable-web-components' );
1709 }
1710 }
1711