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

1,226 lines 33.8 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 if ( ! current_user_can( 'frm_view_forms' ) ) {
14 return;
15 }
16
17 $menu_name = FrmAppHelper::get_menu_name();
18 add_menu_page( 'Formidable', $menu_name, 'frm_view_forms', 'formidable', 'FrmFormsController::route', self::menu_icon(), self::get_menu_position() );
19 }
20
21 /**
22 * @return int
23 */
24 private static function get_menu_position() {
25 return (int) apply_filters( 'frm_menu_position', 29 );
26 }
27
28 /**
29 * @since 3.05
30 */
31 private static function menu_icon() {
32 $icon = FrmAppHelper::svg_logo(
33 array(
34 'fill' => '#a0a5aa',
35 'orange' => '#a0a5aa',
36 )
37 );
38 $icon = 'data:image/svg+xml;base64,' . base64_encode( $icon );
39
40 return apply_filters( 'frm_icon', $icon );
41 }
42
43 /**
44 * @since 3.0
45 */
46 public static function add_admin_class( $classes ) {
47 if ( self::is_white_page() ) {
48 $classes .= ' frm-white-body ';
49 $classes .= self::get_os();
50
51 $page = str_replace( 'formidable-', '', FrmAppHelper::simple_get( 'page', 'sanitize_title' ) );
52 if ( empty( $page ) || $page === 'formidable' ) {
53 $action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
54 if ( in_array( $action, array( 'settings', 'edit', 'list' ) ) ) {
55 $page .= $action;
56 } else {
57 $page = $action;
58 }
59 }
60 if ( ! empty( $page ) ) {
61 $classes .= ' frm-admin-page-' . $page;
62 }
63 }
64
65 if ( FrmAppHelper::is_full_screen() ) {
66 $full_screen_on = self::get_full_screen_setting();
67 $add_class = '';
68 if ( $full_screen_on ) {
69 $add_class = ' frm-full-screen is-fullscreen-mode';
70
71 // Load the CSS for .is-fullscreen-mode.
72 wp_enqueue_style( 'wp-edit-post' );
73 }
74 $classes .= apply_filters( 'frm_admin_full_screen_class', $add_class );
75 }
76
77 if ( ! FrmAppHelper::pro_is_installed() ) {
78 $classes .= ' frm-lite ';
79 }
80
81 if ( get_user_setting( 'unfold' ) && 'f' !== get_user_setting( 'mfold' ) ) {
82 $classes .= ' frm-unfold ';
83 }
84
85 return $classes;
86 }
87
88 /**
89 * Get the full screen mode setting from the block editor.
90 *
91 * @since 6.1
92 *
93 * @return bool
94 */
95 private static function get_full_screen_setting() {
96 global $wpdb;
97 $meta_key = $wpdb->get_blog_prefix() . 'persisted_preferences';
98
99 $prefs = get_user_meta( get_current_user_id(), $meta_key, true );
100 if ( $prefs && isset( $prefs['core/edit-post']['fullscreenMode'] ) ) {
101 return $prefs['core/edit-post']['fullscreenMode'];
102 }
103
104 return true;
105 }
106
107 /**
108 * @since 4.0
109 *
110 * @return string
111 */
112 private static function get_os() {
113 $agent = strtolower( FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' ) );
114 $os = '';
115 if ( strpos( $agent, 'mac' ) !== false ) {
116 $os = ' osx';
117 } elseif ( strpos( $agent, 'linux' ) !== false ) {
118 $os = ' linux';
119 } elseif ( strpos( $agent, 'windows' ) !== false ) {
120 $os = ' windows';
121 }
122 return $os;
123 }
124
125 /**
126 * @since 3.0
127 */
128 private static function is_white_page() {
129 $white_pages = array(
130 'formidable',
131 'formidable-entries',
132 'formidable-views',
133 'formidable-views-editor',
134 'formidable-pro-upgrade',
135 'formidable-addons',
136 'formidable-import',
137 'formidable-settings',
138 'formidable-styles',
139 'formidable-styles2',
140 'formidable-inbox',
141 'formidable-welcome',
142 'formidable-applications',
143 FrmFormTemplatesController::PAGE_SLUG,
144 );
145
146 if ( ! class_exists( 'FrmTransHooksController', false ) && ! FrmTransLiteAppHelper::should_fallback_to_paypal() ) {
147 // Only consider the payments page as a "white page" when the Payments submodule is off.
148 // Otherwise this causes a lot of styling issues when the Stripe add-on (or Authorize.Net) is active.
149
150 // Add an extra check to avoid white page styling on the PayPal "edit" action.
151 // We fallback to the PayPal add on for the "edit" action since Stripe Lite does not have an edit view.
152 if ( ! in_array( FrmAppHelper::simple_get( 'action' ), array( 'edit', 'new' ), true ) || ! is_callable( 'FrmPaymentsController::route' ) ) {
153 $white_pages[] = 'formidable-payments';
154 }
155 }
156
157 $get_page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
158 $is_white_page = in_array( $get_page, $white_pages, true );
159
160 if ( ! $is_white_page ) {
161 $screen = get_current_screen();
162 $is_white_page = ( $screen && strpos( $screen->id, 'frm_display' ) !== false );
163 }
164
165 /**
166 * Allow another add on to style a page as a Formidable "white page", which adds a white background color.
167 *
168 * @since 5.3
169 *
170 * @param bool $is_white_page
171 */
172 $is_white_page = apply_filters( 'frm_is_white_page', $is_white_page );
173
174 return $is_white_page;
175 }
176
177 /**
178 * @return void
179 */
180 public static function load_wp_admin_style() {
181 FrmAppHelper::load_font_style();
182 }
183
184 /**
185 * @param int|object $form
186 * @param bool $show_nav
187 * @param string $title
188 *
189 * @psalm-param 'hide'|'show' $title
190 *
191 * @return void
192 */
193 public static function get_form_nav( $form, $show_nav = false, $title = 'show' ) {
194 $show_nav = FrmAppHelper::get_param( 'show_nav', $show_nav, 'get', 'absint' );
195 if ( empty( $show_nav ) || ! $form ) {
196 return;
197 }
198
199 FrmForm::maybe_get_form( $form );
200 if ( ! is_object( $form ) ) {
201 return;
202 }
203
204 $id = $form->id;
205 $current_page = self::get_current_page();
206 $nav_items = self::get_form_nav_items( $form );
207
208 include( FrmAppHelper::plugin_path() . '/classes/views/shared/form-nav.php' );
209 }
210
211 /**
212 * @return string
213 */
214 private static function get_current_page() {
215 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
216 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title', 'None' );
217 $current_page = isset( $_GET['page'] ) ? $page : $post_type;
218
219 if ( FrmAppHelper::is_view_builder_page() ) {
220 $current_page = 'frm_display';
221 }
222
223 return $current_page;
224 }
225
226 /**
227 * @param object $form
228 * @return array
229 */
230 private static function get_form_nav_items( $form ) {
231 $id = $form->parent_form_id ? $form->parent_form_id : $form->id;
232
233 $nav_items = array(
234 array(
235 'link' => FrmForm::get_edit_link( $id ),
236 'label' => __( 'Build', 'formidable' ),
237 'current' => array( 'edit', 'new', 'duplicate' ),
238 'page' => 'formidable',
239 'permission' => 'frm_edit_forms',
240 ),
241 array(
242 'link' => FrmStylesHelper::get_list_url( $id ),
243 'label' => __( 'Style', 'formidable' ),
244 'current' => array(),
245 'page' => 'formidable-styles',
246 'permission' => 'frm_edit_forms',
247 ),
248 array(
249 'link' => admin_url( 'admin.php?page=formidable&frm_action=settings&id=' . absint( $id ) ),
250 'label' => __( 'Settings', 'formidable' ),
251 'current' => array( 'settings' ),
252 'page' => 'formidable',
253 'permission' => 'frm_edit_forms',
254 ),
255 array(
256 'link' => admin_url( 'admin.php?page=formidable-entries&frm_action=list&form=' . absint( $id ) ),
257 'label' => __( 'Entries', 'formidable' ),
258 'current' => array(),
259 'page' => 'formidable-entries',
260 'permission' => 'frm_view_entries',
261 ),
262 );
263
264 $views_installed = is_callable( 'FrmProAppHelper::views_is_installed' ) ? FrmProAppHelper::views_is_installed() : FrmAppHelper::pro_is_installed();
265
266 if ( ! $views_installed ) {
267 $nav_items[] = array(
268 'link' => admin_url( 'admin.php?page=formidable-views&form=' . absint( $id ) ),
269 'label' => __( 'Views', 'formidable' ),
270 'current' => array(),
271 'page' => 'formidable-views',
272 'permission' => 'frm_view_entries',
273 'atts' => array(
274 'class' => 'frm_noallow',
275 ),
276 );
277 }
278
279 // Let people know reports and views exist.
280 if ( ! FrmAppHelper::pro_is_installed() ) {
281 $nav_items[] = array(
282 'link' => admin_url( 'admin.php?page=formidable&frm_action=lite-reports&form=' . absint( $id ) ),
283 'label' => __( 'Reports', 'formidable' ),
284 'current' => array( 'reports' ),
285 'page' => 'formidable',
286 'permission' => 'frm_view_entries',
287 'atts' => array(
288 'class' => 'frm_noallow',
289 ),
290 );
291 }
292
293 $nav_args = array(
294 'form_id' => $id,
295 'form' => $form,
296 );
297
298 return (array) apply_filters( 'frm_form_nav_list', $nav_items, $nav_args );
299 }
300
301 // Adds a settings link to the plugins page
302 /**
303 * @return array
304 */
305 public static function settings_link( $links ) {
306 $settings = array();
307
308 if ( ! FrmAppHelper::pro_is_installed() ) {
309 $label = FrmAddonsController::is_license_expired() ? __( 'Renew', 'formidable' ) : __( 'Upgrade to Pro', 'formidable' );
310 $settings[] = '<a href="' . esc_url( FrmAppHelper::admin_upgrade_link( 'plugin-row' ) ) . '" target="_blank" rel="noopener"><b style="color:#1da867;font-weight:700;">' . esc_html( $label ) . '</b></a>';
311 }
312
313 $settings[] = '<a href="' . esc_url( admin_url( 'admin.php?page=formidable' ) ) . '">' . __( 'Build a Form', 'formidable' ) . '</a>';
314
315 return array_merge( $settings, $links );
316 }
317
318 /**
319 * @return void
320 */
321 public static function pro_get_started_headline() {
322 self::review_request();
323 FrmAppHelper::min_pro_version_notice( '4.0' );
324 }
325
326 /**
327 * Add admin notices as needed for reviews
328 *
329 * @since 3.04.03
330 *
331 * @return void
332 */
333 private static function review_request() {
334 $reviews = new FrmReviews();
335 $reviews->review_request();
336 }
337
338 /**
339 * Save the request to hide the review
340 *
341 * @since 3.04.03
342 *
343 * @return void
344 */
345 public static function dismiss_review() {
346 FrmAppHelper::permission_check( 'frm_change_settings' );
347 check_ajax_referer( 'frm_ajax', 'nonce' );
348
349 $reviews = new FrmReviews();
350 $reviews->dismiss_review();
351 }
352
353 /**
354 * @since 3.04.02
355 *
356 * @return void
357 */
358 public static function include_upgrade_overlay() {
359 self::enqueue_dialog_assets();
360 add_action( 'admin_footer', 'FrmAppController::upgrade_overlay_html' );
361 }
362
363 /**
364 * Enqueue scripts and styles required for modals.
365 *
366 * @since 5.3
367 *
368 * @return void
369 */
370 public static function enqueue_dialog_assets() {
371 wp_enqueue_script( 'jquery-ui-dialog' );
372 wp_enqueue_style( 'jquery-ui-dialog' );
373 }
374
375 /**
376 * @since 3.06.03
377 *
378 * @return void
379 */
380 public static function upgrade_overlay_html() {
381 $is_pro = FrmAppHelper::pro_is_installed();
382 $upgrade_link = array(
383 'medium' => 'builder',
384 'content' => 'upgrade',
385 );
386 $default_link = FrmAppHelper::admin_upgrade_link( $upgrade_link );
387 $plugin_path = FrmAppHelper::plugin_path();
388 $shared_path = $plugin_path . '/classes/views/shared/';
389
390 include $shared_path . 'upgrade_overlay.php';
391 include $shared_path . 'confirm-overlay.php';
392 }
393
394 /**
395 * Create a basic form with an email field.
396 *
397 * @param string $form_key
398 * @param string $title
399 * @param string $description
400 * @return void
401 */
402 public static function api_email_form( $form_key, $title, $description ) {
403 $user = wp_get_current_user();
404 $args = array(
405 'api_url' => 'https://sandbox.formidableforms.com/api/wp-json/frm/v2/forms/' . $form_key . '?return=html&exclude_script=jquery&exclude_style=formidable-css',
406 'title' => $title,
407 'description' => $description,
408 );
409 require FrmAppHelper::plugin_path() . '/classes/views/form-templates/modals/leave-email-modal.php';
410 }
411
412 /**
413 * @return void
414 */
415 public static function include_info_overlay() {
416 self::enqueue_dialog_assets();
417 add_action( 'admin_footer', 'FrmAppController::info_overlay_html' );
418 }
419
420 /**
421 * @return void
422 */
423 public static function info_overlay_html() {
424 include FrmAppHelper::plugin_path() . '/classes/views/shared/info-overlay.php';
425 }
426
427 /**
428 * @since 3.04.02
429 *
430 * @return void
431 */
432 public static function remove_upsells() {
433 remove_action( 'frm_before_settings', 'FrmSettingsController::license_box' );
434 remove_action( 'frm_after_settings', 'FrmSettingsController::settings_cta' );
435 remove_action( 'frm_add_form_style_tab_options', 'FrmFormsController::add_form_style_tab_options' );
436 remove_action( 'frm_after_field_options', 'FrmFormsController::logic_tip' );
437 }
438
439 /**
440 * If there are CURL problems on this server, wp_remote_post won't work for installing
441 * Use a javascript fallback instead.
442 *
443 * @since 2.0.3
444 *
445 * @return void
446 */
447 public static function install_js_fallback() {
448 FrmAppHelper::load_admin_wide_js();
449 ?>
450 <div id="frm_install_message"></div>
451 <script>jQuery(document).ready( frm_install_now );</script>
452 <?php
453 }
454
455 /**
456 * Check if the database is outdated
457 *
458 * @since 2.0.1
459 * @return boolean
460 */
461 public static function needs_update() {
462 $needs_upgrade = self::compare_for_update(
463 array(
464 'option' => 'frm_db_version',
465 'new_db_version' => FrmAppHelper::$db_version,
466 'new_plugin_version' => FrmAppHelper::plugin_version(),
467 )
468 );
469
470 if ( ! $needs_upgrade ) {
471 $needs_upgrade = apply_filters( 'frm_db_needs_upgrade', $needs_upgrade );
472 }
473
474 return $needs_upgrade;
475 }
476
477 /**
478 * Check both version number and DB number for changes
479 *
480 * @since 3.0.04
481 *
482 * @param array $atts
483 * @return bool
484 */
485 public static function compare_for_update( $atts ) {
486 $db_version = get_option( $atts['option'] );
487
488 if ( strpos( $db_version, '-' ) === false ) {
489 $needs_upgrade = true;
490 } else {
491 $last_upgrade = explode( '-', $db_version );
492 $needs_db_upgrade = (int) $last_upgrade[1] < (int) $atts['new_db_version'];
493 $new_version = version_compare( $last_upgrade[0], $atts['new_plugin_version'], '<' );
494 $needs_upgrade = $needs_db_upgrade || $new_version;
495 }
496
497 return $needs_upgrade;
498 }
499
500 /**
501 * Check for database update and trigger js loading
502 *
503 * @since 2.0.1
504 *
505 * @return void
506 */
507 public static function admin_init() {
508 if ( FrmAppHelper::get_param( 'delete_all' ) && FrmAppHelper::is_admin_page( 'formidable' ) && 'trash' === FrmAppHelper::get_param( 'form_type' ) ) {
509 FrmFormsController::delete_all();
510 }
511
512 if ( FrmAppHelper::is_admin_page( 'formidable' ) && 'duplicate' === FrmAppHelper::get_param( 'frm_action' ) ) {
513 FrmFormsController::duplicate();
514 }
515
516 if ( FrmAppHelper::is_style_editor_page() && 'save' === FrmAppHelper::get_param( 'frm_action' ) ) {
517 // Hook in earlier than FrmStylesController::route so we can redirect before the headers have been sent.
518 FrmStylesController::save_style();
519 }
520
521 // Register personal data hooks.
522 new FrmPersonalData();
523
524 if ( ! FrmAppHelper::doing_ajax() && self::needs_update() ) {
525 self::network_upgrade_site();
526 }
527
528 if ( ! FrmAppHelper::doing_ajax() ) {
529 // don't continue during ajax calls
530 self::admin_js();
531 }
532
533 if ( FrmAppHelper::is_admin_page( 'formidable' ) ) {
534 // Redirect to the "Form Templates" page if the 'frm_action' parameter matches specific actions.
535 // This provides backward compatibility for old addons that use legacy modal templates.
536 $action = FrmAppHelper::get_param( 'frm_action' );
537 $trigger_name_modal = FrmAppHelper::get_param( 'triggerNewFormModal' );
538 if ( $trigger_name_modal || in_array( $action, array( 'add_new', 'list_templates' ), true ) ) {
539 $application_id = FrmAppHelper::simple_get( 'applicationId', 'absint' );
540 $url_param = $application_id ? '&applicationId=' . $application_id : '';
541
542 wp_safe_redirect( admin_url( 'admin.php?page=' . FrmFormTemplatesController::PAGE_SLUG . $url_param ) );
543 exit;
544 }
545
546 FrmInbox::maybe_disable_screen_options();
547 }
548
549 self::maybe_add_ip_warning();
550 }
551
552 /**
553 * Show a warning for the IP address setting if it hasn't been set.
554 *
555 * @since 6.1
556 *
557 * @return void
558 */
559 private static function maybe_add_ip_warning() {
560 $settings = FrmAppHelper::get_settings();
561 if ( false !== $settings->custom_header_ip ) {
562 // The setting has been changed from the false default (to either 1 or 0), so stop showing the message.
563 return;
564 }
565
566 if ( ! self::is_behind_proxy() ) {
567 // This message is only applicable when using a reverse proxy.
568 return;
569 }
570
571 if ( FrmAppHelper::get_post_param( 'frm_action', '', 'sanitize_text_field' ) ) {
572 // Avoid the message on a POST action. We don't want to show the message if we're saving global settings.
573 return;
574 }
575
576 $global_settings_link = admin_url( 'admin.php?page=formidable-settings' ) . '#frm_custom_header_ip';
577 $message = sprintf(
578 // Translators: 1: Global Settings Link
579 __( 'IP addresses in form submissions may no longer be accurate! If you are experiencing issues, we recommend going to %1$s and enabling the "Use custom headers when retrieving IPs with form submissions." setting.', 'formidable' ),
580 '<a href="' . esc_url( $global_settings_link ) . '">Global Settings</a>'
581 );
582 $option_name = 'frm_dismiss_ip_address_notice';
583 FrmAppHelper::add_dismissable_warning_message( $message, $option_name );
584 }
585
586 /**
587 * Check if any reverse proxy headers are set.
588 *
589 * @since 6.1
590 *
591 * @return bool
592 */
593 private static function is_behind_proxy() {
594 $custom_headers = FrmAppHelper::get_custom_header_keys_for_ip();
595 foreach ( $custom_headers as $header ) {
596 if ( 'REMOTE_ADDR' === $header ) {
597 // We want to check every key but REMOTE_ADDR. REMOTE_ATTR is not unique to reverse proxy servers.
598 continue;
599 }
600
601 $ip = trim( FrmAppHelper::get_server_value( $header ) );
602 // Return true for anything that isn't empty but ignoring values like ::1.
603 if ( $ip && 0 !== strpos( $ip, '::' ) ) {
604 return true;
605 }
606 }
607
608 return false;
609 }
610
611 /**
612 * @return void
613 */
614 public static function admin_js() {
615 $plugin_url = FrmAppHelper::plugin_url();
616 $version = FrmAppHelper::plugin_version();
617
618 FrmAppHelper::load_admin_wide_js();
619
620 if ( class_exists( 'FrmOverlayController' ) ) {
621 // This should always exist.
622 // But it may not have loaded properly when updating the plugin.
623 FrmOverlayController::register_assets();
624 }
625
626 wp_register_style( 'formidable_admin_global', $plugin_url . '/css/admin/frm_admin_global.css', array(), $version );
627 wp_enqueue_style( 'formidable_admin_global' );
628
629 wp_register_style( 'formidable-admin', $plugin_url . '/css/frm_admin.css', array(), $version );
630 wp_register_style( 'formidable-grids', $plugin_url . '/css/frm_grids.css', array(), $version );
631
632 wp_register_script( 'formidable_dom', $plugin_url . '/js/admin/dom.js', array( 'jquery', 'jquery-ui-dialog', 'wp-i18n' ), $version, true );
633 wp_register_script( 'formidable_embed', $plugin_url . '/js/admin/embed.js', array( 'formidable_dom', 'jquery-ui-autocomplete' ), $version, true );
634 self::register_popper1();
635 wp_register_script( 'bootstrap_tooltip', $plugin_url . '/js/bootstrap.min.js', array( 'jquery', 'popper' ), '4.6.1', true );
636 wp_register_script( 'formidable_settings', $plugin_url . '/js/admin/settings.js', array(), $version, true );
637
638 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
639
640 // Enqueue Floating Links.
641 $is_valid_page =
642 FrmAppHelper::is_formidable_admin() &&
643 ! FrmAppHelper::is_style_editor_page() &&
644 ! FrmAppHelper::is_admin_page( 'formidable-views-editor' ) &&
645 ! FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
646 if ( $is_valid_page && FrmAppHelper::is_formidable_branding() ) {
647 self::enqueue_floating_links( $plugin_url, $version );
648 }
649 unset( $is_valid_page );
650
651 if ( 'formidable-applications' === $page ) {
652 FrmApplicationsController::load_assets();
653 return;
654 }
655
656 $dependencies = array(
657 'formidable_admin_global',
658 'jquery',
659 'jquery-ui-core',
660 'jquery-ui-draggable',
661 'jquery-ui-sortable',
662 'bootstrap_tooltip',
663 'bootstrap-multiselect',
664 'wp-i18n',
665 // Required in WP versions older than 5.7
666 'wp-hooks',
667 'formidable_dom',
668 'formidable_embed',
669 );
670
671 if ( FrmAppHelper::is_style_editor_page( 'edit' ) ) {
672 // We only need to load the color picker when editing styles.
673 $dependencies[] = 'wp-color-picker';
674 }
675
676 wp_register_script( 'formidable_admin', $plugin_url . '/js/formidable_admin.js', $dependencies, $version, true );
677
678 if ( FrmAppHelper::on_form_listing_page() ) {
679 // For the existing page dropdown in the Form embed modal.
680 wp_enqueue_script( 'jquery-ui-autocomplete' );
681 }
682
683 wp_register_script( 'bootstrap-multiselect', $plugin_url . '/js/bootstrap-multiselect.js', array( 'jquery', 'bootstrap_tooltip', 'popper' ), '1.1.1', true );
684
685 if ( ! class_exists( 'FrmTransHooksController', false ) ) {
686 /**
687 * Gateway fields are included for add-on compatibility but we do not want it to be visible.
688 * They do however need to be visible when the payments submodule is active.
689 */
690 wp_add_inline_style(
691 'formidable-admin',
692 '#frm_builder_page li[data-ftype="gateway"] { display: none; }'
693 );
694 }
695
696 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
697
698 global $pagenow;
699 if ( strpos( $page, 'formidable' ) === 0 || ( $pagenow === 'edit.php' && $post_type === 'frm_display' ) ) {
700
701 wp_enqueue_script( 'admin-widgets' );
702 wp_enqueue_style( 'widgets' );
703 self::maybe_deregister_popper2();
704 wp_enqueue_script( 'formidable_admin' );
705 wp_enqueue_script( 'formidable_embed' );
706 FrmAppHelper::localize_script( 'admin' );
707
708 wp_enqueue_style( 'formidable-admin' );
709 if ( 'formidable-styles' !== $page && 'formidable-styles2' !== $page ) {
710 wp_enqueue_style( 'formidable-grids' );
711 wp_enqueue_style( 'formidable-dropzone' );
712 } else {
713 wp_enqueue_style( 'formidable-grids' );
714 }
715
716 if ( 'formidable-entries' === $page ) {
717 // Load front end js for entries.
718 wp_enqueue_script( 'formidable' );
719
720 // Registers and enqueues the entries page scripts.
721 wp_register_script( 'formidable_entries', $plugin_url . '/js/admin/entries.js', array( 'formidable_admin', 'wp-dom-ready' ), $version, true );
722 wp_enqueue_script( 'formidable_entries' );
723 }
724
725 do_action( 'frm_enqueue_builder_scripts' );
726 self::include_upgrade_overlay();
727 self::include_info_overlay();
728 } elseif ( FrmAppHelper::is_view_builder_page() ) {
729 if ( isset( $_REQUEST['post_type'] ) ) {
730 $post_type = sanitize_title( wp_unslash( $_REQUEST['post_type'] ) );
731 } elseif ( isset( $_REQUEST['post'] ) && absint( $_REQUEST['post'] ) ) {
732 $post = get_post( absint( wp_unslash( $_REQUEST['post'] ) ) );
733 if ( ! $post ) {
734 return;
735 }
736 $post_type = $post->post_type;
737 } else {
738 return;
739 }
740
741 if ( $post_type === 'frm_display' ) {
742 self::enqueue_legacy_views_assets();
743 }
744 }//end if
745
746 }
747
748 /**
749 * @since 6.3.2
750 *
751 * @return void
752 */
753 public static function admin_enqueue_scripts() {
754 self::load_wp_admin_style();
755 self::maybe_force_formidable_block_on_gutenberg_page();
756 }
757
758 /**
759 * Enqueue required assets for the Legacy Views editor (Views v4.x).
760 *
761 * @since 6.1.2
762 *
763 * @return void
764 */
765 private static function enqueue_legacy_views_assets() {
766 wp_enqueue_style( 'formidable-grids' );
767 wp_enqueue_script( 'jquery-ui-draggable' );
768 self::maybe_deregister_popper2();
769 wp_enqueue_script( 'formidable_admin' );
770 wp_add_inline_style(
771 'formidable-admin',
772 '
773 .frm-white-body.post-type-frm_display .columns-2 {
774 display: block;
775 overflow: visible;
776 }
777
778 .frm-white-body.post-type-frm_display .columns-2 > div {
779 overflow-y: hidden;
780 }
781
782 .frm-white-body.post-type-frm_display #titlediv #title-prompt-text {
783 padding: 3px 0 0 10px;
784 }
785
786 .post-type-frm_display #field-search-input,
787 .post-type-frm_display #advanced-search-input {
788 flex: 1;
789 }
790 '
791 );
792 wp_enqueue_style( 'formidable-admin' );
793 FrmAppHelper::localize_script( 'admin' );
794 self::include_info_overlay();
795 }
796
797 /**
798 * Fix a Duplicator Pro conflict because it uses Popper 2. See issue #3459.
799 *
800 * @since 5.2.02.01
801 *
802 * @return void
803 */
804 private static function maybe_deregister_popper2() {
805 global $wp_scripts;
806
807 if ( ! array_key_exists( 'popper', $wp_scripts->registered ) ) {
808 return;
809 }
810
811 $popper = $wp_scripts->registered['popper'];
812 if ( version_compare( $popper->ver, '2.0', '>=' ) ) {
813 wp_deregister_script( 'popper' );
814 self::register_popper1();
815 }
816 }
817
818 /**
819 * Register Popper required for Bootstrap 4.
820 *
821 * @since 5.2.02.01
822 *
823 * @return void
824 */
825 private static function register_popper1() {
826 wp_register_script( 'popper', FrmAppHelper::plugin_url() . '/js/popper.min.js', array( 'jquery' ), '1.16.0', true );
827 }
828
829 /**
830 * Automatically insert a Formidable block when loading Gutenberg when $_GET['frmForm' is set.
831 *
832 * @since 5.2
833 *
834 * @return void
835 */
836 private static function maybe_force_formidable_block_on_gutenberg_page() {
837 global $pagenow;
838 if ( 'post.php' !== $pagenow ) {
839 return;
840 }
841
842 $form_id = FrmAppHelper::simple_get( 'frmForm', 'absint' );
843 if ( ! $form_id ) {
844 return;
845 }
846
847 self::add_js_to_inject_gutenberg_block( 'formidable/simple-form', 'formId', $form_id );
848 }
849
850 /**
851 * @since 5.3
852 *
853 * @param string $block_name
854 * @param string $object_key
855 * @param array|string $object_id
856 *
857 * @return void
858 */
859 public static function add_js_to_inject_gutenberg_block( $block_name, $object_key, $object_id ) {
860 require FrmAppHelper::plugin_path() . '/classes/views/shared/edit-page-js.php';
861 }
862
863 /**
864 * @return void
865 */
866 public static function load_lang() {
867 load_plugin_textdomain( 'formidable', false, FrmAppHelper::plugin_folder() . '/languages/' );
868 }
869
870 /**
871 * Check if the styles are updated when a form is loaded on the front-end
872 *
873 * @since 3.0.1
874 *
875 * @return void
876 */
877 public static function maybe_update_styles() {
878 if ( self::needs_update() ) {
879 self::network_upgrade_site();
880 }
881 }
882
883 /**
884 * @since 3.0
885 *
886 * @return void
887 */
888 public static function create_rest_routes() {
889 $args = array(
890 'methods' => 'GET',
891 'callback' => 'FrmAppController::api_install',
892 'permission_callback' => __CLASS__ . '::can_update_db',
893 );
894
895 register_rest_route( 'frm-admin/v1', '/install', $args );
896
897 $args = array(
898 'methods' => 'GET',
899 'callback' => 'FrmAddonsController::install_addon_api',
900 'permission_callback' => 'FrmAddonsController::can_install_addon_api',
901 );
902
903 register_rest_route( 'frm-admin/v1', '/install-addon', $args );
904 }
905
906 /**
907 * Make sure the install is only being run when we tell it to.
908 * We don't want to run manually by people calling the API.
909 *
910 * @since 4.06.02
911 */
912 public static function can_update_db() {
913 return get_transient( 'frm_updating_api' );
914 }
915
916 /**
917 * Run silent upgrade on each site in the network during a network upgrade.
918 * Update database settings for all sites in a network during network upgrade process.
919 *
920 * @since 2.0.1
921 *
922 * @param int $blog_id Blog ID.
923 *
924 * @return void
925 */
926 public static function network_upgrade_site( $blog_id = 0 ) {
927 // Flag to check if install is happening as intended.
928 set_transient( 'frm_updating_api', true, MINUTE_IN_SECONDS );
929 $request = new WP_REST_Request( 'GET', '/frm-admin/v1/install' );
930
931 self::maybe_add_wp_site_health();
932
933 if ( $blog_id ) {
934 switch_to_blog( $blog_id );
935 $response = rest_do_request( $request );
936 restore_current_blog();
937 } else {
938 $response = rest_do_request( $request );
939 }
940
941 if ( $response->is_error() ) {
942 // if the remove post fails, use javascript instead
943 add_action( 'admin_notices', 'FrmAppController::install_js_fallback' );
944 }
945 }
946
947 /**
948 * Make sure WP_Site_Health has been included because it is required when calling rest_do_request.
949 * Check first that the file exists because WP_Site_Health was only introduced in WordPress 5.2.
950 *
951 * @return void
952 */
953 private static function maybe_add_wp_site_health() {
954 if ( ! class_exists( 'WP_Site_Health' ) ) {
955 $wp_site_health_path = ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
956 if ( file_exists( $wp_site_health_path ) ) {
957 require_once $wp_site_health_path;
958 }
959 }
960 }
961
962 /**
963 * @since 3.0
964 *
965 * @return true
966 */
967 public static function api_install() {
968 delete_transient( 'frm_updating_api' );
969 if ( self::needs_update() ) {
970 $running = get_option( 'frm_install_running' );
971 if ( false === $running || $running < strtotime( '-5 minutes' ) ) {
972 update_option( 'frm_install_running', time(), 'no' );
973 self::install();
974 delete_option( 'frm_install_running' );
975 }
976 }
977
978 return true;
979 }
980
981 /**
982 * Silent database upgrade (no redirect).
983 * Called via ajax request during network upgrade process.
984 *
985 * @since 2.0.1
986 *
987 * @return void
988 */
989 public static function ajax_install() {
990 FrmAppHelper::permission_check( 'frm_change_settings' );
991 check_ajax_referer( 'frm_ajax', 'nonce' );
992 self::api_install();
993 wp_die();
994 }
995
996 /**
997 * @return void
998 */
999 public static function install() {
1000 $frmdb = new FrmMigrate();
1001 $frmdb->upgrade();
1002 }
1003
1004 /**
1005 * @return void
1006 */
1007 public static function uninstall() {
1008 FrmAppHelper::permission_check( 'administrator' );
1009 check_ajax_referer( 'frm_ajax', 'nonce' );
1010
1011 $frmdb = new FrmMigrate();
1012 $frmdb->uninstall();
1013
1014 // Disable the plugin and redirect after uninstall so the tables don't get added right back.
1015 $plugins = array( FrmAppHelper::plugin_folder() . '/formidable.php', 'formidable-pro/formidable-pro.php' );
1016 deactivate_plugins( $plugins, false, false );
1017 echo esc_url_raw( admin_url( 'plugins.php?deactivate=true' ) );
1018
1019 wp_die();
1020 }
1021
1022 public static function drop_tables( $tables ) {
1023 global $wpdb;
1024 $tables[] = $wpdb->prefix . 'frm_fields';
1025 $tables[] = $wpdb->prefix . 'frm_forms';
1026 $tables[] = $wpdb->prefix . 'frm_items';
1027 $tables[] = $wpdb->prefix . 'frm_item_metas';
1028
1029 return $tables;
1030 }
1031
1032 /**
1033 * @return void
1034 */
1035 public static function deauthorize() {
1036 FrmAppHelper::permission_check( 'frm_change_settings' );
1037 check_ajax_referer( 'frm_ajax', 'nonce' );
1038
1039 delete_option( 'frmpro-credentials' );
1040 delete_option( 'frmpro-authorized' );
1041 delete_site_option( 'frmpro-credentials' );
1042 delete_site_option( 'frmpro-authorized' );
1043 wp_die();
1044 }
1045
1046 /**
1047 * This is triggered when Formidable is activated.
1048 *
1049 * @return void
1050 */
1051 public static function handle_activation() {
1052 self::maybe_activate_payment_cron();
1053 }
1054
1055 /**
1056 * The payment cron is unscheduled when Formidable is deactivated.
1057 * We need to add it back again on activation if Stripe is configured.
1058 *
1059 * @since 6.5
1060 *
1061 * @return void
1062 */
1063 private static function maybe_activate_payment_cron() {
1064 if ( ! FrmStrpLiteConnectHelper::stripe_connect_is_setup() ) {
1065 return;
1066 }
1067
1068 FrmTransLiteAppController::maybe_schedule_cron();
1069 }
1070
1071 public static function set_footer_text( $text ) {
1072 if ( FrmAppHelper::is_formidable_admin() ) {
1073 $text = '';
1074 }
1075
1076 return $text;
1077 }
1078
1079 /**
1080 * Add admin footer links.
1081 *
1082 * @since 6.4.1
1083 *
1084 * @return void
1085 */
1086 public static function add_admin_footer_links() {
1087 if ( self::should_show_footer_links() ) {
1088 include FrmAppHelper::plugin_path() . '/classes/views/shared/admin-footer-links.php';
1089 }
1090 }
1091
1092 /**
1093 * Check if the footer links should be shown.
1094 *
1095 * @since 6.7
1096 *
1097 * @return bool
1098 */
1099 private static function should_show_footer_links() {
1100 $post_type = FrmAppHelper::simple_get( 'post_type', 'sanitize_title' );
1101 $is_formidable_page = FrmAppHelper::is_formidable_admin() || 'frm_logs' === $post_type;
1102 $show_footer_links = $is_formidable_page;
1103 if ( FrmAppHelper::is_full_screen() || ! FrmAppHelper::is_formidable_branding() ) {
1104 $show_footer_links = false;
1105 }
1106
1107 /**
1108 * Filter whether to show the Formidable footer links.
1109 *
1110 * @since 6.7
1111 *
1112 * @param bool $show_footer_links
1113 * @return bool
1114 */
1115 return apply_filters( 'frm_show_footer_links', $show_footer_links );
1116 }
1117
1118 /**
1119 * Show an error modal and terminate the script execution.
1120 *
1121 * @since 6.7
1122 *
1123 * @param array $error_args Arguments that control the behavior of the error modal.
1124 *
1125 * @return void
1126 */
1127 public static function show_error_modal( $error_args ) {
1128 $defaults = array(
1129 'title' => '',
1130 'body' => '',
1131 'cancel_url' => '',
1132 'cancel_classes' => '',
1133 'continue_url' => '',
1134 'continue_classes' => '',
1135 'icon' => 'frm_lock_simple',
1136 );
1137
1138 $error_args = wp_parse_args( $error_args, $defaults );
1139 if ( ! isset( $error_args['cancel_text'] ) && ! empty( $error_args['cancel_url'] ) ) {
1140 $error_args['cancel_text'] = __( 'Cancel', 'formidable' );
1141 }
1142
1143 if ( ! isset( $error_args['continue_text'] ) && ! empty( $error_args['continue_url'] ) ) {
1144 $error_args['continue_text'] = __( 'Continue', 'formidable' );
1145 }
1146
1147 include FrmAppHelper::plugin_path() . '/classes/views/frm-forms/error-modal.php';
1148 }
1149
1150 /**
1151 * @deprecated 3.0.04
1152 *
1153 * @codeCoverageIgnore
1154 *
1155 * @return void
1156 */
1157 public static function activation_install() {
1158 FrmDeprecated::activation_install();
1159 }
1160
1161 /**
1162 * @deprecated 3.0
1163 * @codeCoverageIgnore
1164 */
1165 public static function page_route( $content ) {
1166 return FrmDeprecated::page_route( $content );
1167 }
1168
1169 /**
1170 * Include icons on page for Embed Form modal.
1171 *
1172 * @since 5.2
1173 *
1174 * @return void
1175 */
1176 public static function include_embed_form_icons() {
1177 _deprecated_function( __METHOD__, '5.3' );
1178 }
1179
1180 /**
1181 * @deprecated 1.07.05 This is still referenced in the API add on as of v1.13.
1182 * @codeCoverageIgnore
1183 *
1184 * @param array $atts
1185 * @return string
1186 */
1187 public static function get_form_shortcode( $atts ) {
1188 _deprecated_function( __FUNCTION__, '1.07.05', 'FrmFormsController::get_form_shortcode' );
1189 return FrmFormsController::get_form_shortcode( $atts );
1190 }
1191
1192 /**
1193 * Handles Floating Links' scripts and styles enqueueing.
1194 *
1195 * @since 6.4
1196 *
1197 * @param string $plugin_url URL of the plugin.
1198 * @param string $version Current version of the plugin.
1199 * @return void
1200 */
1201 private static function enqueue_floating_links( $plugin_url, $version ) {
1202 if ( ! $plugin_url || ! $version ) {
1203 // If any required parameters are missing, exit early.
1204 return;
1205 }
1206
1207 // Enqueue the Floating Links styles.
1208 wp_enqueue_style( 's11-floating-links', $plugin_url . '/css/packages/s11-floating-links.css', array(), $version );
1209
1210 // Enqueue the Floating Links script.
1211 wp_enqueue_script( 's11-floating-links', $plugin_url . '/js/packages/floating-links/s11-floating-links.js', array(), $version, true );
1212
1213 // Enqueue the config script.
1214 wp_enqueue_script( 's11-floating-links-config', $plugin_url . '/js/packages/floating-links/config.js', array( 'wp-i18n' ), $version, true );
1215
1216 if ( function_exists( 'wp_set_script_translations' ) ) {
1217 wp_set_script_translations( 's11-floating-links-config', 's11-' );
1218 }
1219
1220 $floating_links_data = array(
1221 'proIsInstalled' => FrmAppHelper::pro_is_installed(),
1222 );
1223 wp_localize_script( 's11-floating-links-config', 's11FloatingLinksData', $floating_links_data );
1224 }
1225 }
1226