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

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