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

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

1,569 lines 42.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 FrmAddonsController {
7
8 /**
9 * @var string
10 */
11 protected static $plugin;
12
13 /**
14 * @return void
15 */
16 public static function menu() {
17 if ( ! current_user_can( 'activate_plugins' ) ) {
18 return;
19 }
20
21 $label = __( 'Add-Ons', 'formidable' );
22 $label = '<span style="color:#1da867">' . $label . '</span>';
23
24 add_submenu_page( 'formidable', 'Formidable | ' . __( 'Add-Ons', 'formidable' ), $label, 'frm_view_forms', 'formidable-addons', 'FrmAddonsController::list_addons' );
25
26 // remove default created subpage, make the page with highest priority as default.
27 remove_submenu_page( 'formidable', 'formidable' );
28
29 if ( ! FrmAppHelper::pro_is_installed() ) {
30 add_submenu_page(
31 'formidable',
32 'Formidable | ' . __( 'Upgrade', 'formidable' ),
33 '<span class="frm-upgrade-submenu">' . __( 'Upgrade', 'formidable' ) . '</span>',
34 'frm_view_forms',
35 'formidable-pro-upgrade',
36 'FrmAddonsController::upgrade_to_pro'
37 );
38 } elseif ( 'formidable-pro-upgrade' === FrmAppHelper::get_param( 'page' ) ) {
39 wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
40 exit;
41 }
42 }
43
44 /**
45 * @return void
46 */
47 public static function list_addons() {
48 FrmAppHelper::include_svg();
49 $installed_addons = apply_filters( 'frm_installed_addons', array() );
50 $license_type = '';
51
52 $addons = self::get_api_addons();
53 $errors = array();
54
55 if ( isset( $addons['error'] ) ) {
56 $api = new FrmFormApi();
57 $errors = $api->get_error_from_response( $addons );
58 $license_type = isset( $addons['error']['type'] ) ? $addons['error']['type'] : '';
59 unset( $addons['error'] );
60 }
61
62 $pro = array(
63 'pro' => array(
64 'title' => 'Formidable Forms Pro',
65 'slug' => 'formidable-pro',
66 'released' => '2011-02-05',
67 'docs' => 'knowledgebase/',
68 'excerpt' => 'Create calculators, surveys, smart forms, and data-driven applications. Build directories, real estate listings, job boards, and much more.',
69 ),
70 );
71 $addons = $pro + $addons;
72 self::prepare_addons( $addons );
73
74 $pricing = FrmAppHelper::admin_upgrade_link( 'addons' );
75
76 include FrmAppHelper::plugin_path() . '/classes/views/addons/list.php';
77 }
78
79 /**
80 * @return void
81 */
82 public static function license_settings() {
83 $plugins = apply_filters( 'frm_installed_addons', array() );
84 if ( empty( $plugins ) ) {
85 esc_html_e( 'There are no plugins on your site that require a license', 'formidable' );
86
87 return;
88 }
89
90 ksort( $plugins );
91
92 include FrmAppHelper::plugin_path() . '/classes/views/addons/settings.php';
93 }
94
95 /**
96 * @return array
97 */
98 protected static function get_api_addons() {
99 $api = new FrmFormApi();
100 $addons = $api->get_api_info();
101
102 if ( empty( $addons ) ) {
103 $addons = self::fallback_plugin_list();
104 } else {
105 foreach ( $addons as $k => $addon ) {
106 if ( empty( $addon['excerpt'] ) && $k !== 'error' ) {
107 unset( $addons[ $k ] );
108 }
109 }
110 }
111
112 return $addons;
113 }
114
115 /**
116 * Retrieves the count of available addons.
117 *
118 * @since 6.9
119 *
120 * @return int Count of addons.
121 */
122 public static function get_addons_count() {
123 $addons = self::get_api_addons();
124
125 return count( $addons );
126 }
127
128 /**
129 * If the API is unable to connect, show something on the addons page
130 *
131 * @since 3.04.03
132 * @return array
133 */
134 protected static function fallback_plugin_list() {
135 $list = array(
136 'formidable-pro' => array(
137 'title' => 'Formidable Forms Pro',
138 'link' => 'pricing/',
139 'docs' => '',
140 'excerpt' => 'Enhance your basic Formidable forms with a plethora of Pro field types and features. Create advanced forms and data-driven applications in minutes.',
141 ),
142 'mailchimp' => array(
143 'title' => 'Mailchimp Forms',
144 'excerpt' => 'Get on the path to more sales and leads in a matter of minutes. Add leads to a Mailchimp mailing list when they submit forms and update their information along with the entry.',
145 ),
146 'registration' => array(
147 'title' => 'User Registration Forms',
148 'link' => 'downloads/user-registration/',
149 'excerpt' => 'Give new users access to your site as quickly and painlessly as possible. Allow users to register, edit and be able to login to their profiles on your site from the front end in a clean, customized registration form.',
150 ),
151 'paypal' => array(
152 'title' => 'PayPal Standard Forms',
153 'link' => 'downloads/paypal-standard/',
154 'excerpt' => 'Automate your business by collecting instant payments from your clients. Collect information, calculate a total, and send them on to PayPal. Require a payment before publishing content on your site.',
155 ),
156 'stripe' => array(
157 'title' => 'Stripe Forms',
158 'docs' => 'knowledgebase/stripe/',
159 'excerpt' => 'Any Formidable forms on your site can accept credit card payments without users ever leaving your site.',
160 ),
161 'authorize-net' => array(
162 'title' => 'Authorize.net AIM Forms',
163 'link' => 'downloads/authorize-net-aim/',
164 'docs' => 'knowledgebase/authorize-net-aim/',
165 'excerpt' => 'Accept one-time payments directly on your site, using Authorize.net AIM.',
166 ),
167 'woocommerce' => array(
168 'title' => 'WooCommerce Forms',
169 'excerpt' => 'Use a Formidable form on your WooCommerce product pages.',
170 ),
171 'autoresponder' => array(
172 'title' => 'Form Action Automation',
173 'docs' => 'knowledgebase/schedule-autoresponder/',
174 'excerpt' => 'Schedule email notifications, SMS messages, and API actions.',
175 ),
176 'modal' => array(
177 'title' => 'Bootstrap Modal Forms',
178 'link' => 'downloads/bootstrap-modal/',
179 'docs' => 'knowledgebase/bootstrap-modal/',
180 'excerpt' => 'Open a view or form in a Bootstrap popup.',
181 ),
182 'bootstrap' => array(
183 'title' => 'Bootstrap Style Forms',
184 'excerpt' => 'Instantly add Bootstrap styling to all your Formidable forms.',
185 ),
186 'zapier' => array(
187 'title' => 'Zapier Forms',
188 'excerpt' => 'Connect with hundreds of different applications through Zapier. Insert a new row in a Google docs spreadsheet, post on Twitter, or add a new Dropbox file with your form.',
189 ),
190 'signature' => array(
191 'title' => 'Digital Signature Forms',
192 'excerpt' => 'Add a signature field to your form. The user may write their signature with a trackpad/mouse or just type it.',
193 ),
194 'api' => array(
195 'title' => 'Formidable Forms API',
196 'link' => 'downloads/formidable-api/',
197 'excerpt' => 'Send entry results to any other site that has a Rest API. This includes the option of sending entries from one Formidable site to another.',
198 ),
199 'twilio' => array(
200 'title' => 'Twilio SMS Forms',
201 'docs' => 'knowledgebase/twilio-add-on/',
202 'excerpt' => 'Allow users to text their votes for polls created by Formidable Forms, or send SMS notifications when entries are submitted or updated.',
203 ),
204 'views' => array(
205 'title' => 'Formidable Views',
206 'excerpt' => 'Add the power of views to your Formidable Forms to display your form submissions in listings, tables, calendars, and more.',
207 ),
208 'quiz_maker' => array(
209 'title' => 'Quiz Maker',
210 'link' => 'downloads/quiz-maker/',
211 'excerpt' => 'Make quizzes, automatically score them and show user scores.',
212 ),
213 );
214
215 $defaults = array(
216 'released' => '',
217 );
218
219 foreach ( $list as $k => $info ) {
220 $info['slug'] = $k;
221 $list[ $k ] = array_merge( $defaults, $info );
222 }
223 return $list;
224 }
225
226 /**
227 * If Pro is missing but has been authenticated, include a download URL
228 *
229 * @since 3.04.03
230 * @return string
231 */
232 public static function get_pro_download_url() {
233 $license = self::get_pro_license();
234 $api = new FrmFormApi( $license );
235 $downloads = $api->get_api_info();
236 $pro = self::get_pro_from_addons( $downloads );
237
238 return isset( $pro['url'] ) ? $pro['url'] : '';
239 }
240
241 /**
242 * @since 4.08
243 */
244 public static function get_pro_license() {
245 $pro_cred_store = 'frmpro-credentials';
246 $pro_wpmu_store = 'frmpro-wpmu-sitewide';
247 if ( is_multisite() && get_site_option( $pro_wpmu_store ) ) {
248 $creds = get_site_option( $pro_cred_store );
249 } else {
250 $creds = get_option( $pro_cred_store );
251 }
252
253 if ( empty( $creds ) || ! is_array( $creds ) || ! isset( $creds['license'] ) ) {
254 return '';
255 }
256
257 $license = $creds['license'];
258 if ( empty( $license ) ) {
259 return '';
260 }
261
262 if ( strpos( $license, '-' ) ) {
263 // this is a fix for licenses saved in the past
264 $license = strtoupper( $license );
265 }
266 return $license;
267 }
268
269 /**
270 * @since 4.08
271 *
272 * @param array $addons
273 * @return array
274 */
275 protected static function get_pro_from_addons( $addons ) {
276 return isset( $addons['93790'] ) ? $addons['93790'] : array();
277 }
278
279 /**
280 * @since 4.06
281 */
282 public static function license_type() {
283 if ( is_callable( 'FrmProAddonsController::license_type' ) ) {
284 return FrmProAddonsController::license_type();
285 }
286
287 return 'free';
288 }
289
290 /**
291 * @since 4.0.01
292 *
293 * @return bool
294 */
295 public static function is_license_expired() {
296 $version_info = self::get_primary_license_info();
297 if ( ! isset( $version_info['error'] ) ) {
298 return false;
299 }
300
301 $expires = isset( $version_info['error']['expires'] ) ? $version_info['error']['expires'] : 0;
302 if ( empty( $expires ) || $expires > time() ) {
303 return false;
304 }
305
306 $rate_limited = ! empty( $version_info['response_code'] ) && 429 === (int) $version_info['response_code'];
307 if ( $rate_limited ) {
308 // Do not return false positives for rate limited responses.
309 return false;
310 }
311
312 return $version_info['error'];
313 }
314
315 /**
316 * @since 4.08
317 * @since 6.7 This is public.
318 *
319 * @return array|false
320 */
321 public static function get_primary_license_info() {
322 $installed_addons = apply_filters( 'frm_installed_addons', array() );
323 if ( empty( $installed_addons ) || ! isset( $installed_addons['formidable_pro'] ) ) {
324 return false;
325 }
326 $installed_addons = array(
327 'formidable_pro' => $installed_addons['formidable_pro'],
328 );
329
330 return self::fill_update_addon_info( $installed_addons );
331 }
332
333 /**
334 * @since 3.04.03
335 */
336 public static function check_update( $transient ) {
337 if ( ! FrmAppHelper::pro_is_installed() ) {
338 // Don't make any changes if only Lite is installed.
339 return $transient;
340 }
341
342 if ( ! is_object( $transient ) ) {
343 $transient = new stdClass();
344 }
345
346 $installed_addons = apply_filters( 'frm_installed_addons', array() );
347 if ( empty( $installed_addons ) ) {
348 return $transient;
349 }
350
351 $version_info = self::fill_update_addon_info( $installed_addons );
352 $transient->last_checked = time();
353 $wp_plugins = self::get_plugins();
354
355 foreach ( $version_info as $plugin ) {
356 $plugin = (object) $plugin;
357
358 if ( ! isset( $plugin->new_version ) || ! isset( $plugin->package ) ) {
359 continue;
360 }
361
362 $folder = $plugin->plugin;
363 if ( empty( $folder ) ) {
364 continue;
365 }
366
367 if ( ! self::is_installed( $folder ) ) {
368 // don't show an update if the plugin isn't installed
369 continue;
370 }
371
372 $wp_plugin = isset( $wp_plugins[ $folder ] ) ? $wp_plugins[ $folder ] : array();
373 $wp_version = isset( $wp_plugin['Version'] ) ? $wp_plugin['Version'] : '1.0';
374 $plugin->slug = explode( '/', $folder )[0];
375
376 if ( version_compare( $wp_version, $plugin->new_version, '<' ) ) {
377 $transient->response[ $folder ] = $plugin;
378 } else {
379 $transient->no_update[ $folder ] = $plugin;
380 }
381
382 $transient->checked[ $folder ] = $wp_version;
383
384 }//end foreach
385
386 return $transient;
387 }
388
389 /**
390 * Copy of FrmAppHelper::get_plugins.
391 * Because this gets called on "pre_set_site_transient_update_plugins" an old version of FrmAppHelper may be loaded on plugin update.
392 * This means that trying to access FrmAppHelper::get_plugins when upgrading from a Lite version before v5.5 results in a one-off error.
393 *
394 * @since 5.5.2
395 * @return array
396 */
397 protected static function get_plugins() {
398 if ( ! function_exists( 'get_plugins' ) ) {
399 require_once ABSPATH . 'wp-admin/includes/plugin.php';
400 }
401 return get_plugins();
402 }
403
404 /**
405 * Check if a plugin is installed before showing an update for it
406 *
407 * @since 3.05
408 *
409 * @param string $plugin The folder/filename.php for a plugin.
410 *
411 * @return bool - True if installed
412 */
413 protected static function is_installed( $plugin ) {
414 $all_plugins = self::get_plugins();
415 return isset( $all_plugins[ $plugin ] );
416 }
417
418 /**
419 * @since 3.04.03
420 *
421 * @param array $installed_addons
422 *
423 * @return array
424 */
425 protected static function fill_update_addon_info( $installed_addons ) {
426 $checked_licenses = array();
427 $version_info = array();
428
429 foreach ( $installed_addons as $addon ) {
430 if ( $addon->store_url !== 'https://formidableforms.com' ) {
431 // check if this is a third-party addon
432 continue;
433 }
434
435 $new_license = $addon->license;
436 if ( empty( $new_license ) || in_array( $new_license, $checked_licenses ) ) {
437 continue;
438 }
439
440 $checked_licenses[] = $new_license;
441
442 $api = new FrmFormApi( $new_license );
443 if ( empty( $version_info ) ) {
444 $version_info = $api->get_api_info();
445 continue;
446 }
447
448 $plugin = $api->get_addon_for_license( $addon, $version_info );
449 if ( empty( $plugin ) ) {
450 continue;
451 }
452
453 $download_id = isset( $plugin['id'] ) ? $plugin['id'] : 0;
454 if ( ! empty( $download_id ) && ! isset( $version_info[ $download_id ]['package'] ) ) {
455 // if this addon is using its own license, get the update url
456 $addon_info = $api->get_api_info();
457
458 $version_info[ $download_id ] = $addon_info[ $download_id ];
459 if ( isset( $addon_info['error'] ) ) {
460 $version_info[ $download_id ]['error'] = array(
461 'message' => $addon_info['error']['message'],
462 'code' => $addon_info['error']['code'],
463 );
464 }
465 }
466 }//end foreach
467
468 return $version_info;
469 }
470
471 /**
472 * Get the action link for an addon that isn't active.
473 *
474 * @since 3.06.03
475 * @param string $plugin The plugin slug.
476 * @return array
477 */
478 public static function install_link( $plugin ) {
479 $link = array();
480 $addon = self::get_addon( $plugin );
481
482 if ( $addon ) {
483 if ( $addon['status']['type'] === 'installed' && ! empty( $addon['activate_url'] ) ) {
484 $link = array(
485 'url' => $addon['plugin'],
486 'class' => 'frm-activate-addon',
487 );
488 } elseif ( ! empty( $addon['url'] ) ) {
489 $link = array(
490 'url' => $addon['url'],
491 'class' => 'frm-install-addon',
492 );
493 } elseif ( ! empty( $addon['categories'] ) ) {
494 $link = array(
495 'categories' => $addon['categories'],
496 );
497 }
498
499 if ( ! empty( $link ) ) {
500 $link['status'] = $addon['status']['type'];
501 }
502 } elseif ( current_user_can( 'activate_plugins' ) && self::is_installed( 'formidable-' . $plugin . '/formidable-' . $plugin . '.php' ) ) {
503 $link = array(
504 'url' => 'formidable-' . $plugin . '/formidable-' . $plugin . '.php',
505 'class' => 'frm-activate-addon',
506 );
507 }//end if
508
509 return $link;
510 }
511
512 /**
513 * @since 4.09
514 * @param string $plugin The plugin slug.
515 * @return array|false
516 */
517 public static function get_addon( $plugin ) {
518 $addons = self::get_api_addons();
519 self::prepare_addons( $addons );
520 foreach ( $addons as $addon ) {
521 $slug = explode( '/', $addon['plugin'] );
522 if ( $slug[0] === 'formidable-' . $plugin ) {
523 return $addon;
524 }
525 }
526 return false;
527 }
528
529 /**
530 * @since 4.09
531 * @return string
532 */
533 protected static function get_license_type() {
534 $license_type = '';
535 $addons = self::get_api_addons();
536 if ( isset( $addons['error'] ) && isset( $addons['error']['type'] ) ) {
537 $license_type = $addons['error']['type'];
538 }
539 return $license_type;
540 }
541
542 /**
543 * @since 3.04.03
544 *
545 * @param array $addons
546 * @param object $license The FrmAddon object.
547 *
548 * @return array
549 */
550 public static function get_addon_for_license( $addons, $license ) {
551 $download_id = $license->download_id;
552 $plugin = array();
553 if ( empty( $download_id ) && ! empty( $addons ) ) {
554 foreach ( $addons as $addon ) {
555 if ( strtolower( $license->plugin_name ) === strtolower( $addon['title'] ) ) {
556 return $addon;
557 }
558 }
559 } elseif ( isset( $addons[ $download_id ] ) ) {
560 $plugin = $addons[ $download_id ];
561 }
562
563 return $plugin;
564 }
565
566 /**
567 * @return void
568 */
569 protected static function prepare_addons( &$addons ) {
570 $activate_url = '';
571 if ( current_user_can( 'activate_plugins' ) ) {
572 $activate_url = add_query_arg( array( 'action' => 'activate' ), admin_url( 'plugins.php' ) );
573 }
574
575 $loop_addons = $addons;
576 foreach ( $loop_addons as $id => $addon ) {
577 if ( is_numeric( $id ) ) {
578 $slug = str_replace( array( '-wordpress-plugin', '-wordpress' ), '', $addon['slug'] );
579 $file_name = $addon['plugin'];
580 } else {
581 $slug = $id;
582 if ( isset( $addon['file'] ) ) {
583 $base_file = $addon['file'];
584 } else {
585 $base_file = 'formidable-' . $slug;
586 }
587 $file_name = $base_file . '/' . $base_file . '.php';
588 if ( ! isset( $addon['plugin'] ) ) {
589 $addon['plugin'] = $file_name;
590 }
591 }
592
593 $addon['installed'] = self::is_installed( $file_name );
594 if ( $addon['installed'] && 'formidable-views/formidable-views.php' === $file_name ) {
595 $active_views_version = self::get_active_views_version();
596 if ( false !== $active_views_version && $slug !== $active_views_version ) {
597 $addon['installed'] = false;
598 }
599 }
600
601 $addon['activate_url'] = '';
602
603 if ( $addon['installed'] && ! empty( $activate_url ) && ! self::is_plugin_active( $file_name, $slug ) ) {
604 $addon['activate_url'] = add_query_arg(
605 array(
606 '_wpnonce' => wp_create_nonce( 'activate-plugin_' . $file_name ),
607 'plugin' => $file_name,
608 ),
609 $activate_url
610 );
611 }
612
613 if ( ! isset( $addon['docs'] ) ) {
614 $addon['docs'] = 'knowledgebase/formidable-' . $slug . '/';
615 }
616 self::prepare_addon_link( $addon['docs'] );
617
618 if ( ! isset( $addon['link'] ) ) {
619 $addon['link'] = 'downloads/' . $slug . '/';
620 }
621 self::prepare_addon_link( $addon['link'] );
622
623 self::set_addon_status( $addon );
624 $addons[ $id ] = $addon;
625 }//end foreach
626 }
627
628 /**
629 * @return bool
630 */
631 private static function is_plugin_active( $file_name, $slug ) {
632 if ( 'formidable-views/formidable-views.php' === $file_name ) {
633 return self::get_active_views_version() === $slug;
634 }
635 return is_plugin_active( $file_name );
636 }
637
638 /**
639 * @return false|string either 'visual-views' or 'views', false if one is not found.
640 */
641 private static function get_active_views_version() {
642 if ( ! is_callable( 'FrmViewsAppHelper::plugin_version' ) ) {
643 return false;
644 }
645 $plugin_version = FrmViewsAppHelper::plugin_version();
646 return version_compare( $plugin_version, '5.0', '>=' ) ? 'visual-views' : 'views';
647 }
648
649 /**
650 * @since 3.04.02
651 *
652 * @return void
653 */
654 protected static function prepare_addon_link( &$link ) {
655 $site_url = 'https://formidableforms.com/';
656 if ( strpos( $link, 'http' ) !== 0 ) {
657 $link = $site_url . $link;
658 }
659 $link = FrmAppHelper::make_affiliate_url( $link );
660 $query_args = array(
661 'utm_source' => 'WordPress',
662 'utm_medium' => 'addons',
663 'utm_campaign' => 'liteplugin',
664 );
665 $link = add_query_arg( $query_args, $link );
666 }
667
668 /**
669 * Add the status to the addon array. Status options are:
670 * installed, active, not installed
671 *
672 * @since 3.04.02
673 *
674 * @return void
675 */
676 protected static function set_addon_status( &$addon ) {
677 if ( ! empty( $addon['activate_url'] ) ) {
678 $addon['status'] = array(
679 'type' => 'installed',
680 'label' => __( 'Installed', 'formidable' ),
681 );
682 } elseif ( $addon['installed'] ) {
683 $addon['status'] = array(
684 'type' => 'active',
685 'label' => __( 'Active', 'formidable' ),
686 );
687 } else {
688 $addon['status'] = array(
689 'type' => 'not-installed',
690 'label' => __( 'Not Installed', 'formidable' ),
691 );
692 }
693 }
694
695 /**
696 * @return void
697 */
698 public static function upgrade_to_pro() {
699 FrmAppHelper::include_svg();
700
701 $link_parts = array(
702 'medium' => 'upgrade',
703 'content' => 'button',
704 );
705
706 $features = array(
707 'Display Entries' => array(
708 array(
709 'label' => 'Display form data with virtually limitless views',
710 'link' => array(
711 'content' => 'views',
712 'param' => 'views-display-form-data',
713 ),
714 'lite' => false,
715 ),
716 array(
717 'label' => 'Generate graphs and stats based on your submitted data',
718 'link' => array(
719 'content' => 'graphs',
720 'param' => 'statistics-graphs-wordpress-forms',
721 ),
722 'lite' => false,
723 ),
724 ),
725 'Entry Management' => array(
726 array(
727 'label' => 'Import entries from a CSV',
728 'link' => array(
729 'content' => 'import-entries',
730 'param' => 'importing-exporting-wordpress-forms',
731 ),
732 'lite' => false,
733 ),
734 array(
735 'label' => 'Logged-in users can save drafts and return later',
736 'link' => array(
737 'content' => 'save-drafts',
738 'param' => 'save-drafts-wordpress-form',
739 ),
740 'lite' => false,
741 ),
742 array(
743 'label' => 'Flexibly and powerfully view, edit, and delete entries from anywhere on your site',
744 'link' => array(
745 'content' => 'front-edit',
746 'param' => 'wordpress-front-end-editing',
747 ),
748 'lite' => false,
749 ),
750 array(
751 'label' => 'View form submissions from the back-end',
752 'lite' => true,
753 ),
754 array(
755 'label' => 'Export your entries to a CSV',
756 'lite' => true,
757 ),
758 ),
759 'Form Building' => array(
760 array(
761 'label' => 'Save a calculated value into a field',
762 'link' => array(
763 'content' => 'calculations',
764 'param' => 'field-calculations-wordpress-form',
765 ),
766 'lite' => false,
767 ),
768 array(
769 'label' => 'Allow multiple file uploads',
770 'link' => array(
771 'content' => 'file-uploads',
772 'param' => 'wordpress-multi-file-upload-fields',
773 ),
774 'lite' => false,
775 ),
776 array(
777 'label' => 'Repeat sections of fields',
778 'link' => array(
779 'content' => 'repeaters',
780 'param' => 'repeatable-sections-forms',
781 ),
782 'lite' => false,
783 ),
784 array(
785 'label' => 'Hide and show fields conditionally based on other fields or the user\'s role',
786 'link' => array(
787 'content' => 'conditional-logic',
788 'param' => 'conditional-logic-wordpress-forms',
789 ),
790 'lite' => false,
791 ),
792 array(
793 'label' => 'Confirmation fields',
794 'link' => array(
795 'content' => 'confirmation-fields',
796 'param' => 'confirmation-fields-wordpress-forms',
797 ),
798 'lite' => false,
799 ),
800 array(
801 'label' => 'Multi-paged forms',
802 'link' => array(
803 'content' => 'page-breaks',
804 'param' => 'wordpress-multi-page-forms',
805 ),
806 'lite' => false,
807 ),
808 array(
809 'label' => 'Include section headings, page breaks, rich text, dates, times, scales, star ratings, sliders, toggles, dynamic fields populated from other forms, passwords, and tags in advanced forms.',
810 'lite' => false,
811 ),
812 array(
813 'label' => 'Include text, email, url, paragraph text, radio, checkbox, dropdown fields, hidden fields, user ID fields, and HTML blocks in your form.',
814 'lite' => true,
815 ),
816 array(
817 'label' => 'Drag & Drop Form building',
818 'link' => array(
819 'content' => 'drag-drop',
820 'param' => 'drag-drop-forms',
821 ),
822 'lite' => true,
823 ),
824 array(
825 'label' => 'Create forms from Templates',
826 'link' => array(
827 'content' => 'form-templates',
828 'param' => 'wordpress-form-templates',
829 ),
830 'lite' => true,
831 ),
832 array(
833 'label' => 'Import and export forms with XML',
834 'link' => array(
835 'content' => 'import',
836 'param' => 'importing-exporting-wordpress-forms',
837 ),
838 'lite' => true,
839 ),
840 array(
841 'label' => 'Use input placeholder text in your fields that clear when typing starts.',
842 'lite' => true,
843 ),
844 ),
845 'Form Actions' => array(
846 array(
847 'label' => 'Conditionally send your email notifications based on values in your form',
848 'link' => array(
849 'content' => 'conditional-emails',
850 ),
851 'lite' => false,
852 ),
853 array(
854 'label' => 'Create and edit WordPress posts or custom posts from the front-end',
855 'link' => array(
856 'content' => 'create-posts',
857 'param' => 'create-posts-pages-wordpress-forms',
858 ),
859 'lite' => false,
860 ),
861 array(
862 'label' => 'Send multiple emails and autoresponders',
863 'link' => array(
864 'content' => 'multiple-emails',
865 'param' => 'virtually-unlimited-emails',
866 ),
867 'lite' => true,
868 ),
869 ),
870 'Form Appearance' => array(
871 array(
872 'label' => 'Create Multiple styles for different forms',
873 'link' => array(
874 'content' => 'multiple-styles',
875 'param' => 'wordpress-visual-form-styler',
876 ),
877 'lite' => false,
878 ),
879 array(
880 'label' => 'Customizable layout with CSS classes',
881 'link' => array(
882 'content' => 'form-layout',
883 'param' => 'wordpress-mobile-friendly-forms',
884 ),
885 'lite' => true,
886 ),
887 array(
888 'label' => 'Customize the HTML for your forms',
889 'link' => array(
890 'content' => 'custom-html',
891 'param' => 'customizable-html-wordpress-form',
892 ),
893 'lite' => true,
894 ),
895 array(
896 'label' => 'Style your form with the Visual Form Styler',
897 'lite' => true,
898 ),
899 ),
900 );
901
902 include FrmAppHelper::plugin_path() . '/classes/views/addons/upgrade_to_pro.php';
903 }
904
905 /**
906 * @since 5.5.2
907 *
908 * @param string $plugin
909 * @param string $redirect
910 * @param bool $network_wide
911 * @param bool $silent
912 * @return WP_Error|null Null on success, WP_Error on invalid file.
913 */
914 protected static function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) {
915 if ( ! function_exists( 'activate_plugin' ) ) {
916 require_once ABSPATH . 'wp-admin/includes/plugin.php';
917 }
918 return activate_plugin( $plugin, $redirect, $network_wide, $silent );
919 }
920
921 /**
922 * Deactivate a specified plugin.
923 *
924 * @since 6.8
925 *
926 * @param string $plugin
927 * @param bool $silent
928 * @return void
929 */
930 protected static function deactivate_plugin( $plugin, $silent = false ) {
931 if ( ! function_exists( 'deactivate_plugins' ) ) {
932 require_once ABSPATH . 'wp-admin/includes/plugin.php';
933 }
934 deactivate_plugins( $plugin, $silent );
935 }
936
937 /**
938 * Uninstall a specified plugin.
939 *
940 * @since 6.8
941 *
942 * @param string $plugin
943 * @return true|WP_Error True on success, WP_Error on invalid file.
944 */
945 protected static function uninstall_plugin( $plugin ) {
946 if ( ! current_user_can( 'delete_plugins' ) ) {
947 return new WP_Error( 'uninstall_failed', __( 'Current user cannot delete plugins.', 'formidable' ) );
948 }
949
950 if ( ! function_exists( 'delete_plugins' ) ) {
951 require_once ABSPATH . 'wp-admin/includes/plugin.php';
952 }
953
954 self::deactivate_plugin( $plugin, true );
955 $result = delete_plugins( array( $plugin ) );
956
957 if ( is_wp_error( $result ) ) {
958 return $result;
959 }
960
961 return true;
962 }
963
964 /**
965 * @since 5.0.10
966 *
967 * @return string
968 */
969 protected static function get_current_plugin() {
970 if ( empty( self::$plugin ) ) {
971 self::$plugin = FrmAppHelper::get_param( 'plugin', '', 'post', 'esc_url_raw' );
972 }
973 return self::$plugin;
974 }
975
976 /**
977 * @since 4.08
978 *
979 * @return array|void
980 */
981 protected static function download_and_activate() {
982 if ( is_admin() ) {
983 FrmAppHelper::set_current_screen_and_hook_suffix();
984 }
985
986 self::maybe_show_cred_form();
987
988 $installed = self::install_addon();
989 if ( is_array( $installed ) && isset( $installed['message'] ) ) {
990 return $installed;
991 }
992 self::handle_addon_action( $installed, 'activate' );
993 }
994
995 /**
996 * @since 3.04.02
997 *
998 * @return void
999 */
1000 protected static function maybe_show_cred_form() {
1001 if ( ! function_exists( 'request_filesystem_credentials' ) ) {
1002 include_once ABSPATH . 'wp-admin/includes/file.php';
1003 }
1004
1005 // Start output bufferring to catch the filesystem form if credentials are needed.
1006 ob_start();
1007
1008 $show_form = false;
1009 $method = '';
1010 $url = add_query_arg( array( 'page' => 'formidable-settings' ), admin_url( 'admin.php' ) );
1011 $url = esc_url_raw( $url );
1012 $creds = request_filesystem_credentials( $url, $method, false, false, null );
1013
1014 if ( false === $creds ) {
1015 $show_form = true;
1016 } elseif ( ! WP_Filesystem( $creds ) ) {
1017 request_filesystem_credentials( $url, $method, true, false, null );
1018 $show_form = true;
1019 }
1020
1021 if ( $show_form ) {
1022 $form = ob_get_clean();
1023 $message = __( 'Sorry, your site requires FTP authentication. Please download plugins from FormidableForms.com and install them manually.', 'formidable' );
1024 $data = $form;
1025 $response = array(
1026 'success' => false,
1027 'message' => $message,
1028 'form' => $form,
1029 );
1030 wp_send_json( $response );
1031 }
1032
1033 ob_end_clean();
1034 }
1035
1036 /**
1037 * Checks if an addon download url is allowed.
1038 *
1039 * @since 6.2
1040 *
1041 * @param string $download_url
1042 *
1043 * @return bool
1044 */
1045 public static function url_is_allowed( $download_url ) {
1046 return FrmAppHelper::validate_url_is_in_s3_bucket( $download_url, 'zip' ) || in_array( $download_url, self::allowed_external_urls(), true );
1047 }
1048
1049 /**
1050 * We do not need any extra credentials if we have gotten this far,
1051 * so let's install the plugin.
1052 *
1053 * @since 3.04.02
1054 */
1055 protected static function install_addon() {
1056 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
1057
1058 $download_url = self::get_current_plugin();
1059
1060 if ( ! self::url_is_allowed( $download_url ) ) {
1061 return array(
1062 'message' => 'Plugin URL is not valid',
1063 'success' => false,
1064 );
1065 }
1066
1067 // Create the plugin upgrader with our custom skin.
1068 $installer = new Plugin_Upgrader( new FrmInstallerSkin() );
1069 $installer->install( $download_url );
1070
1071 // Flush the cache and return the newly installed plugin basename.
1072 wp_cache_flush();
1073
1074 $plugin = $installer->plugin_info();
1075 if ( ! $plugin ) {
1076 return array(
1077 'message' => 'Plugin was not installed. ' . $installer->result,
1078 'success' => false,
1079 );
1080 }
1081 return $plugin;
1082 }
1083
1084 /**
1085 * Handle the AJAX request to activate an add-on.
1086 *
1087 * @since 6.8
1088 *
1089 * @return void
1090 */
1091 public static function ajax_activate_addon() {
1092 self::process_addon_action(
1093 function ( $plugin ) {
1094 return self::handle_addon_action( $plugin, 'activate' );
1095 },
1096 array( 'FrmAddonsController', 'get_addon_activation_response' )
1097 );
1098 }
1099
1100 /**
1101 * @since 3.04.02
1102 *
1103 * @param string $installed The plugin folder name with file name.
1104 */
1105 protected static function maybe_activate_addon( $installed ) {
1106 self::ajax_activate_addon();
1107 }
1108
1109 /**
1110 * Handle the AJAX request to deactivate an add-on.
1111 *
1112 * @since 6.8
1113 *
1114 * @return void
1115 */
1116 public static function ajax_deactivate_addon() {
1117 self::process_addon_action(
1118 function ( $plugin ) {
1119 return self::handle_addon_action( $plugin, 'deactivate' );
1120 }
1121 );
1122 }
1123
1124 /**
1125 * Handle the AJAX request to uninstall an add-on.
1126 *
1127 * @since 6.8
1128 *
1129 * @return void
1130 */
1131 public static function ajax_uninstall_addon() {
1132 self::process_addon_action(
1133 function ( $plugin ) {
1134 return self::handle_addon_action( $plugin, 'uninstall' );
1135 }
1136 );
1137 }
1138
1139 /**
1140 * Process a specific action (activate, deactivate, uninstall) on an add-on.
1141 *
1142 * @since 6.8
1143 *
1144 * @param callable $action_callback The specific add-on action to be executed.
1145 * @param callable|null $response_callback Optional. The response handling callback. Default null.
1146 * @return void
1147 */
1148 private static function process_addon_action( $action_callback, $response_callback = null ) {
1149 self::install_addon_permissions();
1150 FrmAppHelper::set_current_screen_and_hook_suffix();
1151
1152 $plugin = FrmAppHelper::get_param( 'plugin', '', 'post', 'sanitize_text_field' );
1153 call_user_func( $action_callback, $plugin );
1154
1155 if ( is_callable( $response_callback ) ) {
1156 wp_send_json_success( call_user_func( $response_callback ) );
1157 return;
1158 }
1159
1160 wp_send_json_success();
1161 }
1162
1163 /**
1164 * Attempt to perform a specific action (activate, deactivate, uninstall) on an add-on.
1165 *
1166 * @since 6.8
1167 *
1168 * @param string $installed The plugin folder name with file name.
1169 * @param string $action The action type ('activate', 'deactivate', 'uninstall').
1170 * @return array|void
1171 */
1172 protected static function handle_addon_action( $installed, $action ) {
1173 if ( ! $installed || ! $action ) {
1174 return;
1175 }
1176
1177 $result = null;
1178 switch ( $action ) {
1179 case 'activate':
1180 $result = self::activate_plugin( $installed );
1181 break;
1182 case 'deactivate':
1183 self::deactivate_plugin( $installed );
1184 break;
1185 case 'uninstall':
1186 $result = self::uninstall_plugin( $installed );
1187 break;
1188 }
1189
1190 if ( is_wp_error( $result ) ) {
1191 // Ignore the invalid header message that shows with nested plugins.
1192 if ( $result->get_error_code() !== 'no_plugin_header' ) {
1193 if ( wp_doing_ajax() ) {
1194 wp_send_json_error( array( 'error' => $result->get_error_message() ) );
1195 }
1196 return array(
1197 'message' => $result->get_error_message(),
1198 'success' => false,
1199 );
1200 }
1201 }
1202
1203 return $result;
1204 }
1205
1206 /**
1207 * @return array
1208 */
1209 private static function get_addon_activation_response() {
1210 $activating_page = self::get_activating_page();
1211
1212 $message = $activating_page ? __( 'Your plugin has been activated. Would you like to save and reload the page now?', 'formidable' ) : __( 'Your plugin has been activated.', 'formidable' );
1213
1214 $response = array(
1215 'message' => $message,
1216 'saveAndReload' => $activating_page,
1217 );
1218
1219 return $response;
1220 }
1221
1222 /**
1223 * Return a string that reflects the page from which the addon is being activated on,
1224 * if it is from settings or form builder, otherwise return empty string.
1225 *
1226 * @return string
1227 */
1228 private static function get_activating_page() {
1229 $referer = FrmAppHelper::get_server_value( 'HTTP_REFERER' );
1230 if ( false !== strpos( $referer, 'frm_action=settings' ) ) {
1231 return 'settings';
1232 }
1233
1234 if ( false !== strpos( $referer, 'frm_action=edit' ) ) {
1235 return 'form_builder';
1236 }
1237
1238 return '';
1239 }
1240
1241 /**
1242 * Run security checks before installing
1243 *
1244 * @since 3.04.02
1245 *
1246 * @return void
1247 */
1248 protected static function install_addon_permissions() {
1249 check_ajax_referer( 'frm_ajax', 'nonce' );
1250
1251 if ( ! current_user_can( 'activate_plugins' ) || ! self::get_current_plugin() ) {
1252 echo json_encode( true );
1253 wp_die();
1254 }
1255 }
1256
1257 /**
1258 * @since 4.08
1259 *
1260 * @return string
1261 */
1262 public static function connect_link() {
1263 $auth = get_option( 'frm_connect_token' );
1264 if ( empty( $auth ) ) {
1265 $auth = hash( 'sha512', wp_rand() );
1266 update_option( 'frm_connect_token', $auth, 'no' );
1267 }
1268 $page = FrmAppHelper::simple_get( 'page', 'sanitize_title', 'formidable-settings' );
1269 $link = 'https://formidableforms.com/api-connect/';
1270 $args = array(
1271 'v' => 2,
1272 'siteurl' => FrmAppHelper::site_url(),
1273 'url' => get_rest_url(),
1274 'inst' => (int) FrmAppHelper::pro_is_included(),
1275 'return' => $page,
1276 'token' => $auth,
1277 'l' => self::get_pro_license(),
1278 );
1279
1280 return add_query_arg( $args, $link );
1281 }
1282
1283 /**
1284 * Check the auth value for install permission.
1285 *
1286 * @since 4.08
1287 *
1288 * @return bool
1289 */
1290 public static function can_install_addon_api() {
1291 // Verify params present (auth & download link).
1292 $post_auth = FrmAppHelper::get_param( 'token', '', 'request', 'sanitize_text_field' );
1293 $post_url = FrmAppHelper::get_param( 'file_url', '', 'request', 'sanitize_text_field' );
1294
1295 // The download link is not required if already installed.
1296 $is_installed = FrmAppHelper::pro_is_included();
1297 $file_missing = ! $is_installed && empty( $post_url );
1298 if ( ! $post_auth || $file_missing ) {
1299 return false;
1300 }
1301
1302 // Verify auth.
1303 $auth = get_option( 'frm_connect_token' );
1304 if ( empty( $auth ) || ! hash_equals( $auth, $post_auth ) ) {
1305 return false;
1306 }
1307
1308 return true;
1309 }
1310
1311 /**
1312 * Install and/or activate the add-on file.
1313 *
1314 * @since 4.08
1315 *
1316 * @return array
1317 */
1318 public static function install_addon_api() {
1319 self::$plugin = FrmAppHelper::get_param( 'file_url', '', 'request', 'esc_url_raw' );
1320
1321 $error = esc_html__( 'Could not install an upgrade. Please download from formidableforms.com and install manually.', 'formidable' );
1322
1323 // Delete so cannot replay.
1324 delete_option( 'frm_connect_token' );
1325
1326 // It's already installed and active.
1327 $active = self::activate_plugin( 'formidable-pro/formidable-pro.php', false, false, true );
1328 if ( is_wp_error( $active ) ) {
1329 $response = self::maybe_download_and_activate();
1330 if ( is_array( $response ) ) {
1331 // The download failed.
1332 return $response;
1333 }
1334 }
1335
1336 // If empty license, save it now.
1337 if ( empty( self::get_pro_license() ) && function_exists( 'load_formidable_pro' ) ) {
1338 load_formidable_pro();
1339 $license = stripslashes( FrmAppHelper::get_param( 'key', '', 'request', 'sanitize_text_field' ) );
1340 if ( ! $license ) {
1341 return array(
1342 'success' => false,
1343 'error' => 'That site does not have a valid license key.',
1344 );
1345 }
1346
1347 $response = FrmAddon::activate_license_for_plugin( $license, 'formidable_pro' );
1348 if ( ! $response['success'] ) {
1349 // Could not activate license.
1350 return $response;
1351 }
1352 }
1353
1354 return array(
1355 'success' => true,
1356 );
1357 }
1358
1359 /**
1360 * @since 6.8.3
1361 *
1362 * @return array|true
1363 */
1364 private static function maybe_download_and_activate() {
1365 if ( ! self::$plugin ) {
1366 return array(
1367 'success' => false,
1368 'message' => __( 'The plugin download was not found.', 'formidable' ),
1369 );
1370 }
1371
1372 // Download plugin now.
1373 $response = self::download_and_activate();
1374 if ( is_array( $response ) && isset( $response['success'] ) ) {
1375 // The download failed.
1376 return $response;
1377 }
1378
1379 return true;
1380 }
1381
1382 /**
1383 * Render a conditional action button for a specified plugin
1384 *
1385 * @since 4.09
1386 *
1387 * @param string $plugin
1388 * @param array|string $upgrade_link_args
1389 * @return void
1390 */
1391 public static function conditional_action_button( $plugin, $upgrade_link_args ) {
1392 if ( is_callable( 'FrmProAddonsController::conditional_action_button' ) ) {
1393 FrmProAddonsController::conditional_action_button( $plugin, $upgrade_link_args );
1394 return;
1395 }
1396
1397 $addon = self::get_addon( $plugin );
1398 $upgrade_link = FrmAppHelper::admin_upgrade_link( $upgrade_link_args );
1399
1400 if ( ! is_array( $upgrade_link_args ) ) {
1401 // A string $upgrade_link_args is used for the utm-medium value when calling
1402 // FrmAppHelper::admin_upgrade_link above.
1403 // For self::addon_upgrade_link, we'll pass just an empty array with the link key (set below).
1404 $upgrade_link_args = array();
1405 }
1406
1407 $upgrade_link_args['link'] = $upgrade_link;
1408
1409 self::addon_upgrade_link( $addon, $upgrade_link_args );
1410 }
1411
1412 /**
1413 * Render a conditional action button for an add on
1414 *
1415 * @since 4.09.01
1416 *
1417 * @param array $atts {
1418 * Button attributes.
1419 *
1420 * @type array $addon
1421 * @type false|string $license_type
1422 * @type string $plan_required
1423 * @type string $upgrade_link
1424 * }
1425 * @return void
1426 */
1427 public static function show_conditional_action_button( $atts ) {
1428 if ( is_callable( 'FrmProAddonsController::show_conditional_action_button' ) ) {
1429 FrmProAddonsController::show_conditional_action_button( $atts );
1430 return;
1431 }
1432
1433 self::addon_upgrade_link( $atts['addon'], $atts['upgrade_link'] );
1434 }
1435
1436 /**
1437 * @since 4.09.01
1438 *
1439 * @param array|false $addon
1440 * @param array|string $upgrade_link
1441 *
1442 * @return void
1443 */
1444 protected static function addon_upgrade_link( $addon, $upgrade_link ) {
1445 $atts = is_array( $upgrade_link ) ? $upgrade_link : array();
1446 $upgrade_link = is_array( $upgrade_link ) ? $upgrade_link['link'] : $upgrade_link;
1447
1448 if ( $addon ) {
1449 $upgrade_link .= '&utm_content=' . $addon['slug'];
1450 }
1451
1452 if ( $addon && isset( $addon['categories'] ) && in_array( 'Solution', $addon['categories'], true ) ) {
1453 // Solutions will go to a separate page.
1454 $upgrade_link = FrmAppHelper::admin_upgrade_link( 'addons', $addon['link'] );
1455 }
1456
1457 $class = ! empty( $atts['class'] ) ? $atts['class'] : '';
1458 if ( strpos( $class, 'frm-button' ) === false ) {
1459 $class .= ' frm-button-secondary frm-button-sm';
1460 }
1461 ?>
1462 <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' ); ?>">
1463 <?php esc_html_e( 'Upgrade Now', 'formidable' ); ?>
1464 </a>
1465 <?php
1466 }
1467
1468 /**
1469 * @since 3.04.02
1470 *
1471 * @return void
1472 */
1473 public static function ajax_install_addon() {
1474 self::install_addon_permissions();
1475
1476 $result = self::download_and_activate();
1477 if ( isset( $result['success'] ) && ! $result['success'] ) {
1478 echo json_encode( $result );
1479 wp_die();
1480 }
1481
1482 echo json_encode( self::get_addon_activation_response() );
1483 wp_die();
1484 }
1485
1486 /**
1487 * Allowed URLs used for internal source of plugins installation.
1488 *
1489 * @since 6.3.1
1490 *
1491 * @return array
1492 */
1493 private static function allowed_external_urls() {
1494 $allowed_url_list = array(
1495 'https://downloads.wordpress.org/plugin/formidable-gravity-forms-importer.zip',
1496 'https://downloads.wordpress.org/plugin/formidable-import-pirate-forms.zip',
1497 'https://downloads.wordpress.org/plugin/wp-mail-smtp.zip',
1498 );
1499
1500 /**
1501 * List of URLs used in plugin formidable internal installation.
1502 *
1503 * @since 6.3.1
1504 *
1505 * @param array $allowed_url_list List of URLs.
1506 */
1507 $allowed_url_list = apply_filters( 'frm_allowed_external_urls', $allowed_url_list );
1508
1509 if ( ! is_array( $allowed_url_list ) ) {
1510 _doing_it_wrong( __METHOD__, 'Only an array of URLs could be used within this filter.', '6.3.1' );
1511
1512 return array();
1513 }
1514
1515 return $allowed_url_list;
1516 }
1517
1518 /**
1519 * Gets required plan for an addon.
1520 *
1521 * @since 6.4.2
1522 *
1523 * @return string Empty string if no plan is required for active license.
1524 */
1525 public static function get_addon_required_plan( $addon_id ) {
1526 $api = new FrmFormApi();
1527 $addons = $api->get_api_info();
1528
1529 if ( is_array( $addons ) && array_key_exists( $addon_id, $addons ) ) {
1530 $dates = $addons[ $addon_id ];
1531 $requires = FrmFormsHelper::get_plan_required( $dates );
1532 }
1533
1534 if ( ! isset( $requires ) || ! is_string( $requires ) ) {
1535 $requires = '';
1536 }
1537
1538 return $requires;
1539 }
1540
1541 /**
1542 * @since 4.02.05
1543 * @deprecated 6.8.3
1544 *
1545 * @codeCoverageIgnore
1546 *
1547 * @return void
1548 */
1549 public static function connect_pro() {
1550 _deprecated_function( __METHOD__, '6.8.3' );
1551 }
1552
1553 /**
1554 * @since 4.08
1555 * @deprecated 6.11.1
1556 *
1557 * @return bool|int false or the number of days until expiration.
1558 */
1559 public static function is_license_expiring() {
1560 _deprecated_function( __METHOD__, '6.11.1', 'FrmProAddonsController::is_license_expiring' );
1561
1562 if ( is_callable( 'FrmProAddonsController::is_license_expiring' ) ) {
1563 return FrmProAddonsController::is_license_expiring();
1564 }
1565
1566 return false;
1567 }
1568 }
1569