PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.0.08
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.0.08
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 5.0.08, at classes/controllers/FrmAddonsController.php

1,285 lines 35.0 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 public static function menu() {
9 if ( ! current_user_can( 'activate_plugins' ) ) {
10 return;
11 }
12
13 $label = __( 'Add-Ons', 'formidable' );
14 $label = '<span style="color:#fe5a1d">' . $label . '</span>';
15
16 add_submenu_page( 'formidable', 'Formidable | ' . __( 'Add-Ons', 'formidable' ), $label, 'frm_view_forms', 'formidable-addons', 'FrmAddonsController::list_addons' );
17
18 if ( ! FrmAppHelper::pro_is_installed() ) {
19 add_submenu_page(
20 'formidable',
21 'Formidable | ' . __( 'Upgrade', 'formidable' ),
22 '<span class="frm-upgrade-submenu">' . __( 'Upgrade', 'formidable' ) . '</span>',
23 'frm_view_forms',
24 'formidable-pro-upgrade',
25 'FrmAddonsController::upgrade_to_pro'
26 );
27 } elseif ( 'formidable-pro-upgrade' === FrmAppHelper::get_param( 'page' ) ) {
28 wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
29 exit;
30 }
31 }
32
33 public static function list_addons() {
34 FrmAppHelper::include_svg();
35 $installed_addons = apply_filters( 'frm_installed_addons', array() );
36 $license_type = '';
37
38 $addons = self::get_api_addons();
39 $errors = array();
40
41 if ( isset( $addons['error'] ) ) {
42 $api = new FrmFormApi();
43 $errors = $api->get_error_from_response( $addons );
44 $license_type = isset( $addons['error']['type'] ) ? $addons['error']['type'] : '';
45 unset( $addons['error'] );
46 }
47
48 $pro = array(
49 'pro' => array(
50 'title' => 'Formidable Forms Pro',
51 'slug' => 'formidable-pro',
52 'released' => '2011-02-05',
53 'docs' => 'knowledgebase/',
54 'excerpt' => 'Create calculators, surveys, smart forms, and data-driven applications. Build directories, real estate listings, job boards, and much more.',
55 ),
56 );
57 $addons = $pro + $addons;
58 self::prepare_addons( $addons );
59
60 $pricing = FrmAppHelper::admin_upgrade_link( 'addons' );
61
62 include( FrmAppHelper::plugin_path() . '/classes/views/addons/list.php' );
63 }
64
65 public static function license_settings() {
66 $plugins = apply_filters( 'frm_installed_addons', array() );
67 if ( empty( $plugins ) ) {
68 esc_html_e( 'There are no plugins on your site that require a license', 'formidable' );
69
70 return;
71 }
72
73 ksort( $plugins );
74
75 include( FrmAppHelper::plugin_path() . '/classes/views/addons/settings.php' );
76 }
77
78 protected static function get_api_addons() {
79 $api = new FrmFormApi();
80 $addons = $api->get_api_info();
81
82 if ( empty( $addons ) ) {
83 $addons = self::fallback_plugin_list();
84 } else {
85 foreach ( $addons as $k => $addon ) {
86 if ( empty( $addon['excerpt'] ) && $k !== 'error' ) {
87 unset( $addons[ $k ] );
88 }
89 }
90 }
91
92 return $addons;
93 }
94
95 /**
96 * If the API is unable to connect, show something on the addons page
97 *
98 * @since 3.04.03
99 * @return array
100 */
101 protected static function fallback_plugin_list() {
102 $list = array(
103 'formidable-pro' => array(
104 'title' => 'Formidable Forms Pro',
105 'link' => 'pricing/',
106 'docs' => '',
107 'excerpt' => 'Enhance your basic Formidable forms with a plethora of Pro field types and features. Create advanced forms and data-driven applications in minutes.',
108 ),
109 'mailchimp' => array(
110 'title' => 'MailChimp Forms',
111 '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.',
112 ),
113 'registration' => array(
114 'title' => 'User Registration Forms',
115 'link' => 'downloads/user-registration/',
116 '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.',
117 ),
118 'paypal' => array(
119 'title' => 'PayPal Standard Forms',
120 'link' => 'downloads/paypal-standard/',
121 '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.',
122 ),
123 'stripe' => array(
124 'title' => 'Stripe Forms',
125 'docs' => 'knowledgebase/stripe/',
126 'excerpt' => 'Any Formidable forms on your site can accept credit card payments without users ever leaving your site.',
127 ),
128 'authorize-net' => array(
129 'title' => 'Authorize.net AIM Forms',
130 'link' => 'downloads/authorize-net-aim/',
131 'docs' => 'knowledgebase/authorize-net-aim/',
132 'excerpt' => 'Accept one-time payments directly on your site, using Authorize.net AIM.',
133 ),
134 'woocommerce' => array(
135 'title' => 'WooCommerce Forms',
136 'excerpt' => 'Use a Formidable form on your WooCommerce product pages.',
137 ),
138 'autoresponder' => array(
139 'title' => 'Form Action Automation',
140 'docs' => 'knowledgebase/schedule-autoresponder/',
141 'excerpt' => 'Schedule email notifications, SMS messages, and API actions.',
142 ),
143 'modal' => array(
144 'title' => 'Bootstrap Modal Forms',
145 'link' => 'downloads/bootstrap-modal/',
146 'docs' => 'knowledgebase/bootstrap-modal/',
147 'excerpt' => 'Open a view or form in a Bootstrap popup.',
148 ),
149 'bootstrap' => array(
150 'title' => 'Bootstrap Style Forms',
151 'excerpt' => 'Instantly add Bootstrap styling to all your Formidable forms.',
152 ),
153 'zapier' => array(
154 'title' => 'Zapier Forms',
155 '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.',
156 ),
157 'signature' => array(
158 'title' => 'Digital Signature Forms',
159 'excerpt' => 'Add a signature field to your form. The user may write their signature with a trackpad/mouse or just type it.',
160 ),
161 'api' => array(
162 'title' => 'Formidable Forms API',
163 'link' => 'downloads/formidable-api/',
164 '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.',
165 ),
166 'twilio' => array(
167 'title' => 'Twilio SMS Forms',
168 'docs' => 'knowledgebase/twilio-add-on/',
169 'excerpt' => 'Allow users to text their votes for polls created by Formidable Forms, or send SMS notifications when entries are submitted or updated.',
170 ),
171 'views' => array(
172 'title' => 'Formidable Views',
173 'excerpt' => 'Add the power of views to your Formidable Forms to display your form submissions in listings, tables, calendars, and more.',
174 ),
175 );
176
177 $defaults = array(
178 'released' => '',
179 );
180
181 foreach ( $list as $k => $info ) {
182 $info['slug'] = $k;
183 $list[ $k ] = array_merge( $defaults, $info );
184 }
185 return $list;
186 }
187
188 /**
189 * If Pro is missing but has been authenticated, include a download URL
190 *
191 * @since 3.04.03
192 * @return string
193 */
194 public static function get_pro_download_url() {
195 $license = self::get_pro_license();
196 $api = new FrmFormApi( $license );
197 $downloads = $api->get_api_info();
198 $pro = self::get_pro_from_addons( $downloads );
199
200 return isset( $pro['url'] ) ? $pro['url'] : '';
201 }
202
203 /**
204 * @since 4.08
205 */
206 public static function get_pro_license() {
207 $pro_cred_store = 'frmpro-credentials';
208 $pro_wpmu_store = 'frmpro-wpmu-sitewide';
209 if ( is_multisite() && get_site_option( $pro_wpmu_store ) ) {
210 $creds = get_site_option( $pro_cred_store );
211 } else {
212 $creds = get_option( $pro_cred_store );
213 }
214
215 if ( empty( $creds ) || ! is_array( $creds ) || ! isset( $creds['license'] ) ) {
216 return '';
217 }
218
219 $license = $creds['license'];
220 if ( empty( $license ) ) {
221 return '';
222 }
223
224 if ( strpos( $license, '-' ) ) {
225 // this is a fix for licenses saved in the past
226 $license = strtoupper( $license );
227 }
228 return $license;
229 }
230
231 /**
232 * @since 4.08
233 */
234 protected static function get_pro_from_addons( $addons ) {
235 return isset( $addons['93790'] ) ? $addons['93790'] : array();
236 }
237
238 /**
239 * @since 4.06
240 */
241 public static function license_type() {
242 if ( is_callable( 'FrmProAddonsController::license_type' ) ) {
243 return FrmProAddonsController::license_type();
244 }
245
246 return 'free';
247 }
248
249 /**
250 * @since 4.0.01
251 */
252 public static function is_license_expired() {
253 $version_info = self::get_primary_license_info();
254 if ( ! isset( $version_info['error'] ) ) {
255 return false;
256 }
257
258 return $version_info['error'];
259 }
260
261 /**
262 * @since 4.08
263 *
264 * @return boolean|int false or the number of days until expiration.
265 */
266 public static function is_license_expiring() {
267 if ( is_callable( 'FrmProAddonsController::is_license_expiring' ) ) {
268 return FrmProAddonsController::is_license_expiring();
269 }
270
271 return false;
272 }
273
274 /**
275 * @since 4.08
276 */
277 protected static function get_primary_license_info() {
278 $installed_addons = apply_filters( 'frm_installed_addons', array() );
279 if ( empty( $installed_addons ) || ! isset( $installed_addons['formidable_pro'] ) ) {
280 return false;
281 }
282 $installed_addons = array(
283 'formidable_pro' => $installed_addons['formidable_pro'],
284 );
285
286 return self::fill_update_addon_info( $installed_addons );
287 }
288
289 /**
290 * @since 3.04.03
291 */
292 public static function check_update( $transient ) {
293 if ( ! FrmAppHelper::pro_is_installed() ) {
294 // Don't make any changes if only Lite is installed.
295 return $transient;
296 }
297
298 if ( ! is_object( $transient ) ) {
299 $transient = new stdClass();
300 }
301
302 $installed_addons = apply_filters( 'frm_installed_addons', array() );
303 if ( empty( $installed_addons ) ) {
304 return $transient;
305 }
306
307 $version_info = self::fill_update_addon_info( $installed_addons );
308
309 $transient->last_checked = time();
310
311 if ( ! function_exists( 'get_plugins' ) ) {
312 require_once ABSPATH . 'wp-admin/includes/plugin.php';
313 }
314 $wp_plugins = get_plugins();
315
316 foreach ( $version_info as $id => $plugin ) {
317 $plugin = (object) $plugin;
318
319 if ( ! isset( $plugin->new_version ) || ! isset( $plugin->package ) ) {
320 continue;
321 }
322
323 $folder = $plugin->plugin;
324 if ( empty( $folder ) ) {
325 continue;
326 }
327
328 if ( ! self::is_installed( $folder ) ) {
329 // don't show an update if the plugin isn't installed
330 continue;
331 }
332
333 $wp_plugin = isset( $wp_plugins[ $folder ] ) ? $wp_plugins[ $folder ] : array();
334 $wp_version = isset( $wp_plugin['Version'] ) ? $wp_plugin['Version'] : '1.0';
335
336 if ( version_compare( $wp_version, $plugin->new_version, '<' ) ) {
337 $slug = explode( '/', $folder );
338 $plugin->slug = $slug[0];
339 $transient->response[ $folder ] = $plugin;
340 }
341
342 $transient->checked[ $folder ] = $wp_version;
343
344 }
345
346 return $transient;
347 }
348
349 /**
350 * Check if a plugin is installed before showing an update for it
351 *
352 * @since 3.05
353 *
354 * @param string $plugin - the folder/filename.php for a plugin
355 *
356 * @return bool - True if installed
357 */
358 protected static function is_installed( $plugin ) {
359 if ( ! function_exists( 'get_plugins' ) ) {
360 require_once ABSPATH . 'wp-admin/includes/plugin.php';
361 }
362
363 $all_plugins = get_plugins();
364
365 return isset( $all_plugins[ $plugin ] );
366 }
367
368 /**
369 * @since 3.04.03
370 *
371 * @param array $installed_addons
372 *
373 * @return array
374 */
375 protected static function fill_update_addon_info( $installed_addons ) {
376 $checked_licenses = array();
377 $version_info = array();
378
379 foreach ( $installed_addons as $addon ) {
380 if ( $addon->store_url !== 'https://formidableforms.com' ) {
381 // check if this is a third-party addon
382 continue;
383 }
384
385 $new_license = $addon->license;
386 if ( empty( $new_license ) || in_array( $new_license, $checked_licenses ) ) {
387 continue;
388 }
389
390 $checked_licenses[] = $new_license;
391
392 $api = new FrmFormApi( $new_license );
393 if ( empty( $version_info ) ) {
394 $version_info = $api->get_api_info();
395 continue;
396 }
397
398 $plugin = $api->get_addon_for_license( $addon, $version_info );
399 if ( empty( $plugin ) ) {
400 continue;
401 }
402
403 $download_id = isset( $plugin['id'] ) ? $plugin['id'] : 0;
404 if ( ! empty( $download_id ) && ! isset( $version_info[ $download_id ]['package'] ) ) {
405 // if this addon is using its own license, get the update url
406 $addon_info = $api->get_api_info();
407
408 $version_info[ $download_id ] = $addon_info[ $download_id ];
409 if ( isset( $addon_info['error'] ) ) {
410 $version_info[ $download_id ]['error'] = array(
411 'message' => $addon_info['error']['message'],
412 'code' => $addon_info['error']['code'],
413 );
414 }
415 }
416 }
417
418 return $version_info;
419 }
420
421 /**
422 * Get the action link for an addon that isn't active.
423 *
424 * @since 3.06.03
425 * @param string $plugin The plugin slug
426 * @return array
427 */
428 public static function install_link( $plugin ) {
429 $link = array();
430 $addon = self::get_addon( $plugin );
431
432 if ( $addon ) {
433 if ( $addon['status']['type'] === 'installed' && ! empty( $addon['activate_url'] ) ) {
434 $link = array(
435 'url' => $addon['plugin'],
436 'class' => 'frm-activate-addon',
437 );
438 } elseif ( isset( $addon['url'] ) && ! empty( $addon['url'] ) ) {
439 $link = array(
440 'url' => $addon['url'],
441 'class' => 'frm-install-addon',
442 );
443 } elseif ( isset( $addon['categories'] ) && ! empty( $addon['categories'] ) ) {
444 $link = array(
445 'categories' => $addon['categories'],
446 );
447 }
448
449 if ( ! empty( $link ) ) {
450 $link['status'] = $addon['status']['type'];
451 }
452 }
453
454 return $link;
455 }
456
457 /**
458 * @since 4.09
459 * @param string $plugin The plugin slug
460 * @return array|false
461 */
462 protected static function get_addon( $plugin ) {
463 $addons = self::get_api_addons();
464 self::prepare_addons( $addons );
465 foreach ( $addons as $addon ) {
466 $slug = explode( '/', $addon['plugin'] );
467 if ( $slug[0] === 'formidable-' . $plugin ) {
468 return $addon;
469 }
470 }
471 return false;
472 }
473
474 /**
475 * @since 4.09
476 * @return string
477 */
478 protected static function get_license_type() {
479 $license_type = '';
480 $addons = self::get_api_addons();
481 if ( isset( $addons['error'] ) && isset( $addons['error']['type'] ) ) {
482 $license_type = $addons['error']['type'];
483 }
484 return $license_type;
485 }
486
487 /**
488 * @since 3.04.03
489 *
490 * @param array $addons
491 * @param object $license The FrmAddon object
492 *
493 * @return array
494 */
495 public static function get_addon_for_license( $addons, $license ) {
496 $download_id = $license->download_id;
497 $plugin = array();
498 if ( empty( $download_id ) && ! empty( $addons ) ) {
499 foreach ( $addons as $addon ) {
500 if ( strtolower( $license->plugin_name ) == strtolower( $addon['title'] ) ) {
501 return $addon;
502 }
503 }
504 } elseif ( isset( $addons[ $download_id ] ) ) {
505 $plugin = $addons[ $download_id ];
506 }
507
508 return $plugin;
509 }
510
511 protected static function prepare_addons( &$addons ) {
512 $activate_url = '';
513 if ( current_user_can( 'activate_plugins' ) ) {
514 $activate_url = add_query_arg( array( 'action' => 'activate' ), admin_url( 'plugins.php' ) );
515 }
516
517 $loop_addons = $addons;
518 foreach ( $loop_addons as $id => $addon ) {
519 if ( is_numeric( $id ) ) {
520 $slug = str_replace( array( '-wordpress-plugin', '-wordpress' ), '', $addon['slug'] );
521 $file_name = $addon['plugin'];
522 } else {
523 $slug = $id;
524 if ( isset( $addon['file'] ) ) {
525 $base_file = $addon['file'];
526 } else {
527 $base_file = 'formidable-' . $slug;
528 }
529 $file_name = $base_file . '/' . $base_file . '.php';
530 if ( ! isset( $addon['plugin'] ) ) {
531 $addon['plugin'] = $file_name;
532 }
533 }
534
535 $addon['installed'] = self::is_installed( $file_name );
536 if ( $addon['installed'] && 'formidable-views/formidable-views.php' === $file_name ) {
537 $active_views_version = self::get_active_views_version();
538 if ( false !== $active_views_version && $slug !== $active_views_version ) {
539 $addon['installed'] = false;
540 }
541 }
542
543 $addon['activate_url'] = '';
544
545 if ( $addon['installed'] && ! empty( $activate_url ) && ! self::is_plugin_active( $file_name, $slug ) ) {
546 $addon['activate_url'] = add_query_arg(
547 array(
548 '_wpnonce' => wp_create_nonce( 'activate-plugin_' . $file_name ),
549 'plugin' => $file_name,
550 ),
551 $activate_url
552 );
553 }
554
555 if ( ! isset( $addon['docs'] ) ) {
556 $addon['docs'] = 'knowledgebase/formidable-' . $slug . '/';
557 }
558 self::prepare_addon_link( $addon['docs'] );
559
560 if ( ! isset( $addon['link'] ) ) {
561 $addon['link'] = 'downloads/' . $slug . '/';
562 }
563 self::prepare_addon_link( $addon['link'] );
564
565 self::set_addon_status( $addon );
566 $addons[ $id ] = $addon;
567 }
568 }
569
570 private static function is_plugin_active( $file_name, $slug ) {
571 if ( 'formidable-views/formidable-views.php' === $file_name ) {
572 return self::get_active_views_version() === $slug;
573 }
574 return is_plugin_active( $file_name );
575 }
576
577 /**
578 * @return string|false either 'visual-views' or 'views', false if one is not found.
579 */
580 private static function get_active_views_version() {
581 if ( ! is_callable( 'FrmViewsAppHelper::plugin_version' ) ) {
582 return false;
583 }
584 $plugin_version = FrmViewsAppHelper::plugin_version();
585 return version_compare( $plugin_version, '5.0', '>=' ) ? 'visual-views' : 'views';
586 }
587
588 /**
589 * @since 3.04.02
590 */
591 protected static function prepare_addon_link( &$link ) {
592 $site_url = 'https://formidableforms.com/';
593 if ( strpos( $link, 'http' ) !== 0 ) {
594 $link = $site_url . $link;
595 }
596 $link = FrmAppHelper::make_affiliate_url( $link );
597 $query_args = array(
598 'utm_source' => 'WordPress',
599 'utm_medium' => 'addons',
600 'utm_campaign' => 'liteplugin',
601 );
602 $link = add_query_arg( $query_args, $link );
603 }
604
605 /**
606 * Add the status to the addon array. Status options are:
607 * installed, active, not installed
608 *
609 * @since 3.04.02
610 */
611 protected static function set_addon_status( &$addon ) {
612 if ( ! empty( $addon['activate_url'] ) ) {
613 $addon['status'] = array(
614 'type' => 'installed',
615 'label' => __( 'Installed', 'formidable' ),
616 );
617 } elseif ( $addon['installed'] ) {
618 $addon['status'] = array(
619 'type' => 'active',
620 'label' => __( 'Active', 'formidable' ),
621 );
622 } else {
623 $addon['status'] = array(
624 'type' => 'not-installed',
625 'label' => __( 'Not Installed', 'formidable' ),
626 );
627 }
628 }
629
630 public static function upgrade_to_pro() {
631 FrmAppHelper::include_svg();
632
633 $link_parts = array(
634 'medium' => 'upgrade',
635 'content' => 'button',
636 );
637
638 $features = array(
639 'Display Entries' => array(
640 array(
641 'label' => 'Display form data with virtually limitless views',
642 'link' => array(
643 'content' => 'views',
644 'param' => 'views-display-form-data',
645 ),
646 'lite' => false,
647 ),
648 array(
649 'label' => 'Generate graphs and stats based on your submitted data',
650 'link' => array(
651 'content' => 'graphs',
652 'param' => 'statistics-graphs-wordpress-forms',
653 ),
654 'lite' => false,
655 ),
656 ),
657 'Entry Management' => array(
658 array(
659 'label' => 'Import entries from a CSV',
660 'link' => array(
661 'content' => 'import-entries',
662 'param' => 'importing-exporting-wordpress-forms',
663 ),
664 'lite' => false,
665 ),
666 array(
667 'label' => 'Logged-in users can save drafts and return later',
668 'link' => array(
669 'content' => 'save-drafts',
670 'param' => 'save-drafts-wordpress-form',
671 ),
672 'lite' => false,
673 ),
674 array(
675 'label' => 'Flexibly and powerfully view, edit, and delete entries from anywhere on your site',
676 'link' => array(
677 'content' => 'front-edit',
678 'param' => 'wordpress-front-end-editing',
679 ),
680 'lite' => false,
681 ),
682 array(
683 'label' => 'View form submissions from the back-end',
684 'lite' => true,
685 ),
686 array(
687 'label' => 'Export your entries to a CSV',
688 'lite' => true,
689 ),
690 ),
691 'Form Building' => array(
692 array(
693 'label' => 'Save a calculated value into a field',
694 'link' => array(
695 'content' => 'calculations',
696 'param' => 'field-calculations-wordpress-form',
697 ),
698 'lite' => false,
699 ),
700 array(
701 'label' => 'Allow multiple file uploads',
702 'link' => array(
703 'content' => 'file-uploads',
704 'param' => 'wordpress-multi-file-upload-fields',
705 ),
706 'lite' => false,
707 ),
708 array(
709 'label' => 'Repeat sections of fields',
710 'link' => array(
711 'content' => 'repeaters',
712 'param' => 'repeatable-sections-forms',
713 ),
714 'lite' => false,
715 ),
716 array(
717 'label' => 'Hide and show fields conditionally based on other fields or the user\'s role',
718 'link' => array(
719 'content' => 'conditional-logic',
720 'param' => 'conditional-logic-wordpress-forms',
721 ),
722 'lite' => false,
723 ),
724 array(
725 'label' => 'Confirmation fields',
726 'link' => array(
727 'content' => 'confirmation-fields',
728 'param' => 'confirmation-fields-wordpress-forms',
729 ),
730 'lite' => false,
731 ),
732 array(
733 'label' => 'Multi-paged forms',
734 'link' => array(
735 'content' => 'page-breaks',
736 'param' => 'wordpress-multi-page-forms',
737 ),
738 'lite' => false,
739 ),
740 array(
741 '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.',
742 'lite' => false,
743 ),
744 array(
745 'label' => 'Include text, email, url, paragraph text, radio, checkbox, dropdown fields, hidden fields, user ID fields, and HTML blocks in your form.',
746 'lite' => true,
747 ),
748 array(
749 'label' => 'Drag & Drop Form building',
750 'link' => array(
751 'content' => 'drag-drop',
752 'param' => 'drag-drop-forms',
753 ),
754 'lite' => true,
755 ),
756 array(
757 'label' => 'Create forms from Templates',
758 'link' => array(
759 'content' => 'form-templates',
760 'param' => 'wordpress-form-templates',
761 ),
762 'lite' => true,
763 ),
764 array(
765 'label' => 'Import and export forms with XML',
766 'link' => array(
767 'content' => 'import',
768 'param' => 'importing-exporting-wordpress-forms',
769 ),
770 'lite' => true,
771 ),
772 array(
773 'label' => 'Use input placeholder text in your fields that clear when typing starts.',
774 'lite' => true,
775 ),
776 ),
777 'Form Actions' => array(
778 array(
779 'label' => 'Conditionally send your email notifications based on values in your form',
780 'link' => array(
781 'content' => 'conditional-emails',
782 ),
783 'lite' => false,
784 ),
785 array(
786 'label' => 'Create and edit WordPress posts or custom posts from the front-end',
787 'link' => array(
788 'content' => 'create-posts',
789 'param' => 'create-posts-pages-wordpress-forms',
790 ),
791 'lite' => false,
792 ),
793 array(
794 'label' => 'Send multiple emails and autoresponders',
795 'link' => array(
796 'content' => 'multiple-emails',
797 'param' => 'virtually-unlimited-emails',
798 ),
799 'lite' => true,
800 ),
801 ),
802 'Form Appearance' => array(
803 array(
804 'label' => 'Create Multiple styles for different forms',
805 'link' => array(
806 'content' => 'multiple-styles',
807 'param' => 'wordpress-visual-form-styler',
808 ),
809 'lite' => false,
810 ),
811 array(
812 'label' => 'Customizable layout with CSS classes',
813 'link' => array(
814 'content' => 'form-layout',
815 'param' => 'wordpress-mobile-friendly-forms',
816 ),
817 'lite' => true,
818 ),
819 array(
820 'label' => 'Customize the HTML for your forms',
821 'link' => array(
822 'content' => 'custom-html',
823 'param' => 'customizable-html-wordpress-form',
824 ),
825 'lite' => true,
826 ),
827 array(
828 'label' => 'Style your form with the Visual Form Styler',
829 'lite' => true,
830 ),
831 ),
832 );
833
834 include( FrmAppHelper::plugin_path() . '/classes/views/addons/upgrade_to_pro.php' );
835 }
836
837 /**
838 * Install Pro after connection with Formidable.
839 *
840 * @since 4.02.05
841 */
842 public static function connect_pro() {
843 FrmAppHelper::permission_check( 'install_plugins' );
844 check_ajax_referer( 'frm_ajax', 'nonce' );
845
846 $url = FrmAppHelper::get_post_param( 'plugin', '', 'sanitize_text_field' );
847 if ( FrmAppHelper::pro_is_installed() || empty( $url ) ) {
848 wp_die();
849 }
850
851 $response = array();
852
853 // It's already installed and active.
854 $active = activate_plugin( 'formidable-pro/formidable-pro.php', false, false, true );
855 if ( is_wp_error( $active ) ) {
856 // The plugin was installed, but not active. Download it now.
857 self::ajax_install_addon();
858 } else {
859 $response['active'] = true;
860 $response['success'] = true;
861 }
862
863 echo json_encode( $response );
864 wp_die();
865 }
866
867 /**
868 * @since 4.08
869 */
870 protected static function download_and_activate() {
871 // Set the current screen to avoid undefined notices.
872 if ( is_admin() ) {
873 global $hook_suffix;
874 set_current_screen();
875 }
876
877 self::maybe_show_cred_form();
878
879 $installed = self::install_addon();
880 if ( is_array( $installed ) && isset( $installed['message'] ) ) {
881 return $installed;
882 }
883 self::maybe_activate_addon( $installed );
884 }
885
886 /**
887 * @since 3.04.02
888 */
889 protected static function maybe_show_cred_form() {
890 if ( ! function_exists( 'request_filesystem_credentials' ) ) {
891 include_once( ABSPATH . 'wp-admin/includes/file.php' );
892 }
893
894 // Start output bufferring to catch the filesystem form if credentials are needed.
895 ob_start();
896
897 $show_form = false;
898 $method = '';
899 $url = add_query_arg( array( 'page' => 'formidable-settings' ), admin_url( 'admin.php' ) );
900 $url = esc_url_raw( $url );
901 $creds = request_filesystem_credentials( $url, $method, false, false, null );
902
903 if ( false === $creds ) {
904 $show_form = true;
905 } elseif ( ! WP_Filesystem( $creds ) ) {
906 request_filesystem_credentials( $url, $method, true, false, null );
907 $show_form = true;
908 }
909
910 if ( $show_form ) {
911 $form = ob_get_clean();
912 $message = __( 'Sorry, your site requires FTP authentication. Please download plugins from FormidableForms.com and install them manually.', 'formidable' );
913 $data = $form;
914 $response = array(
915 'success' => false,
916 'message' => $message,
917 'form' => $form,
918 );
919 wp_send_json( $response );
920 }
921
922 ob_end_clean();
923 }
924
925 /**
926 * We do not need any extra credentials if we have gotten this far,
927 * so let's install the plugin.
928 *
929 * @since 3.04.02
930 */
931 protected static function install_addon() {
932 require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
933
934 $download_url = FrmAppHelper::get_param( 'plugin', '', 'post', 'esc_url_raw' );
935
936 // Create the plugin upgrader with our custom skin.
937 $installer = new Plugin_Upgrader( new FrmInstallerSkin() );
938 $installer->install( $download_url );
939
940 // Flush the cache and return the newly installed plugin basename.
941 wp_cache_flush();
942
943 $plugin = $installer->plugin_info();
944 if ( empty( $plugin ) ) {
945 return array(
946 'message' => 'Plugin was not installed. ' . $installer->result,
947 'success' => false,
948 );
949 }
950 return $plugin;
951 }
952
953 /**
954 * @since 3.06.03
955 */
956 public static function ajax_activate_addon() {
957
958 self::install_addon_permissions();
959
960 // Set the current screen to avoid undefined notices.
961 global $hook_suffix;
962 set_current_screen();
963
964 $plugin = FrmAppHelper::get_param( 'plugin', '', 'post', 'sanitize_text_field' );
965 self::maybe_activate_addon( $plugin );
966
967 echo json_encode( self::get_addon_activation_response() );
968 wp_die();
969 }
970
971 /**
972 * @return array|string
973 */
974 private static function get_addon_activation_response() {
975 if ( self::activating_from_settings_page() ) {
976 $response = array(
977 'message' => __( 'Your plugin has been activated. Would you like to save and reload the page now?', 'formidable' ),
978 'saveAndReload' => 'settings',
979 );
980 } else {
981 $response = __( 'Your plugin has been activated. Please reload the page to see more options.', 'formidable' );
982 }
983 return $response;
984 }
985
986 /**
987 * @return bool
988 */
989 private static function activating_from_settings_page() {
990 return false !== strpos( FrmAppHelper::get_server_value( 'HTTP_REFERER' ), 'frm_action=settings' );
991 }
992
993 /**
994 * @since 3.04.02
995 * @param string $installed The plugin folder name with file name
996 */
997 protected static function maybe_activate_addon( $installed ) {
998 if ( ! $installed ) {
999 return;
1000 }
1001
1002 $activate = activate_plugin( $installed );
1003 if ( is_wp_error( $activate ) ) {
1004 // Ignore the invalid header message that shows with nested plugins.
1005 if ( $activate->get_error_code() !== 'no_plugin_header' ) {
1006 if ( wp_doing_ajax() ) {
1007 echo json_encode( array( 'error' => $activate->get_error_message() ) );
1008 wp_die();
1009 }
1010 return array(
1011 'message' => $activate->get_error_message(),
1012 'success' => false,
1013 );
1014 }
1015 }
1016 }
1017
1018 /**
1019 * Run security checks before installing
1020 *
1021 * @since 3.04.02
1022 */
1023 protected static function install_addon_permissions() {
1024 check_ajax_referer( 'frm_ajax', 'nonce' );
1025
1026 if ( ! current_user_can( 'activate_plugins' ) || ! isset( $_POST['plugin'] ) ) {
1027 echo json_encode( true );
1028 wp_die();
1029 }
1030 }
1031
1032 /**
1033 * @since 4.08
1034 */
1035 public static function connect_link() {
1036 $auth = get_option( 'frm_connect_token' );
1037 if ( empty( $auth ) ) {
1038 $auth = hash( 'sha512', wp_rand() );
1039 update_option( 'frm_connect_token', $auth );
1040 }
1041 $link = FrmAppHelper::admin_upgrade_link( 'connect', 'api-connect' );
1042 $args = array(
1043 'v' => 2,
1044 'siteurl' => FrmAppHelper::site_url(),
1045 'url' => get_rest_url(),
1046 'token' => $auth,
1047 'l' => self::get_pro_license(),
1048 );
1049
1050 return add_query_arg( $args, $link );
1051 }
1052
1053 /**
1054 * Check the auth value for install permission.
1055 *
1056 * @since 4.08
1057 *
1058 * @return bool
1059 */
1060 public static function can_install_addon_api() {
1061 // Verify params present (auth & download link).
1062 $post_auth = FrmAppHelper::get_param( 'token', '', 'request', 'sanitize_text_field' );
1063 $post_url = FrmAppHelper::get_param( 'file_url', '', 'request', 'sanitize_text_field' );
1064
1065 if ( empty( $post_auth ) || empty( $post_url ) ) {
1066 return false;
1067 }
1068
1069 // Verify auth.
1070 $auth = get_option( 'frm_connect_token' );
1071 if ( empty( $auth ) || ! hash_equals( $auth, $post_auth ) ) {
1072 return false;
1073 }
1074
1075 return true;
1076 }
1077
1078 /**
1079 * Install and/or activate the add-on file.
1080 *
1081 * @since 4.08
1082 */
1083 public static function install_addon_api() {
1084 // Sanitize when it's used to prevent double sanitizing.
1085 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
1086 $_POST['plugin'] = isset( $_REQUEST['file_url'] ) ? $_REQUEST['file_url'] : ''; // Set for later use
1087
1088 $error = esc_html__( 'Could not install an upgrade. Please download from formidableforms.com and install manually.', 'formidable' );
1089
1090 // Delete so cannot replay.
1091 delete_option( 'frm_connect_token' );
1092
1093 // It's already installed and active.
1094 $active = activate_plugin( 'formidable-pro/formidable-pro.php', false, false, true );
1095 if ( is_wp_error( $active ) ) {
1096 // Download plugin now.
1097 $response = self::download_and_activate();
1098 if ( is_array( $response ) && isset( $response['success'] ) ) {
1099 return $response;
1100 }
1101 }
1102
1103 // If empty license, save it now.
1104 if ( empty( self::get_pro_license() ) && function_exists( 'load_formidable_pro' ) ) {
1105 load_formidable_pro();
1106 $license = stripslashes( FrmAppHelper::get_param( 'key', '', 'request', 'sanitize_text_field' ) );
1107 if ( empty( $license ) ) {
1108 return array(
1109 'success' => false,
1110 'error' => 'That site does not have a valid license key.',
1111 );
1112 }
1113
1114 $response = FrmAddon::activate_license_for_plugin( $license, 'formidable_pro' );
1115 if ( ! $response['success'] ) {
1116 // Could not activate license.
1117 return $response;
1118 }
1119 }
1120
1121 return array(
1122 'success' => true,
1123 );
1124 }
1125
1126 /**
1127 * Render a conditional action button for a specified plugin
1128 *
1129 * @param string $plugin
1130 * @param array|string $upgrade_link_args
1131 * @since 4.09
1132 */
1133 public static function conditional_action_button( $plugin, $upgrade_link_args ) {
1134 if ( is_callable( 'FrmProAddonsController::conditional_action_button' ) ) {
1135 return FrmProAddonsController::conditional_action_button( $plugin, $upgrade_link_args );
1136 }
1137
1138 $addon = self::get_addon( $plugin );
1139 $upgrade_link = FrmAppHelper::admin_upgrade_link( $upgrade_link_args );
1140 self::addon_upgrade_link( $addon, $upgrade_link );
1141 }
1142
1143 /**
1144 * Render a conditional action button for an add on
1145 *
1146 * @since 4.09.01
1147 * @param array $addon
1148 * @param string|false $license_type
1149 * @param string $plan_required
1150 * @param string $upgrade_link
1151 */
1152 public static function show_conditional_action_button( $atts ) {
1153 if ( is_callable( 'FrmProAddonsController::show_conditional_action_button' ) ) {
1154 return FrmProAddonsController::show_conditional_action_button( $atts );
1155 }
1156
1157 self::addon_upgrade_link( $atts['addon'], $atts['upgrade_link'] );
1158 }
1159
1160 /**
1161 * @since 4.09.01
1162 */
1163 protected static function addon_upgrade_link( $addon, $upgrade_link ) {
1164 if ( $addon ) {
1165 $upgrade_link .= '&utm_content=' . $addon['slug'];
1166 }
1167
1168 if ( $addon && isset( $addon['categories'] ) && in_array( 'Solution', $addon['categories'], true ) ) {
1169 // Solutions will go to a separate page.
1170 $upgrade_link = FrmAppHelper::admin_upgrade_link( 'addons', $addon['link'] );
1171 }
1172 ?>
1173 <a class="install-now button button-secondary frm-button-secondary" href="<?php echo esc_url( $upgrade_link ); ?>" target="_blank" rel="noopener" aria-label="<?php esc_attr_e( 'Upgrade Now', 'formidable' ); ?>">
1174 <?php esc_html_e( 'Upgrade Now', 'formidable' ); ?>
1175 </a>
1176 <?php
1177 }
1178
1179 /**
1180 * @since 3.04.02
1181 */
1182 public static function ajax_install_addon() {
1183 self::install_addon_permissions();
1184
1185 self::download_and_activate();
1186
1187 echo json_encode( self::get_addon_activation_response() );
1188 wp_die();
1189 }
1190
1191 /**
1192 * @since 4.06.02
1193 * @deprecated 4.09.01
1194 */
1195 public static function ajax_multiple_addons() {
1196 FrmDeprecated::ajax_multiple_addons();
1197 }
1198
1199 /**
1200 * @since 3.04.03
1201 * @deprecated 3.06
1202 * @codeCoverageIgnore
1203 * @return array
1204 */
1205 public static function error_for_license( $license ) {
1206 return FrmDeprecated::error_for_license( $license );
1207 }
1208
1209 /**
1210 * @since 3.04.03
1211 * @deprecated 3.06
1212 * @codeCoverageIgnore
1213 */
1214 public static function get_pro_updater() {
1215 return FrmDeprecated::get_pro_updater();
1216 }
1217
1218 /**
1219 * @since 3.04.03
1220 * @deprecated 3.06
1221 * @codeCoverageIgnore
1222 *
1223 * @return array
1224 */
1225 public static function get_addon_info( $license = '' ) {
1226 return FrmDeprecated::get_addon_info( $license );
1227 }
1228
1229 /**
1230 * @since 3.04.03
1231 * @deprecated 3.06
1232 * @codeCoverageIgnore
1233 *
1234 * @return string
1235 */
1236 public static function get_cache_key( $license ) {
1237 return FrmDeprecated::get_cache_key( $license );
1238 }
1239
1240 /**
1241 * @since 3.04.03
1242 * @deprecated 3.06
1243 * @codeCoverageIgnore
1244 */
1245 public static function reset_cached_addons( $license = '' ) {
1246 FrmDeprecated::reset_cached_addons( $license );
1247 }
1248
1249 /**
1250 * @since 2.03.08
1251 * @deprecated 3.04.03
1252 * @codeCoverageIgnore
1253 *
1254 * @param boolean $return
1255 * @param string $package
1256 *
1257 * @return boolean
1258 */
1259 public static function add_shorten_edd_filename_filter( $return, $package ) {
1260 return FrmDeprecated::add_shorten_edd_filename_filter( $return, $package );
1261 }
1262
1263 /**
1264 * @since 2.03.08
1265 * @deprecated 3.04.03
1266 * @codeCoverageIgnore
1267 *
1268 * @param string $filename
1269 * @param string $ext
1270 *
1271 * @return string
1272 */
1273 public static function shorten_edd_filename( $filename, $ext ) {
1274 return FrmDeprecated::shorten_edd_filename( $filename, $ext );
1275 }
1276
1277 /**
1278 * @deprecated 3.04.03
1279 * @codeCoverageIgnore
1280 */
1281 public static function get_licenses() {
1282 FrmDeprecated::get_licenses();
1283 }
1284 }
1285