PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.15
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.15
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
← All changes | classes/controllers/FrmAddonsController.php +492 -235 6.56.15 View file →
@@ -5,15 +5,92 @@
5 5
6 6 class FrmAddonsController {
7 7
8 8 /**
9 - * @var string $plugin
9 + * @var string
10 10 */
11 + const SCRIPT_HANDLE = 'frm-addons-page';
12 +
13 + /**
14 + * @var array
15 + */
16 + private static $categories = array();
17 +
18 + /**
19 + * @var string
20 + */
21 + private static $request_addon_url;
22 +
23 + /**
24 + * @var string
25 + */
11 26 protected static $plugin;
12 27
13 28 /**
29 + * @since 6.15
30 + */
31 + public static function load_admin_hooks() {
32 + add_action( 'admin_menu', __CLASS__ . '::menu', 100 );
33 + add_filter( 'pre_set_site_transient_update_plugins', __CLASS__ . '::check_update' );
34 +
35 + if ( FrmAppHelper::is_admin_page( 'formidable-addons' ) ) {
36 + self::$request_addon_url = 'https://connect.formidableforms.com/add-on-request/';
37 +
38 + add_action( 'admin_enqueue_scripts', __CLASS__ . '::enqueue_assets', 15 );
39 + add_filter( 'frm_show_footer_links', '__return_false' );
40 + }
41 + }
42 +
43 + /**
44 + * Enqueues the Add-Ons page scripts and styles.
45 + *
46 + * @since 6.15
47 + *
14 48 * @return void
15 49 */
50 + public static function enqueue_assets() {
51 + $plugin_url = FrmAppHelper::plugin_url();
52 + $version = FrmAppHelper::plugin_version();
53 + $js_dependencies = array(
54 + 'wp-i18n',
55 + // This prevents a console error "wp.hooks is undefined" in WP versions older than 5.7.
56 + 'wp-hooks',
57 + 'formidable_dom',
58 + );
59 +
60 + // Enqueue styles that needed.
61 + wp_enqueue_style( 'formidable-admin' );
62 + wp_enqueue_style( 'formidable-grids' );
63 +
64 + // Register and enqueue Add-Ons page style.
65 + wp_register_style( self::SCRIPT_HANDLE, $plugin_url . '/css/admin/addons-page.css', array(), $version );
66 + wp_enqueue_style( self::SCRIPT_HANDLE );
67 +
68 + // Register and enqueue Add-Ons page script.
69 + wp_register_script( self::SCRIPT_HANDLE, $plugin_url . '/js/addons-page.js', $js_dependencies, $version, true );
70 + wp_localize_script( self::SCRIPT_HANDLE, 'frmAddonsVars', self::get_js_variables() );
71 + wp_enqueue_script( self::SCRIPT_HANDLE );
72 +
73 + FrmAppHelper::dequeue_extra_global_scripts();
74 + }
75 +
76 + /**
77 + * Get the Add-Ons page JS variables as an array.
78 + *
79 + * @since 6.15
80 + *
81 + * @return array
82 + */
83 + private static function get_js_variables() {
84 + return array(
85 + 'proIsIncluded' => FrmAppHelper::pro_is_included(),
86 + 'addonRequestURL' => self::$request_addon_url,
87 + );
88 + }
89 +
90 + /**
91 + * @return void
92 + */
16 93 public static function menu() {
17 94 if ( ! current_user_can( 'activate_plugins' ) ) {
18 95 return;
19 96 }
@@ -18,12 +95,15 @@
18 95 return;
19 96 }
20 97
21 98 $label = __( 'Add-Ons', 'formidable' );
22 - $label = '<span style="color:#1da867">' . $label . '</span>';
99 + $label = '<span style="color:#3FCA89">' . $label . '</span>';
23 100
24 101 add_submenu_page( 'formidable', 'Formidable | ' . __( 'Add-Ons', 'formidable' ), $label, 'frm_view_forms', 'formidable-addons', 'FrmAddonsController::list_addons' );
25 102
103 + // remove default created subpage, make the page with highest priority as default.
104 + remove_submenu_page( 'formidable', 'formidable' );
105 +
26 106 if ( ! FrmAppHelper::pro_is_installed() ) {
27 107 add_submenu_page(
28 108 'formidable',
29 109 'Formidable | ' . __( 'Upgrade', 'formidable' ),
@@ -42,28 +122,31 @@
42 122 * @return void
43 123 */
44 124 public static function list_addons() {
45 125 FrmAppHelper::include_svg();
46 - $installed_addons = apply_filters( 'frm_installed_addons', array() );
47 - $license_type = '';
48 126
49 - $addons = self::get_api_addons();
50 - $errors = array();
127 + $view_path = FrmAppHelper::plugin_path() . '/classes/views/addons/';
128 + $installed_addons = apply_filters( 'frm_installed_addons', array() );
129 + $addons = self::get_api_addons();
130 + $errors = array();
131 + $license_type = '';
132 + $request_addon_url = self::$request_addon_url;
51 133
52 134 if ( isset( $addons['error'] ) ) {
53 - $api = new FrmFormApi();
54 - $errors = $api->get_error_from_response( $addons );
135 + $api = new FrmFormApi();
136 + $errors = $api->get_error_from_response( $addons );
55 137 $license_type = isset( $addons['error']['type'] ) ? $addons['error']['type'] : '';
56 138 unset( $addons['error'] );
57 139 }
58 140
59 - $pro = array(
141 + $pro = array(
60 142 'pro' => array(
61 - 'title' => 'Formidable Forms Pro',
62 - 'slug' => 'formidable-pro',
63 - 'released' => '2011-02-05',
64 - 'docs' => 'knowledgebase/',
65 - 'excerpt' => 'Create calculators, surveys, smart forms, and data-driven applications. Build directories, real estate listings, job boards, and much more.',
143 + 'title' => 'Formidable Forms Pro',
144 + 'slug' => 'formidable-pro',
145 + 'released' => '2011-02-05',
146 + 'docs' => 'knowledgebase/',
147 + 'categories' => array( 'basic', 'plus', 'business', 'elite' ),
148 + 'excerpt' => 'Create calculators, surveys, smart forms, and data-driven applications. Build directories, real estate listings, job boards, and much more.',
66 149 ),
67 150 );
68 151 $addons = $pro + $addons;
69 152 self::prepare_addons( $addons );
@@ -69,14 +152,105 @@
69 152 self::prepare_addons( $addons );
70 153
71 154 $pricing = FrmAppHelper::admin_upgrade_link( 'addons' );
72 155
73 - include( FrmAppHelper::plugin_path() . '/classes/views/addons/list.php' );
156 + self::organize_and_get_categories();
157 + $categories = self::$categories;
158 +
159 + include $view_path . 'index.php';
74 160 }
75 161
76 162 /**
163 + * Organize and set categories.
164 + *
165 + * @since 6.15
166 + *
77 167 * @return void
78 168 */
169 + protected static function organize_and_get_categories() {
170 + unset( self::$categories['strategy11'] );
171 + ksort( self::$categories );
172 +
173 + $bottom_categories = array();
174 + $plans = FrmFormsHelper::get_license_types(
175 + array(
176 + 'include_all' => false,
177 + 'case_lower' => true,
178 + )
179 + );
180 +
181 + // Extract the elements to move
182 + foreach ( $plans as $plan ) {
183 + if ( isset( self::$categories[ $plan ] ) ) {
184 + $bottom_categories[ $plan ] = self::$categories[ $plan ];
185 + unset( self::$categories[ $plan ] );
186 + }
187 + }
188 +
189 + $special_categories = array();
190 + if ( 'elite' !== self::license_type() ) {
191 + $special_categories['available-addons'] = array(
192 + 'name' => __( 'Available', 'formidable' ),
193 + // To be assigned via JavaScript.
194 + 'count' => 0,
195 + );
196 + }
197 +
198 + $special_categories['active-addons'] = array(
199 + 'name' => __( 'Active', 'formidable' ),
200 + // To be assigned via JavaScript.
201 + 'count' => 0,
202 + );
203 +
204 + $special_categories['all-items'] = array(
205 + 'name' => __( 'All Add-Ons', 'formidable' ),
206 + // To be assigned via JavaScript.
207 + 'count' => 0,
208 + );
209 +
210 + self::$categories = array_merge(
211 + $special_categories,
212 + self::$categories,
213 + $bottom_categories
214 + );
215 + }
216 +
217 + /**
218 + * Organize and set categories.
219 + *
220 + * @since 6.15
221 + *
222 + * @param array $addon The addon array that will be modified by reference.
223 + * @return void
224 + */
225 + protected static function set_categories( &$addon ) {
226 + if ( ! isset( $addon['categories'] ) ) {
227 + return;
228 + }
229 +
230 + $addon['category-slugs'] = array();
231 +
232 + foreach ( $addon['categories'] as $category ) {
233 + $category = FrmFormsHelper::convert_legacy_package_names( $category );
234 + $category_slug = sanitize_title( $category );
235 +
236 + // Add the slug to the new array.
237 + $addon['category-slugs'][] = $category_slug;
238 +
239 + if ( ! isset( self::$categories[ $category_slug ] ) ) {
240 + self::$categories[ $category_slug ] = array(
241 + 'name' => $category,
242 + 'count' => 0,
243 + );
244 + }
245 +
246 + ++self::$categories[ $category_slug ]['count'];
247 + }
248 + }
249 +
250 + /**
251 + * @return void
252 + */
79 253 public static function license_settings() {
80 254 $plugins = apply_filters( 'frm_installed_addons', array() );
81 255 if ( empty( $plugins ) ) {
82 256 esc_html_e( 'There are no plugins on your site that require a license', 'formidable' );
@@ -85,9 +259,9 @@
85 259 }
86 260
87 261 ksort( $plugins );
88 262
89 - include( FrmAppHelper::plugin_path() . '/classes/views/addons/settings.php' );
263 + include FrmAppHelper::plugin_path() . '/classes/views/addons/settings.php';
90 264 }
91 265
92 266 /**
93 267 * @return array
@@ -109,8 +283,21 @@
109 283 return $addons;
110 284 }
111 285
112 286 /**
287 + * Retrieves the count of available addons.
288 + *
289 + * @since 6.9
290 + *
291 + * @return int Count of addons.
292 + */
293 + public static function get_addons_count() {
294 + $addons = self::get_api_addons();
295 +
296 + return count( $addons );
297 + }
298 +
299 + /**
113 300 * If the API is unable to connect, show something on the addons page
114 301 *
115 302 * @since 3.04.03
116 303 * @return array
@@ -272,8 +459,10 @@
272 459 }
273 460
274 461 /**
275 462 * @since 4.0.01
463 + *
464 + * @return bool
276 465 */
277 466 public static function is_license_expired() {
278 467 $version_info = self::get_primary_license_info();
279 468 if ( ! isset( $version_info['error'] ) ) {
@@ -279,30 +468,29 @@
279 468 if ( ! isset( $version_info['error'] ) ) {
280 469 return false;
281 470 }
282 471
283 - return $version_info['error'];
284 - }
472 + $expires = isset( $version_info['error']['expires'] ) ? $version_info['error']['expires'] : 0;
473 + if ( empty( $expires ) || $expires > time() ) {
474 + return false;
475 + }
285 476
286 - /**
287 - * @since 4.08
288 - *
289 - * @return boolean|int false or the number of days until expiration.
290 - */
291 - public static function is_license_expiring() {
292 - if ( is_callable( 'FrmProAddonsController::is_license_expiring' ) ) {
293 - return FrmProAddonsController::is_license_expiring();
477 + $rate_limited = ! empty( $version_info['response_code'] ) && 429 === (int) $version_info['response_code'];
478 + if ( $rate_limited ) {
479 + // Do not return false positives for rate limited responses.
480 + return false;
294 481 }
295 482
296 - return false;
483 + return $version_info['error'];
297 484 }
298 485
299 486 /**
300 487 * @since 4.08
488 + * @since 6.7 This is public.
301 489 *
302 490 * @return array|false
303 491 */
304 - protected static function get_primary_license_info() {
492 + public static function get_primary_license_info() {
305 493 $installed_addons = apply_filters( 'frm_installed_addons', array() );
306 494 if ( empty( $installed_addons ) || ! isset( $installed_addons['formidable_pro'] ) ) {
307 495 return false;
308 496 }
@@ -334,9 +522,9 @@
334 522 $version_info = self::fill_update_addon_info( $installed_addons );
335 523 $transient->last_checked = time();
336 524 $wp_plugins = self::get_plugins();
337 525
338 - foreach ( $version_info as $id => $plugin ) {
526 + foreach ( $version_info as $plugin ) {
339 527 $plugin = (object) $plugin;
340 528
341 529 if ( ! isset( $plugin->new_version ) || ! isset( $plugin->package ) ) {
342 530 continue;
@@ -351,20 +539,21 @@
351 539 // don't show an update if the plugin isn't installed
352 540 continue;
353 541 }
354 542
355 - $wp_plugin = isset( $wp_plugins[ $folder ] ) ? $wp_plugins[ $folder ] : array();
356 - $wp_version = isset( $wp_plugin['Version'] ) ? $wp_plugin['Version'] : '1.0';
543 + $wp_plugin = isset( $wp_plugins[ $folder ] ) ? $wp_plugins[ $folder ] : array();
544 + $wp_version = isset( $wp_plugin['Version'] ) ? $wp_plugin['Version'] : '1.0';
545 + $plugin->slug = explode( '/', $folder )[0];
357 546
358 547 if ( version_compare( $wp_version, $plugin->new_version, '<' ) ) {
359 - $slug = explode( '/', $folder );
360 - $plugin->slug = $slug[0];
361 548 $transient->response[ $folder ] = $plugin;
549 + } else {
550 + $transient->no_update[ $folder ] = $plugin;
362 551 }
363 552
364 553 $transient->checked[ $folder ] = $wp_version;
365 554
366 - }
555 + }//end foreach
367 556
368 557 return $transient;
369 558 }
370 559
@@ -387,9 +576,9 @@
387 576 * Check if a plugin is installed before showing an update for it
388 577 *
389 578 * @since 3.05
390 579 *
391 - * @param string $plugin - the folder/filename.php for a plugin
580 + * @param string $plugin The folder/filename.php for a plugin.
392 581 *
393 582 * @return bool - True if installed
394 583 */
395 584 protected static function is_installed( $plugin ) {
@@ -444,9 +633,9 @@
444 633 'code' => $addon_info['error']['code'],
445 634 );
446 635 }
447 636 }
448 - }
637 + }//end foreach
449 638
450 639 return $version_info;
451 640 }
452 641
@@ -453,9 +642,9 @@
453 642 /**
454 643 * Get the action link for an addon that isn't active.
455 644 *
456 645 * @since 3.06.03
457 - * @param string $plugin The plugin slug
646 + * @param string $plugin The plugin slug.
458 647 * @return array
459 648 */
460 649 public static function install_link( $plugin ) {
461 650 $link = array();
@@ -466,14 +655,14 @@
466 655 $link = array(
467 656 'url' => $addon['plugin'],
468 657 'class' => 'frm-activate-addon',
469 658 );
470 - } elseif ( isset( $addon['url'] ) && ! empty( $addon['url'] ) ) {
659 + } elseif ( ! empty( $addon['url'] ) ) {
471 660 $link = array(
472 661 'url' => $addon['url'],
473 662 'class' => 'frm-install-addon',
474 663 );
475 - } elseif ( isset( $addon['categories'] ) && ! empty( $addon['categories'] ) ) {
664 + } elseif ( ! empty( $addon['categories'] ) ) {
476 665 $link = array(
477 666 'categories' => $addon['categories'],
478 667 );
479 668 }
@@ -485,9 +674,9 @@
485 674 $link = array(
486 675 'url' => 'formidable-' . $plugin . '/formidable-' . $plugin . '.php',
487 676 'class' => 'frm-activate-addon',
488 677 );
489 - }
678 + }//end if
490 679
491 680 return $link;
492 681 }
493 682
@@ -492,12 +681,12 @@
492 681 }
493 682
494 683 /**
495 684 * @since 4.09
496 - * @param string $plugin The plugin slug
685 + * @param string $plugin The plugin slug.
497 686 * @return array|false
498 687 */
499 - protected static function get_addon( $plugin ) {
688 + public static function get_addon( $plugin ) {
500 689 $addons = self::get_api_addons();
501 690 self::prepare_addons( $addons );
502 691 foreach ( $addons as $addon ) {
503 692 $slug = explode( '/', $addon['plugin'] );
@@ -523,10 +712,10 @@
523 712
524 713 /**
525 714 * @since 3.04.03
526 715 *
527 - * @param array $addons
528 - * @param object $license The FrmAddon object
716 + * @param array $addons
717 + * @param object $license The FrmAddon object.
529 718 *
530 719 * @return array
531 720 */
532 721 public static function get_addon_for_license( $addons, $license ) {
@@ -533,9 +722,9 @@
533 722 $download_id = $license->download_id;
534 723 $plugin = array();
535 724 if ( empty( $download_id ) && ! empty( $addons ) ) {
536 725 foreach ( $addons as $addon ) {
537 - if ( strtolower( $license->plugin_name ) == strtolower( $addon['title'] ) ) {
726 + if ( strtolower( $license->plugin_name ) === strtolower( $addon['title'] ) ) {
538 727 return $addon;
539 728 }
540 729 }
541 730 } elseif ( isset( $addons[ $download_id ] ) ) {
@@ -599,13 +788,15 @@
599 788
600 789 if ( ! isset( $addon['link'] ) ) {
601 790 $addon['link'] = 'downloads/' . $slug . '/';
602 791 }
792 +
603 793 self::prepare_addon_link( $addon['link'] );
794 + self::set_addon_status( $addon );
795 + self::set_categories( $addon );
604 796
605 - self::set_addon_status( $addon );
606 797 $addons[ $id ] = $addon;
607 - }
798 + }//end foreach
608 799 }
609 800
610 801 /**
611 802 * @return bool
@@ -617,9 +808,9 @@
617 808 return is_plugin_active( $file_name );
618 809 }
619 810
620 811 /**
621 - * @return string|false either 'visual-views' or 'views', false if one is not found.
812 + * @return false|string either 'visual-views' or 'views', false if one is not found.
622 813 */
623 814 private static function get_active_views_version() {
624 815 if ( ! is_callable( 'FrmViewsAppHelper::plugin_version' ) ) {
625 816 return false;
@@ -685,9 +876,9 @@
685 876 'content' => 'button',
686 877 );
687 878
688 879 $features = array(
689 - 'Display Entries' => array(
880 + 'Display Entries' => array(
690 881 array(
691 882 'label' => 'Display form data with virtually limitless views',
692 883 'link' => array(
693 884 'content' => 'views',
@@ -737,9 +928,9 @@
737 928 'label' => 'Export your entries to a CSV',
738 929 'lite' => true,
739 930 ),
740 931 ),
741 - 'Form Building' => array(
932 + 'Form Building' => array(
742 933 array(
743 934 'label' => 'Save a calculated value into a field',
744 935 'link' => array(
745 936 'content' => 'calculations',
@@ -823,9 +1014,9 @@
823 1014 'label' => 'Use input placeholder text in your fields that clear when typing starts.',
824 1015 'lite' => true,
825 1016 ),
826 1017 ),
827 - 'Form Actions' => array(
1018 + 'Form Actions' => array(
828 1019 array(
829 1020 'label' => 'Conditionally send your email notifications based on values in your form',
830 1021 'link' => array(
831 1022 'content' => 'conditional-emails',
@@ -848,9 +1039,9 @@
848 1039 ),
849 1040 'lite' => true,
850 1041 ),
851 1042 ),
852 - 'Form Appearance' => array(
1043 + 'Form Appearance' => array(
853 1044 array(
854 1045 'label' => 'Create Multiple styles for different forms',
855 1046 'link' => array(
856 1047 'content' => 'multiple-styles',
@@ -880,57 +1071,68 @@
880 1071 ),
881 1072 ),
882 1073 );
883 1074
884 - include( FrmAppHelper::plugin_path() . '/classes/views/addons/upgrade_to_pro.php' );
1075 + include FrmAppHelper::plugin_path() . '/classes/views/addons/upgrade_to_pro.php';
885 1076 }
886 1077
887 1078 /**
888 - * Install Pro after connection with Formidable.
1079 + * @since 5.5.2
889 1080 *
890 - * @since 4.02.05
1081 + * @param string $plugin
1082 + * @param string $redirect
1083 + * @param bool $network_wide
1084 + * @param bool $silent
1085 + * @return WP_Error|null Null on success, WP_Error on invalid file.
1086 + */
1087 + protected static function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) {
1088 + if ( ! function_exists( 'activate_plugin' ) ) {
1089 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
1090 + }
1091 + return activate_plugin( $plugin, $redirect, $network_wide, $silent );
1092 + }
1093 +
1094 + /**
1095 + * Deactivate a specified plugin.
891 1096 *
1097 + * @since 6.8
1098 + *
1099 + * @param string $plugin
1100 + * @param bool $silent
892 1101 * @return void
893 1102 */
894 - public static function connect_pro() {
895 - FrmAppHelper::permission_check( 'install_plugins' );
896 - check_ajax_referer( 'frm_ajax', 'nonce' );
897 -
898 - $url = self::get_current_plugin();
899 - if ( FrmAppHelper::pro_is_installed() || empty( $url ) ) {
900 - wp_die();
1103 + protected static function deactivate_plugin( $plugin, $silent = false ) {
1104 + if ( ! function_exists( 'deactivate_plugins' ) ) {
1105 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
901 1106 }
902 -
903 - $response = array();
904 -
905 - // It's already installed and active.
906 - $active = self::activate_plugin( 'formidable-pro/formidable-pro.php', false, false, true );
907 - if ( is_wp_error( $active ) ) {
908 - // The plugin was installed, but not active. Download it now.
909 - self::ajax_install_addon();
910 - } else {
911 - $response['active'] = true;
912 - $response['success'] = true;
913 - }
914 -
915 - echo json_encode( $response );
916 - wp_die();
1107 + deactivate_plugins( $plugin, $silent );
917 1108 }
918 1109
919 1110 /**
920 - * @since 5.5.2
1111 + * Uninstall a specified plugin.
921 1112 *
1113 + * @since 6.8
1114 + *
922 1115 * @param string $plugin
923 - * @param string $redirect
924 - * @param bool $network_wide
925 - * @param bool $silent
926 - * @return null|WP_Error Null on success, WP_Error on invalid file.
1116 + * @return true|WP_Error True on success, WP_Error on invalid file.
927 1117 */
928 - protected static function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) {
929 - if ( ! function_exists( 'activate_plugin' ) ) {
1118 + protected static function uninstall_plugin( $plugin ) {
1119 + if ( ! current_user_can( 'delete_plugins' ) ) {
1120 + return new WP_Error( 'uninstall_failed', __( 'Current user cannot delete plugins.', 'formidable' ) );
1121 + }
1122 +
1123 + if ( ! function_exists( 'delete_plugins' ) ) {
930 1124 require_once ABSPATH . 'wp-admin/includes/plugin.php';
931 1125 }
932 - return activate_plugin( $plugin, $redirect, $network_wide, $silent );
1126 +
1127 + self::deactivate_plugin( $plugin, true );
1128 + $result = delete_plugins( array( $plugin ) );
1129 +
1130 + if ( is_wp_error( $result ) ) {
1131 + return $result;
1132 + }
1133 +
1134 + return true;
933 1135 }
934 1136
935 1137 /**
936 1138 * @since 5.0.10
@@ -937,9 +1139,9 @@
937 1139 *
938 1140 * @return string
939 1141 */
940 1142 protected static function get_current_plugin() {
941 - if ( ! isset( self::$plugin ) ) {
1143 + if ( empty( self::$plugin ) ) {
942 1144 self::$plugin = FrmAppHelper::get_param( 'plugin', '', 'post', 'esc_url_raw' );
943 1145 }
944 1146 return self::$plugin;
945 1147 }
@@ -945,8 +1147,10 @@
945 1147 }
946 1148
947 1149 /**
948 1150 * @since 4.08
1151 + *
1152 + * @return array|void
949 1153 */
950 1154 protected static function download_and_activate() {
951 1155 if ( is_admin() ) {
952 1156 FrmAppHelper::set_current_screen_and_hook_suffix();
@@ -957,9 +1161,9 @@
957 1161 $installed = self::install_addon();
958 1162 if ( is_array( $installed ) && isset( $installed['message'] ) ) {
959 1163 return $installed;
960 1164 }
961 - self::maybe_activate_addon( $installed );
1165 + self::handle_addon_action( $installed, 'activate' );
962 1166 }
963 1167
964 1168 /**
965 1169 * @since 3.04.02
@@ -967,9 +1171,9 @@
967 1171 * @return void
968 1172 */
969 1173 protected static function maybe_show_cred_form() {
970 1174 if ( ! function_exists( 'request_filesystem_credentials' ) ) {
971 - include_once( ABSPATH . 'wp-admin/includes/file.php' );
1175 + include_once ABSPATH . 'wp-admin/includes/file.php';
972 1176 }
973 1177
974 1178 // Start output bufferring to catch the filesystem form if credentials are needed.
975 1179 ob_start();
@@ -1011,11 +1215,9 @@
1011 1215 *
1012 1216 * @return bool
1013 1217 */
1014 1218 public static function url_is_allowed( $download_url ) {
1015 - return (
1016 - FrmAppHelper::validate_url_is_in_s3_bucket( $download_url, 'zip' ) || in_array( $download_url, self::allowed_external_urls(), true )
1017 - );
1219 + return FrmAppHelper::validate_url_is_in_s3_bucket( $download_url, 'zip' ) || in_array( $download_url, self::allowed_external_urls(), true );
1018 1220 }
1019 1221
1020 1222 /**
1021 1223 * We do not need any extra credentials if we have gotten this far,
@@ -1023,10 +1225,8 @@
1023 1225 *
1024 1226 * @since 3.04.02
1025 1227 */
1026 1228 protected static function install_addon() {
1027 - FrmAppHelper::permission_check( 'install_plugins' );
1028 -
1029 1229 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
1030 1230
1031 1231 $download_url = self::get_current_plugin();
1032 1232
@@ -1054,26 +1254,130 @@
1054 1254 return $plugin;
1055 1255 }
1056 1256
1057 1257 /**
1058 - * @since 3.06.03
1258 + * Handle the AJAX request to activate an add-on.
1059 1259 *
1260 + * @since 6.8
1261 + *
1060 1262 * @return void
1061 1263 */
1062 1264 public static function ajax_activate_addon() {
1265 + self::process_addon_action(
1266 + function ( $plugin ) {
1267 + return self::handle_addon_action( $plugin, 'activate' );
1268 + },
1269 + array( 'FrmAddonsController', 'get_addon_activation_response' )
1270 + );
1271 + }
1063 1272
1273 + /**
1274 + * @since 3.04.02
1275 + *
1276 + * @param string $installed The plugin folder name with file name.
1277 + */
1278 + protected static function maybe_activate_addon( $installed ) {
1279 + self::ajax_activate_addon();
1280 + }
1281 +
1282 + /**
1283 + * Handle the AJAX request to deactivate an add-on.
1284 + *
1285 + * @since 6.8
1286 + *
1287 + * @return void
1288 + */
1289 + public static function ajax_deactivate_addon() {
1290 + self::process_addon_action(
1291 + function ( $plugin ) {
1292 + return self::handle_addon_action( $plugin, 'deactivate' );
1293 + }
1294 + );
1295 + }
1296 +
1297 + /**
1298 + * Handle the AJAX request to uninstall an add-on.
1299 + *
1300 + * @since 6.8
1301 + *
1302 + * @return void
1303 + */
1304 + public static function ajax_uninstall_addon() {
1305 + self::process_addon_action(
1306 + function ( $plugin ) {
1307 + return self::handle_addon_action( $plugin, 'uninstall' );
1308 + }
1309 + );
1310 + }
1311 +
1312 + /**
1313 + * Process a specific action (activate, deactivate, uninstall) on an add-on.
1314 + *
1315 + * @since 6.8
1316 + *
1317 + * @param callable $action_callback The specific add-on action to be executed.
1318 + * @param callable|null $response_callback Optional. The response handling callback. Default null.
1319 + * @return void
1320 + */
1321 + private static function process_addon_action( $action_callback, $response_callback = null ) {
1064 1322 self::install_addon_permissions();
1065 -
1066 1323 FrmAppHelper::set_current_screen_and_hook_suffix();
1067 1324
1068 1325 $plugin = FrmAppHelper::get_param( 'plugin', '', 'post', 'sanitize_text_field' );
1069 - self::maybe_activate_addon( $plugin );
1326 + call_user_func( $action_callback, $plugin );
1070 1327
1071 - echo json_encode( self::get_addon_activation_response() );
1072 - wp_die();
1328 + if ( is_callable( $response_callback ) ) {
1329 + wp_send_json_success( call_user_func( $response_callback ) );
1330 + return;
1331 + }
1332 +
1333 + wp_send_json_success();
1073 1334 }
1074 1335
1075 1336 /**
1337 + * Attempt to perform a specific action (activate, deactivate, uninstall) on an add-on.
1338 + *
1339 + * @since 6.8
1340 + *
1341 + * @param string $installed The plugin folder name with file name.
1342 + * @param string $action The action type ('activate', 'deactivate', 'uninstall').
1343 + * @return array|void
1344 + */
1345 + protected static function handle_addon_action( $installed, $action ) {
1346 + if ( ! $installed || ! $action ) {
1347 + return;
1348 + }
1349 +
1350 + $result = null;
1351 + switch ( $action ) {
1352 + case 'activate':
1353 + $result = self::activate_plugin( $installed );
1354 + break;
1355 + case 'deactivate':
1356 + self::deactivate_plugin( $installed );
1357 + break;
1358 + case 'uninstall':
1359 + $result = self::uninstall_plugin( $installed );
1360 + break;
1361 + }
1362 +
1363 + if ( is_wp_error( $result ) ) {
1364 + // Ignore the invalid header message that shows with nested plugins.
1365 + if ( $result->get_error_code() !== 'no_plugin_header' ) {
1366 + if ( wp_doing_ajax() ) {
1367 + wp_send_json_error( array( 'error' => $result->get_error_message() ) );
1368 + }
1369 + return array(
1370 + 'message' => $result->get_error_message(),
1371 + 'success' => false,
1372 + );
1373 + }
1374 + }
1375 +
1376 + return $result;
1377 + }
1378 +
1379 + /**
1076 1380 * @return array
1077 1381 */
1078 1382 private static function get_addon_activation_response() {
1079 1383 $activating_page = self::get_activating_page();
@@ -1107,34 +1411,8 @@
1107 1411 return '';
1108 1412 }
1109 1413
1110 1414 /**
1111 - * @since 3.04.02
1112 - *
1113 - * @param string $installed The plugin folder name with file name
1114 - */
1115 - protected static function maybe_activate_addon( $installed ) {
1116 - if ( ! $installed ) {
1117 - return;
1118 - }
1119 -
1120 - $activate = self::activate_plugin( $installed );
1121 - if ( is_wp_error( $activate ) ) {
1122 - // Ignore the invalid header message that shows with nested plugins.
1123 - if ( $activate->get_error_code() !== 'no_plugin_header' ) {
1124 - if ( wp_doing_ajax() ) {
1125 - echo json_encode( array( 'error' => $activate->get_error_message() ) );
1126 - wp_die();
1127 - }
1128 - return array(
1129 - 'message' => $activate->get_error_message(),
1130 - 'success' => false,
1131 - );
1132 - }
1133 - }
1134 - }
1135 -
1136 - /**
1137 1415 * Run security checks before installing
1138 1416 *
1139 1417 * @since 3.04.02
1140 1418 *
@@ -1157,15 +1435,18 @@
1157 1435 public static function connect_link() {
1158 1436 $auth = get_option( 'frm_connect_token' );
1159 1437 if ( empty( $auth ) ) {
1160 1438 $auth = hash( 'sha512', wp_rand() );
1161 - update_option( 'frm_connect_token', $auth );
1439 + update_option( 'frm_connect_token', $auth, 'no' );
1162 1440 }
1163 - $link = FrmAppHelper::admin_upgrade_link( 'connect', 'api-connect' );
1441 + $page = FrmAppHelper::simple_get( 'page', 'sanitize_title', 'formidable-settings' );
1442 + $link = 'https://formidableforms.com/api-connect/';
1164 1443 $args = array(
1165 1444 'v' => 2,
1166 1445 'siteurl' => FrmAppHelper::site_url(),
1167 1446 'url' => get_rest_url(),
1447 + 'inst' => (int) FrmAppHelper::pro_is_included(),
1448 + 'return' => $page,
1168 1449 'token' => $auth,
1169 1450 'l' => self::get_pro_license(),
1170 1451 );
1171 1452
@@ -1179,17 +1460,16 @@
1179 1460 *
1180 1461 * @return bool
1181 1462 */
1182 1463 public static function can_install_addon_api() {
1183 - if ( ! current_user_can( 'activate_plugins' ) ) {
1184 - return false;
1185 - }
1186 -
1187 1464 // Verify params present (auth & download link).
1188 1465 $post_auth = FrmAppHelper::get_param( 'token', '', 'request', 'sanitize_text_field' );
1189 1466 $post_url = FrmAppHelper::get_param( 'file_url', '', 'request', 'sanitize_text_field' );
1190 1467
1191 - if ( empty( $post_auth ) || empty( $post_url ) ) {
1468 + // The download link is not required if already installed.
1469 + $is_installed = FrmAppHelper::pro_is_included();
1470 + $file_missing = ! $is_installed && empty( $post_url );
1471 + if ( ! $post_auth || $file_missing ) {
1192 1472 return false;
1193 1473 }
1194 1474
1195 1475 // Verify auth.
@@ -1204,8 +1484,10 @@
1204 1484 /**
1205 1485 * Install and/or activate the add-on file.
1206 1486 *
1207 1487 * @since 4.08
1488 + *
1489 + * @return array
1208 1490 */
1209 1491 public static function install_addon_api() {
1210 1492 self::$plugin = FrmAppHelper::get_param( 'file_url', '', 'request', 'esc_url_raw' );
1211 1493
@@ -1216,11 +1498,11 @@
1216 1498
1217 1499 // It's already installed and active.
1218 1500 $active = self::activate_plugin( 'formidable-pro/formidable-pro.php', false, false, true );
1219 1501 if ( is_wp_error( $active ) ) {
1220 - // Download plugin now.
1221 - $response = self::download_and_activate();
1222 - if ( is_array( $response ) && isset( $response['success'] ) ) {
1502 + $response = self::maybe_download_and_activate();
1503 + if ( is_array( $response ) ) {
1504 + // The download failed.
1223 1505 return $response;
1224 1506 }
1225 1507 }
1226 1508
@@ -1247,22 +1529,58 @@
1247 1529 );
1248 1530 }
1249 1531
1250 1532 /**
1533 + * @since 6.8.3
1534 + *
1535 + * @return array|true
1536 + */
1537 + private static function maybe_download_and_activate() {
1538 + if ( ! self::$plugin ) {
1539 + return array(
1540 + 'success' => false,
1541 + 'message' => __( 'The plugin download was not found.', 'formidable' ),
1542 + );
1543 + }
1544 +
1545 + // Download plugin now.
1546 + $response = self::download_and_activate();
1547 + if ( is_array( $response ) && isset( $response['success'] ) ) {
1548 + // The download failed.
1549 + return $response;
1550 + }
1551 +
1552 + return true;
1553 + }
1554 +
1555 + /**
1251 1556 * Render a conditional action button for a specified plugin
1252 1557 *
1253 - * @param string $plugin
1558 + * @since 4.09
1559 + *
1560 + * @param string $plugin
1254 1561 * @param array|string $upgrade_link_args
1255 - * @since 4.09
1562 + * @return void
1256 1563 */
1257 1564 public static function conditional_action_button( $plugin, $upgrade_link_args ) {
1258 1565 if ( is_callable( 'FrmProAddonsController::conditional_action_button' ) ) {
1259 - return FrmProAddonsController::conditional_action_button( $plugin, $upgrade_link_args );
1566 + FrmProAddonsController::conditional_action_button( $plugin, $upgrade_link_args );
1567 + return;
1260 1568 }
1261 1569
1262 1570 $addon = self::get_addon( $plugin );
1263 1571 $upgrade_link = FrmAppHelper::admin_upgrade_link( $upgrade_link_args );
1264 - self::addon_upgrade_link( $addon, $upgrade_link );
1572 +
1573 + if ( ! is_array( $upgrade_link_args ) ) {
1574 + // A string $upgrade_link_args is used for the utm-medium value when calling
1575 + // FrmAppHelper::admin_upgrade_link above.
1576 + // For self::addon_upgrade_link, we'll pass just an empty array with the link key (set below).
1577 + $upgrade_link_args = array();
1578 + }
1579 +
1580 + $upgrade_link_args['link'] = $upgrade_link;
1581 +
1582 + self::addon_upgrade_link( $addon, $upgrade_link_args );
1265 1583 }
1266 1584
1267 1585 /**
1268 1586 * Render a conditional action button for an add on
@@ -1268,16 +1586,22 @@
1268 1586 * Render a conditional action button for an add on
1269 1587 *
1270 1588 * @since 4.09.01
1271 1589 *
1272 - * @param array $addon
1273 - * @param string|false $license_type
1274 - * @param string $plan_required
1275 - * @param string $upgrade_link
1590 + * @param array $atts {
1591 + * Button attributes.
1592 + *
1593 + * @type array $addon
1594 + * @type false|string $license_type
1595 + * @type string $plan_required
1596 + * @type string $upgrade_link
1597 + * }
1598 + * @return void
1276 1599 */
1277 1600 public static function show_conditional_action_button( $atts ) {
1278 1601 if ( is_callable( 'FrmProAddonsController::show_conditional_action_button' ) ) {
1279 - return FrmProAddonsController::show_conditional_action_button( $atts );
1602 + FrmProAddonsController::show_conditional_action_button( $atts );
1603 + return;
1280 1604 }
1281 1605
1282 1606 self::addon_upgrade_link( $atts['addon'], $atts['upgrade_link'] );
1283 1607 }
@@ -1284,13 +1608,17 @@
1284 1608
1285 1609 /**
1286 1610 * @since 4.09.01
1287 1611 *
1288 - * @param array|false $addon
1612 + * @param array|false $addon
1613 + * @param array|string $upgrade_link
1289 1614 *
1290 1615 * @return void
1291 1616 */
1292 - protected static function addon_upgrade_link( $addon, $upgrade_link ) {
1617 + public static function addon_upgrade_link( $addon, $upgrade_link ) {
1618 + $atts = is_array( $upgrade_link ) ? $upgrade_link : array();
1619 + $upgrade_link = is_array( $upgrade_link ) ? $upgrade_link['link'] : $upgrade_link;
1620 +
1293 1621 if ( $addon ) {
1294 1622 $upgrade_link .= '&utm_content=' . $addon['slug'];
1295 1623 }
1296 1624
@@ -1297,10 +1625,15 @@
1297 1625 if ( $addon && isset( $addon['categories'] ) && in_array( 'Solution', $addon['categories'], true ) ) {
1298 1626 // Solutions will go to a separate page.
1299 1627 $upgrade_link = FrmAppHelper::admin_upgrade_link( 'addons', $addon['link'] );
1300 1628 }
1629 +
1630 + $class = ! empty( $atts['class'] ) ? $atts['class'] : '';
1631 + if ( strpos( $class, 'frm-button' ) === false ) {
1632 + $class .= ' frm-button-secondary frm-button-sm';
1633 + }
1301 1634 ?>
1302 - <a class="install-now button frm-button-secondary frm-button-sm" href="<?php echo esc_url( $upgrade_link ); ?>" target="_blank" rel="noopener" aria-label="<?php esc_attr_e( 'Upgrade Now', 'formidable' ); ?>">
1635 + <a class="install-now button <?php echo esc_attr( $class ); ?>" href="<?php echo esc_url( $upgrade_link ); ?>" target="_blank" rel="noopener" aria-label="<?php esc_attr_e( 'Upgrade Now', 'formidable' ); ?>">
1303 1636 <?php esc_html_e( 'Upgrade Now', 'formidable' ); ?>
1304 1637 </a>
1305 1638 <?php
1306 1639 }
@@ -1378,107 +1711,31 @@
1378 1711 return $requires;
1379 1712 }
1380 1713
1381 1714 /**
1382 - * @since 4.06.02
1715 + * @since 4.02.05
1716 + * @deprecated 6.8.3
1383 1717 *
1384 - * @deprecated 4.09.01
1385 - *
1386 - * @return void
1387 - */
1388 - public static function ajax_multiple_addons() {
1389 - FrmDeprecated::ajax_multiple_addons();
1390 - }
1391 -
1392 - /**
1393 - * @since 3.04.03
1394 - * @deprecated 3.06
1395 1718 * @codeCoverageIgnore
1396 - * @return array
1397 - */
1398 - public static function error_for_license( $license ) {
1399 - return FrmDeprecated::error_for_license( $license );
1400 - }
1401 -
1402 - /**
1403 - * @since 3.04.03
1404 - * @deprecated 3.06
1405 - * @codeCoverageIgnore
1406 - */
1407 - public static function get_pro_updater() {
1408 - return FrmDeprecated::get_pro_updater();
1409 - }
1410 -
1411 - /**
1412 - * @since 3.04.03
1413 - * @deprecated 3.06
1414 - * @codeCoverageIgnore
1415 1719 *
1416 - * @return array
1417 - */
1418 - public static function get_addon_info( $license = '' ) {
1419 - return FrmDeprecated::get_addon_info( $license );
1420 - }
1421 -
1422 - /**
1423 - * @since 3.04.03
1424 - * @deprecated 3.06
1425 - * @codeCoverageIgnore
1426 - *
1427 - * @return string
1428 - */
1429 - public static function get_cache_key( $license ) {
1430 - return FrmDeprecated::get_cache_key( $license );
1431 - }
1432 -
1433 - /**
1434 - * @since 3.04.03
1435 - *
1436 - * @deprecated 3.06
1437 - *
1438 - * @codeCoverageIgnore
1439 - *
1440 1720 * @return void
1441 1721 */
1442 - public static function reset_cached_addons( $license = '' ) {
1443 - FrmDeprecated::reset_cached_addons( $license );
1722 + public static function connect_pro() {
1723 + _deprecated_function( __METHOD__, '6.8.3' );
1444 1724 }
1445 1725
1446 1726 /**
1447 - * @since 2.03.08
1448 - * @deprecated 3.04.03
1449 - * @codeCoverageIgnore
1727 + * @since 4.08
1728 + * @deprecated 6.11.1
1450 1729 *
1451 - * @param boolean $return
1452 - * @param string $package
1453 - *
1454 - * @return boolean
1730 + * @return bool|int false or the number of days until expiration.
1455 1731 */
1456 - public static function add_shorten_edd_filename_filter( $return, $package ) {
1457 - return FrmDeprecated::add_shorten_edd_filename_filter( $return, $package );
1458 - }
1732 + public static function is_license_expiring() {
1733 + _deprecated_function( __METHOD__, '6.11.1', 'FrmProAddonsController::is_license_expiring' );
1459 1734
1460 - /**
1461 - * @since 2.03.08
1462 - * @deprecated 3.04.03
1463 - * @codeCoverageIgnore
1464 - *
1465 - * @param string $filename
1466 - * @param string $ext
1467 - *
1468 - * @return string
1469 - */
1470 - public static function shorten_edd_filename( $filename, $ext ) {
1471 - return FrmDeprecated::shorten_edd_filename( $filename, $ext );
1472 - }
1735 + if ( is_callable( 'FrmProAddonsController::is_license_expiring' ) ) {
1736 + return FrmProAddonsController::is_license_expiring();
1737 + }
1473 1738
1474 - /**
1475 - * @deprecated 3.04.03
1476 - *
1477 - * @codeCoverageIgnore
1478 - *
1479 - * @return void
1480 - */
1481 - public static function get_licenses() {
1482 - FrmDeprecated::get_licenses();
1739 + return false;
1483 1740 }
1484 1741 }