PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.26.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.26.1
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / controllers / FrmAppController.php

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

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