| @@ -156,9 +156,10 @@ | ||
| 156 | 156 | 'pro' => array( |
| 157 | 157 | 'title' => 'Formidable Forms Pro', |
| 158 | 158 | 'slug' => 'formidable-pro', |
| 159 | 159 | 'released' => '2011-02-05', |
| 160 | - 'docs' => 'knowledgebase/', | |
| 160 | + 'docs' => 'knowledgebase/what-is-the-difference-between-the-lite-free-and-pro-version/', | |
| 161 | + 'docs_label' => __( 'Why Upgrade', 'formidable' ), | |
| 161 | 162 | 'categories' => array( 'basic', 'plus', 'business', 'elite' ), |
| 162 | 163 | 'excerpt' => 'Create calculators, surveys, smart forms, and data-driven applications. Build directories, real estate listings, job boards, and much more.', |
| 163 | 164 | ), |
| 164 | 165 | ); |
| @@ -308,10 +309,9 @@ | ||
| 308 | 309 | * |
| 309 | 310 | * @return int Count of addons. |
| 310 | 311 | */ |
| 311 | 312 | public static function get_addons_count() { |
| 312 | - $addons = self::get_api_addons(); | |
| 313 | - return count( $addons ); | |
| 313 | + return count( self::get_api_addons() ); | |
| 314 | 314 | } |
| 315 | 315 | |
| 316 | 316 | /** |
| 317 | 317 | * If the API is unable to connect, show something on the addons page |
| @@ -420,10 +420,9 @@ | ||
| 420 | 420 | * |
| 421 | 421 | * @return string |
| 422 | 422 | */ |
| 423 | 423 | public static function get_pro_download_url() { |
| 424 | - $license = self::get_pro_license(); | |
| 425 | - $api = new FrmFormApi( $license ); | |
| 424 | + $api = new FrmFormApi( self::get_pro_license() ); | |
| 426 | 425 | $downloads = $api->get_api_info(); |
| 427 | 426 | $pro = self::get_pro_from_addons( $downloads ); |
| 428 | 427 | |
| 429 | 428 | return $pro['url'] ?? ''; |
| @@ -474,17 +473,134 @@ | ||
| 474 | 473 | } |
| 475 | 474 | |
| 476 | 475 | /** |
| 477 | 476 | * @since 4.06 |
| 477 | + * @since 6.31 Added the $force_type param. | |
| 478 | 478 | * |
| 479 | + * @param bool $force_type Whether to resolve grandfathered licenses to their real license type. | |
| 480 | + * | |
| 479 | 481 | * @return string |
| 480 | 482 | */ |
| 481 | - public static function license_type() { | |
| 483 | + public static function license_type( $force_type = false ) { | |
| 482 | 484 | if ( is_callable( 'FrmProAddonsController::license_type' ) ) { |
| 483 | - return FrmProAddonsController::license_type(); | |
| 485 | + return FrmProAddonsController::license_type( $force_type ); | |
| 484 | 486 | } |
| 485 | 487 | |
| 486 | 488 | return 'free'; |
| 489 | + } | |
| 490 | + | |
| 491 | + /** | |
| 492 | + * Determine the license status for payment fee decisions. | |
| 493 | + * | |
| 494 | + * Mirrors determine_status_from_license_details in the Stripe Connect service, | |
| 495 | + * including its 2016-04-26 grandfathered cutoff. Square and PayPal Commerce use a | |
| 496 | + * later cutoff, so read their fees through payment_fees_apply instead. | |
| 497 | + * | |
| 498 | + * @since 6.31 | |
| 499 | + * | |
| 500 | + * @return string 'active', 'expired', or 'free'. | |
| 501 | + */ | |
| 502 | + public static function get_payment_license_status() { | |
| 503 | + $version_info = self::get_primary_license_info(); | |
| 504 | + | |
| 505 | + if ( ! $version_info ) { | |
| 506 | + return 'free'; | |
| 507 | + } | |
| 508 | + | |
| 509 | + $error = $version_info['error'] ?? array(); | |
| 510 | + | |
| 511 | + if ( is_array( $error ) && 'expired' === ( $error['code'] ?? '' ) ) { | |
| 512 | + return 'expired'; | |
| 513 | + } | |
| 514 | + | |
| 515 | + if ( self::is_grandfathered_license() ) { | |
| 516 | + $expires = self::get_grandfathered_expiration( $version_info ); | |
| 517 | + | |
| 518 | + if ( $expires && gmdate( 'Y-m-d', $expires ) < '2016-04-26' ) { | |
| 519 | + return 'free'; | |
| 520 | + } | |
| 521 | + } | |
| 522 | + | |
| 523 | + if ( in_array( self::license_type( true ), array( 'elite', 'business' ), true ) ) { | |
| 524 | + return 'active'; | |
| 525 | + } | |
| 526 | + | |
| 527 | + return 'free'; | |
| 528 | + } | |
| 529 | + | |
| 530 | + /** | |
| 531 | + * Check if a connect service charges its per-transaction fee for this license. | |
| 532 | + * | |
| 533 | + * Square and PayPal Commerce launched long after lifetime licenses stopped being | |
| 534 | + * sold, so their services charge every grandfathered license. Stripe's predates | |
| 535 | + * them and exempts most of them, which get_payment_license_status mirrors. | |
| 536 | + * | |
| 537 | + * @since 6.34 | |
| 538 | + * | |
| 539 | + * @param string $service The connect service: 'stripe', 'square', or 'paypal'. | |
| 540 | + * | |
| 541 | + * @return bool | |
| 542 | + */ | |
| 543 | + public static function payment_fees_apply( $service ) { | |
| 544 | + if ( 'active' !== self::get_payment_license_status() ) { | |
| 545 | + return true; | |
| 546 | + } | |
| 547 | + | |
| 548 | + if ( in_array( $service, array( 'square', 'paypal' ), true ) ) { | |
| 549 | + return self::is_grandfathered_license(); | |
| 550 | + } | |
| 551 | + | |
| 552 | + return false; | |
| 553 | + } | |
| 554 | + | |
| 555 | + /** | |
| 556 | + * Check if the primary license is grandfathered. | |
| 557 | + * | |
| 558 | + * The API reports this on the Pro add-on itself, the same place | |
| 559 | + * FrmProAddonsController::license_type reads it from. Older responses put it | |
| 560 | + * in the top level error instead, so check both. | |
| 561 | + * | |
| 562 | + * @since 6.34 | |
| 563 | + * | |
| 564 | + * @return bool | |
| 565 | + */ | |
| 566 | + public static function is_grandfathered_license() { | |
| 567 | + $version_info = self::get_primary_license_info(); | |
| 568 | + | |
| 569 | + if ( ! $version_info ) { | |
| 570 | + return false; | |
| 571 | + } | |
| 572 | + | |
| 573 | + $error = $version_info['error'] ?? array(); | |
| 574 | + | |
| 575 | + if ( is_array( $error ) && 'grandfathered' === ( $error['code'] ?? '' ) ) { | |
| 576 | + return true; | |
| 577 | + } | |
| 578 | + | |
| 579 | + $pro = self::get_pro_from_addons( $version_info ); | |
| 580 | + | |
| 581 | + return 'grandfathered' === ( $pro['code'] ?? '' ); | |
| 582 | + } | |
| 583 | + | |
| 584 | + /** | |
| 585 | + * Get the expiration timestamp reported alongside a grandfathered license. | |
| 586 | + * | |
| 587 | + * @since 6.34 | |
| 588 | + * | |
| 589 | + * @param array $version_info The license info from get_primary_license_info. | |
| 590 | + * | |
| 591 | + * @return int | |
| 592 | + */ | |
| 593 | + private static function get_grandfathered_expiration( $version_info ) { | |
| 594 | + $error = $version_info['error'] ?? array(); | |
| 595 | + | |
| 596 | + if ( is_array( $error ) && ! empty( $error['expires'] ) ) { | |
| 597 | + return (int) $error['expires']; | |
| 598 | + } | |
| 599 | + | |
| 600 | + $pro = self::get_pro_from_addons( $version_info ); | |
| 601 | + | |
| 602 | + return (int) ( $pro['expires'] ?? 0 ); | |
| 487 | 603 | } |
| 488 | 604 | |
| 489 | 605 | /** |
| 490 | 606 | * @since 4.0.01 |