PluginProbe
Tiered Pricing Table for WooCommerce / 2.2.3
Tiered Pricing Table for WooCommerce v2.2.3
8.0.2 7.1.7 7.1.5 7.1.4 7.1.1 6.5.0 6.4.0 6.1.0 trunk 1.0 1.1 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 2.3.1 2.3.2 2.3.3 All 91 releases
← All changes | freemius/includes/fs-plugin-info-dialog.php +557 -90 2.0.1 → 2.2.3 View file →
@@ -30,8 +30,31 @@
30 30 * @var Freemius
31 31 */
32 32 private $_fs;
33 33
34 + /**
35 + * Collection of plugin installation, update, download, activation, and purchase actions. This is used in
36 + * populating the actions dropdown list when there are at least 2 actions. If there's only 1 action, a button
37 + * is used instead.
38 + *
39 + * @author Leo Fajardo (@leorw)
40 + * @since 2.3.0
41 + *
42 + * @var string[]
43 + */
44 + private $actions;
45 +
46 + /**
47 + * Contains plugin status information that is used to determine which actions should be part of the actions
48 + * dropdown list.
49 + *
50 + * @author Leo Fajardo (@leorw)
51 + * @since 2.3.0
52 + *
53 + * @var string[]
54 + */
55 + private $status;
56 +
34 57 function __construct( Freemius $fs ) {
35 58 $this->_fs = $fs;
36 59
37 60 $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $fs->get_slug() . '_info', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
@@ -169,13 +192,16 @@
169 192 }
170 193
171 194 $data->fs_missing = ( ! $has_free_plan || $data->wp_org_missing );
172 195 } else {
173 - $data->wp_org_missing = false;
196 + $data->has_purchased_license = false;
197 + $data->wp_org_missing = false;
174 198
199 + $fs_addon = null;
175 200 $current_addon_version = false;
176 201 if ( $this->_fs->is_addon_activated( $selected_addon->id ) ) {
177 - $current_addon_version = $this->_fs->get_addon_instance( $selected_addon->id )->get_plugin_version();
202 + $fs_addon = $this->_fs->get_addon_instance( $selected_addon->id );
203 + $current_addon_version = $fs_addon->get_plugin_version();
178 204 } else if ( $this->_fs->is_addon_installed( $selected_addon->id ) ) {
179 205 $addon_plugin_data = get_plugin_data(
180 206 ( WP_PLUGIN_DIR . '/' . $this->_fs->get_addon_basename( $selected_addon->id ) ),
181 207 false,
@@ -195,17 +221,48 @@
195 221 $current_addon_version
196 222 );
197 223
198 224 if ( $has_paid_plan ) {
199 - $data->checkout_link = $this->_fs->checkout_url();
225 + $blog_id = fs_request_get( 'fs_blog_id' );
226 + $has_valid_blog_id = is_numeric( $blog_id );
227 +
228 + if ( $has_valid_blog_id ) {
229 + switch_to_blog( $blog_id );
230 + }
231 +
232 + $data->checkout_link = $this->_fs->checkout_url(
233 + WP_FS__PERIOD_ANNUALLY,
234 + false,
235 + array(),
236 + ( $has_valid_blog_id ? false : null )
237 + );
238 +
239 + if ( $has_valid_blog_id ) {
240 + restore_current_blog();
241 + }
242 +
243 + if ( is_object( $fs_addon ) ) {
244 + $data->has_purchased_license = $fs_addon->has_active_valid_license();
245 + } else {
246 + $account_addons = $this->_fs->get_account_addons();
247 + if ( ! empty( $account_addons ) && in_array( $selected_addon->id, $account_addons ) ) {
248 + $data->has_purchased_license = true;
249 + }
250 + }
200 251 }
201 - if ( $has_free_plan ) {
252 +
253 + if ( $has_free_plan || $data->has_purchased_license ) {
202 254 $data->download_link = $this->_fs->_get_latest_download_local_url( $selected_addon->id );
203 255 }
204 256
205 - $data->fs_missing = ( false === $latest );
257 + $data->fs_missing = (
258 + false === $latest &&
259 + (
260 + empty( $selected_addon->premium_releases_count ) ||
261 + ! ( $selected_addon->premium_releases_count > 0 )
262 + )
263 + );
206 264
207 -
208 265 // Fetch as much as possible info from local files.
209 266 $plugin_local_data = $this->_fs->get_plugin_data();
210 267 $data->author = $plugin_local_data['Author'];
211 268
@@ -227,8 +284,10 @@
227 284 $data->version = $latest->version;
228 285 $data->last_updated = $latest->created;
229 286 $data->requires = $latest->requires_platform_version;
230 287 $data->tested = $latest->tested_up_to_version;
288 + } else if ( ! empty( $current_addon_version ) ) {
289 + $data->version = $current_addon_version;
231 290 } else {
232 291 // Add dummy version.
233 292 $data->version = '1.0.0';
234 293
@@ -266,9 +325,15 @@
266 325 $data->has_free_plan = $has_free_plan;
267 326 $data->has_paid_plan = $has_paid_plan;
268 327 $data->is_paid = $has_paid_plan;
269 328 $data->is_wp_org_compliant = $selected_addon->is_wp_org_compliant;
329 + $data->premium_slug = $selected_addon->premium_slug;
330 + $data->addon_id = $selected_addon->id;
270 331
332 + if ( ! isset( $data->has_purchased_license ) ) {
333 + $data->has_purchased_license = false;
334 + }
335 +
271 336 return $data;
272 337 }
273 338
274 339 /**
@@ -332,8 +397,72 @@
332 397 return '$' . $price_tag;
333 398 }
334 399
335 400 /**
401 + * @author Leo Fajardo (@leorw)
402 + * @since 2.3.0
403 + *
404 + * @param object $api
405 + * @param FS_Plugin_Plan $plan
406 + *
407 + * @return string
408 + */
409 + private function get_actions_dropdown( $api, $plan = null ) {
410 + $this->actions = isset( $this->actions ) ?
411 + $this->actions :
412 + $this->get_plugin_actions( $api );
413 +
414 + $actions = $this->actions;
415 +
416 + $checkout_cta = $this->get_checkout_cta( $api, $plan );
417 + if ( ! empty( $checkout_cta ) ) {
418 + /**
419 + * If there's no license yet, make the checkout button the main CTA. Otherwise, make it the last item in
420 + * the actions dropdown.
421 + *
422 + * @author Leo Fajardo (@leorw)
423 + * @since 2.3.0
424 + */
425 + if ( ! $api->has_purchased_license ) {
426 + array_unshift( $actions, $checkout_cta );
427 + } else {
428 + $actions[] = $checkout_cta;
429 + }
430 + }
431 +
432 + if ( empty( $actions ) ) {
433 + return '';
434 + }
435 +
436 + $total_actions = count( $actions );
437 + if ( 1 === $total_actions ) {
438 + return $actions[0];
439 + }
440 +
441 + ob_start();
442 +
443 + ?>
444 + <div class="fs-cta fs-dropdown">
445 + <div class="button-group">
446 + <?php
447 + // This should NOT be sanitized as the $actions are HTML buttons already.
448 + echo $actions[0] ?>
449 + <div class="button button-primary fs-dropdown-arrow-button">
450 + <span class="fs-dropdown-arrow"></span>
451 + <ul class="fs-dropdown-list" style="display: none">
452 + <?php for ( $i = 1; $i < $total_actions; $i ++ ) : ?>
453 + <li><?php echo str_replace( 'button button-primary', '', $actions[ $i ] ) ?></li>
454 + <?php endfor ?>
455 + </ul>
456 + </div>
457 + </div>
458 + </div>
459 + <?php
460 +
461 + return ob_get_clean();
462 + }
463 +
464 + /**
336 465 * @author Vova Feldman (@svovaf)
337 466 * @since 1.1.7
338 467 *
339 468 * @param object $api
@@ -358,16 +487,34 @@
358 487 }
359 488 }
360 489 }
361 490
362 - return '<a class="button button-primary fs-checkout-button right" href="' . $this->_fs->addon_checkout_url(
491 + $blog_id = fs_request_get( 'fs_blog_id' );
492 + $has_valid_blog_id = is_numeric( $blog_id );
493 +
494 + if ( $has_valid_blog_id ) {
495 + switch_to_blog( $blog_id );
496 + }
497 +
498 + $addon_checkout_url = $this->_fs->addon_checkout_url(
363 499 $plan->plugin_id,
364 500 $plan->pricing[0]->id,
365 501 $this->get_billing_cycle( $plan ),
366 - $plan->has_trial()
367 - ) . '" target="_parent">' .
368 - ( ! $plan->has_trial() ?
369 - fs_text_x_inline( 'Purchase', 'verb', 'purchase', $api->slug ) :
502 + $plan->has_trial(),
503 + ( $has_valid_blog_id ? false : null )
504 + );
505 +
506 + if ( $has_valid_blog_id ) {
507 + restore_current_blog();
508 + }
509 +
510 + return '<a class="button button-primary fs-checkout-button right" href="' . $addon_checkout_url . '" target="_parent">' .
511 + esc_html( ! $plan->has_trial() ?
512 + (
513 + $api->has_purchased_license ?
514 + fs_text_inline( 'Purchase More', 'purchase-more', $api->slug ) :
515 + fs_text_x_inline( 'Purchase', 'verb', 'purchase', $api->slug )
516 + ) :
370 517 sprintf(
371 518 /* translators: %s: N-days trial */
372 519 fs_text_inline( 'Start my free %s', 'start-free-x', $api->slug ),
373 520 $this->get_trial_period( $plan )
@@ -376,97 +523,310 @@
376 523 '</a>';
377 524 }
378 525
379 526 /**
380 - * @author Vova Feldman (@svovaf)
381 - * @since 2.0.0
527 + * @author Leo Fajardo (@leorw)
528 + * @since 2.3.0
382 529 *
383 530 * @param object $api
384 - * @param bool $is_primary
385 531 *
386 - * @return string
532 + * @return string[]
387 533 */
388 - private function get_download_cta( $api, $is_primary = true ) {
389 - if ( empty( $api->download_link ) ) {
390 - return '';
534 + private function get_plugin_actions( $api ) {
535 + $this->status = isset( $this->status ) ?
536 + $this->status :
537 + install_plugin_install_status( $api );
538 +
539 + $is_update_available = ( 'update_available' === $this->status['status'] );
540 +
541 + if ( $is_update_available && empty( $this->status['url'] ) ) {
542 + return array();
391 543 }
392 544
393 - $status = install_plugin_install_status( $api );
545 + $blog_id = fs_request_get( 'fs_blog_id' );
394 546
395 - $has_paid_version = $api->has_paid_plan;
547 + $active_plugins_directories_map = Freemius::get_active_plugins_directories_map( $blog_id );
396 548
397 - // Hosted on WordPress.org.
398 - switch ( $status['status'] ) {
399 - case 'install':
400 - if ( $api->is_wp_org_compliant ||
401 - ! $this->_fs->is_org_repo_compliant() ||
402 - $this->_fs->is_premium()
403 - ) {
404 - /**
405 - * Allow immediate installation if one of the following:
406 - * 1. WordPress.org add-on.
407 - * 2. The core module is NOT wp.org compliant.
408 - * 3. The core module is running the premium version which is not wp.org compliant.
409 - */
410 - if ( $status['url'] ) {
411 - return $this->get_cta(
412 - ( $has_paid_version ?
413 - fs_esc_html_inline( 'Install Free Version Now', 'install-free-version-now', $api->slug ) :
414 - fs_esc_html_inline( 'Install Now', 'install-now', $api->slug ) ),
415 - $is_primary,
416 - false,
417 - $status['url'],
418 - '_parent'
419 - );
549 + $actions = array();
550 +
551 + $is_addon_activated = $this->_fs->is_addon_activated( $api->slug );
552 + $fs_addon = null;
553 +
554 + $is_free_installed = null;
555 + $is_premium_installed = null;
556 +
557 + $has_installed_version = ( 'install' !== $this->status['status'] );
558 +
559 + if ( ! $api->has_paid_plan ) {
560 + /**
561 + * Free-only add-on.
562 + *
563 + * @author Leo Fajardo (@leorw)
564 + * @since 2.3.0
565 + */
566 + $is_free_installed = $has_installed_version;
567 + $is_premium_installed = false;
568 + } else if ( ! $api->has_free_plan ) {
569 + /**
570 + * Premium-only add-on.
571 + *
572 + * @author Leo Fajardo (@leorw)
573 + * @since 2.3.0
574 + */
575 + $is_free_installed = false;
576 + $is_premium_installed = $has_installed_version;
577 + } else {
578 + /**
579 + * Freemium add-on.
580 + *
581 + * @author Leo Fajardo (@leorw)
582 + * @since 2.3.0
583 + */
584 + if ( ! $has_installed_version ) {
585 + $is_free_installed = false;
586 + $is_premium_installed = false;
587 + } else {
588 + $fs_addon = $is_addon_activated ?
589 + $this->_fs->get_addon_instance( $api->slug ) :
590 + null;
591 +
592 + if ( is_object( $fs_addon ) ) {
593 + if ( $fs_addon->is_premium() ) {
594 + $is_premium_installed = true;
595 + } else {
596 + $is_free_installed = true;
420 597 }
421 598 }
422 599
423 - return $this->get_cta(
424 - ( $has_paid_version ?
425 - fs_esc_html_x_inline( 'Download Latest Free Version', 'as download latest version', 'download-latest-free-version', $api->slug ) :
426 - fs_esc_html_x_inline( 'Download Latest', 'as download latest version', 'download-latest', $api->slug ) ),
427 - $is_primary,
428 - false,
429 - esc_url( $api->download_link )
430 - );
431 - break;
432 - case 'update_available':
433 - if ( $status['url'] ) {
434 - return $this->get_cta(
435 - ( $has_paid_version ?
436 - fs_esc_html_inline( 'Install Free Version Update Now', 'install-free-version-update-now', $api->slug ) :
437 - fs_esc_html_inline( 'Install Update Now', 'install-update-now', $api->slug ) ),
438 - $is_primary,
439 - false,
440 - $status['url'],
441 - '_parent'
442 - );
600 + if ( is_null( $is_free_installed ) ) {
601 + $is_free_installed = file_exists( fs_normalize_path( WP_PLUGIN_DIR . "/{$api->slug}/{$api->slug}.php" ) );
602 + if ( ! $is_free_installed ) {
603 + /**
604 + * Check if there's a plugin installed in a directory named `$api->slug`.
605 + *
606 + * @author Leo Fajardo (@leorw)
607 + * @since 2.3.0
608 + */
609 + $installed_plugins = get_plugins( '/' . $api->slug );
610 + $is_free_installed = ( ! empty( $installed_plugins ) );
611 + }
443 612 }
444 - break;
445 - case 'newer_installed':
446 - return $this->get_cta(
447 - ( $has_paid_version ?
448 - esc_html( sprintf( fs_text_inline( 'Newer Free Version (%s) Installed', 'newer-free-installed', $api->slug ), $status['version'] ) ) :
449 - esc_html( sprintf( fs_text_inline( 'Newer Version (%s) Installed', 'newer-installed', $api->slug ), $status['version'] ) ) ),
450 - $is_primary,
451 - true
452 - );
453 - break;
454 - case 'latest_installed':
455 - return $this->get_cta(
456 - ( $has_paid_version ?
457 - fs_esc_html_inline( 'Latest Free Version Installed', 'latest-free-installed', $api->slug ) :
458 - fs_esc_html_inline( 'Latest Version Installed', 'latest-installed', $api->slug ) ),
459 - $is_primary,
460 - true
461 - );
462 - break;
613 +
614 + if ( is_null( $is_premium_installed ) ) {
615 + $is_premium_installed = file_exists( fs_normalize_path( WP_PLUGIN_DIR . "/{$api->premium_slug}/{$api->slug}.php" ) );
616 + if ( ! $is_premium_installed ) {
617 + /**
618 + * Check if there's a plugin installed in a directory named `$api->premium_slug`.
619 + *
620 + * @author Leo Fajardo (@leorw)
621 + * @since 2.3.0
622 + */
623 + $installed_plugins = get_plugins( '/' . $api->premium_slug );
624 + $is_premium_installed = ( ! empty( $installed_plugins ) );
625 + }
626 + }
627 + }
628 +
629 + $has_installed_version = ( $is_free_installed || $is_premium_installed );
463 630 }
464 631
465 - return '';
632 + $this->status['is_free_installed'] = $is_free_installed;
633 + $this->status['is_premium_installed'] = $is_premium_installed;
634 +
635 + $can_install_free_version = false;
636 + $can_install_free_version_update = false;
637 + $can_download_free_version = false;
638 + $can_activate_free_version = false;
639 + $can_install_premium_version = false;
640 + $can_install_premium_version_update = false;
641 + $can_download_premium_version = false;
642 + $can_activate_premium_version = false;
643 +
644 + if ( ! $api->has_purchased_license ) {
645 + if ( $api->has_free_plan ) {
646 + if ( $has_installed_version ) {
647 + if ( $is_update_available ) {
648 + $can_install_free_version_update = true;
649 + } else if ( ! $is_premium_installed && ! isset( $active_plugins_directories_map[ dirname( $this->status['file'] ) ] ) ) {
650 + $can_activate_free_version = true;
651 + }
652 + } else {
653 + if (
654 + $this->_fs->is_premium() ||
655 + ! $this->_fs->is_org_repo_compliant() ||
656 + $api->is_wp_org_compliant
657 + ) {
658 + $can_install_free_version = true;
659 + } else {
660 + $can_download_free_version = true;
661 + }
662 + }
663 + }
664 + } else {
665 + if ( ! is_object( $fs_addon ) && $is_addon_activated ) {
666 + $fs_addon = $this->_fs->get_addon_instance( $api->slug );
667 + }
668 +
669 + $can_download_premium_version = true;
670 +
671 + if ( ! isset( $active_plugins_directories_map[ dirname( $this->status['file'] ) ] ) ) {
672 + if ( $is_premium_installed ) {
673 + $can_activate_premium_version = ( ! $is_addon_activated || ! $fs_addon->is_premium() );
674 + } else if ( $is_free_installed ) {
675 + $can_activate_free_version = ( ! $is_addon_activated );
676 + }
677 + }
678 +
679 + if ( $this->_fs->is_premium() || ! $this->_fs->is_org_repo_compliant() ) {
680 + if ( $is_update_available ) {
681 + $can_install_premium_version_update = true;
682 + } else if ( ! $is_premium_installed ) {
683 + $can_install_premium_version = true;
684 + }
685 + }
686 + }
687 +
688 + if (
689 + $can_install_premium_version ||
690 + $can_install_premium_version_update
691 + ) {
692 + if ( is_numeric( $blog_id ) ) {
693 + /**
694 + * Replace the network status URL with a blog admin–based status URL if the `Add-Ons` page is loaded
695 + * from a specific blog admin page (when `fs_blog_id` is valid) in order for plugin installation/update
696 + * to work.
697 + *
698 + * @author Leo Fajardo (@leorw)
699 + * @since 2.3.0
700 + */
701 + $this->status['url'] = self::get_blog_status_url( $blog_id, $this->status['url'], $this->status['status'] );
702 + }
703 +
704 + /**
705 + * Add the `fs_allow_updater_and_dialog` param to the install/update URL so that the add-on can be
706 + * installed/updated.
707 + *
708 + * @author Leo Fajardo (@leorw)
709 + * @since 2.3.0
710 + */
711 + $this->status['url'] = str_replace( '?', '?fs_allow_updater_and_dialog=true&amp;', $this->status['url'] );
712 + }
713 +
714 + if ( $can_install_free_version_update || $can_install_premium_version_update ) {
715 + $actions[] = $this->get_cta(
716 + ( $can_install_free_version_update ?
717 + fs_esc_html_inline( 'Install Free Version Update Now', 'install-free-version-update-now', $api->slug ) :
718 + fs_esc_html_inline( 'Install Update Now', 'install-update-now', $api->slug ) ),
719 + true,
720 + false,
721 + $this->status['url'],
722 + '_parent'
723 + );
724 + } else if ( $can_install_free_version || $can_install_premium_version ) {
725 + $actions[] = $this->get_cta(
726 + ( $can_install_free_version ?
727 + fs_esc_html_inline( 'Install Free Version Now', 'install-free-version-now', $api->slug ) :
728 + fs_esc_html_inline( 'Install Now', 'install-now', $api->slug ) ),
729 + true,
730 + false,
731 + $this->status['url'],
732 + '_parent'
733 + );
734 + }
735 +
736 + $download_latest_action = '';
737 +
738 + if (
739 + ! empty( $api->download_link ) &&
740 + ( $can_download_free_version || $can_download_premium_version )
741 + ) {
742 + $download_latest_action = $this->get_cta(
743 + ( $can_download_free_version ?
744 + fs_esc_html_x_inline( 'Download Latest Free Version', 'as download latest version', 'download-latest-free-version', $api->slug ) :
745 + fs_esc_html_x_inline( 'Download Latest', 'as download latest version', 'download-latest', $api->slug ) ),
746 + true,
747 + false,
748 + esc_url( $api->download_link )
749 + );
750 + }
751 +
752 + if ( ! $can_activate_free_version && ! $can_activate_premium_version ) {
753 + if ( ! empty( $download_latest_action ) ) {
754 + $actions[] = $download_latest_action;
755 + }
756 + } else {
757 + $activate_action = sprintf(
758 + '<a class="button button-primary edit" href="%s" title="%s" target="_parent">%s</a>',
759 + wp_nonce_url( ( is_numeric( $blog_id ) ? trailingslashit( get_admin_url( $blog_id ) ) : '' ) . 'plugins.php?action=activate&amp;plugin=' . $this->status['file'], 'activate-plugin_' . $this->status['file'] ),
760 + fs_esc_attr_inline( 'Activate this add-on', 'activate-this-addon', $api->slug ),
761 + $can_activate_free_version ?
762 + fs_text_inline( 'Activate Free Version', 'activate-free', $api->slug ) :
763 + fs_text_inline( 'Activate', 'activate', $api->slug )
764 + );
765 +
766 + if ( ! $can_download_premium_version && ! empty( $download_latest_action ) ) {
767 + $actions[] = $download_latest_action;
768 +
769 + $download_latest_action = '';
770 + }
771 +
772 + if ( $can_install_premium_version || $can_install_premium_version_update ) {
773 + if ( $can_download_premium_version && ! empty( $download_latest_action ) ) {
774 + $actions[] = $download_latest_action;
775 +
776 + $download_latest_action = '';
777 + }
778 +
779 + $actions[] = $activate_action;
780 + } else {
781 + array_unshift( $actions, $activate_action );
782 + }
783 +
784 + if ( ! empty ($download_latest_action ) ) {
785 + $actions[] = $download_latest_action;
786 + }
787 + }
788 +
789 + return $actions;
466 790 }
467 791
468 792 /**
793 + * Rebuilds the status URL based on the admin URL.
794 + *
795 + * @author Leo Fajardo (@leorw)
796 + * @since 2.3.0
797 + *
798 + * @param int $blog_id
799 + * @param string $network_status_url
800 + * @param string $status
801 + *
802 + * @return string
803 + */
804 + private static function get_blog_status_url( $blog_id, $network_status_url, $status ) {
805 + if ( ! in_array( $status, array( 'install', 'update_available' ) ) ) {
806 + return $network_status_url;
807 + }
808 +
809 + $action = ( 'install' === $status ) ?
810 + 'install-plugin' :
811 + 'upgrade-plugin';
812 +
813 + $query = parse_url( $network_status_url, PHP_URL_QUERY );
814 + if ( empty( $query ) ) {
815 + return $network_status_url;
816 + }
817 +
818 + parse_str( html_entity_decode( $query ), $url_params );
819 + if ( empty( $url_params ) || ! isset( $url_params['plugin'] ) ) {
820 + return $network_status_url;
821 + }
822 +
823 + $plugin = $url_params['plugin'];
824 +
825 + return wp_nonce_url( get_admin_url( $blog_id,"update.php?action={$action}&plugin={$plugin}"), "{$action}_{$plugin}");
826 + }
827 +
828 + /**
469 829 * Helper method to get a CTA button HTML.
470 830 *
471 831 * @author Vova Feldman (@svovaf)
472 832 * @since 2.0.0
@@ -814,9 +1174,9 @@
814 1174 echo " + '&trial=true'";
815 1175 }?>;
816 1176 },
817 1177 _updateCtaUrl = function (plan, pricing, cycle) {
818 - $('.plugin-information-pricing .button, #plugin-information-footer .button.fs-checkout-button').attr('href', _checkoutUrl(plan, pricing, cycle));
1178 + $('.plugin-information-pricing .fs-checkout-button, #plugin-information-footer .fs-checkout-button').attr('href', _checkoutUrl(plan, pricing, cycle));
819 1179 };
820 1180
821 1181 $(document).ready(function () {
822 1182 var $plan = $('.plugin-information-pricing .fs-plan[data-plan-id=<?php echo $plan->id ?>]');
@@ -901,9 +1261,9 @@
901 1261 fs_esc_html_inline( 'Save %s', 'save-x', $api->slug ), $annual_discount . '%' ) ?></span>
902 1262 <?php endif ?>
903 1263 <ul class="fs-licenses">
904 1264 </ul>
905 - <?php echo $this->get_checkout_cta( $api, $plan, false ) ?>
1265 + <?php echo $this->get_actions_dropdown( $api, $plan ) ?>
906 1266 <div style="clear:both"></div>
907 1267 <?php if ( $plan->has_trial() ) : ?>
908 1268 <?php $trial_period = $this->get_trial_period( $plan ) ?>
909 1269 <ul class="fs-trial-terms">
@@ -1126,18 +1486,125 @@
1126 1486 echo "</div>\n";
1127 1487 echo "</div>\n"; // #plugin-information-scrollable
1128 1488 echo "<div id='$tab-footer'>\n";
1129 1489
1130 - if ( $api->has_paid_plan && ! empty( $api->checkout_link ) ) {
1131 - echo $this->get_checkout_cta( $api );
1490 + if (
1491 + ! empty( $api->download_link ) &&
1492 + ! empty( $this->status ) &&
1493 + in_array( $this->status['status'], array( 'newer_installed', 'latest_installed' ) )
1494 + ) {
1495 + if ( 'newer_installed' === $this->status['status'] ) {
1496 + echo $this->get_cta(
1497 + ( $this->status['is_premium_installed'] ?
1498 + esc_html( sprintf( fs_text_inline( 'Newer Version (%s) Installed', 'newer-installed', $api->slug ), $this->status['version'] ) ) :
1499 + esc_html( sprintf( fs_text_inline( 'Newer Free Version (%s) Installed', 'newer-free-installed', $api->slug ), $this->status['version'] ) ) ),
1500 + false,
1501 + true
1502 + );
1503 + } else {
1504 + echo $this->get_cta(
1505 + ( $this->status['is_premium_installed'] ?
1506 + fs_esc_html_inline( 'Latest Version Installed', 'latest-installed', $api->slug ) :
1507 + fs_esc_html_inline( 'Latest Free Version Installed', 'latest-free-installed', $api->slug ) ),
1508 + false,
1509 + true
1510 + );
1511 + }
1132 1512 }
1133 1513
1134 - if ( ! empty( $api->download_link ) ) {
1135 - echo $this->get_download_cta( $api, empty( $api->checkout_link ) );
1136 - }
1514 + echo $this->get_actions_dropdown( $api, null );
1137 1515
1138 1516 echo "</div>\n";
1517 + ?>
1518 + <script type="text/javascript">
1519 + ( function( $, undef ) {
1520 + var $dropdowns = $( '.fs-dropdown' );
1139 1521
1522 + $( '#plugin-information' )
1523 + .click( function( evt ) {
1524 + var $target = $( evt.target );
1525 +
1526 + if (
1527 + $target.hasClass( 'fs-dropdown-arrow-button' ) ||
1528 + ( 0 !== $target.parents( '.fs-dropdown-arrow-button' ).length )
1529 + ) {
1530 + var $dropdown = $target.parents( '.fs-dropdown' ),
1531 + isActive = $dropdown.hasClass( 'active' );
1532 +
1533 + if ( ! isActive ) {
1534 + /**
1535 + * Close the other dropdown if it's active.
1536 + *
1537 + * @author Leo Fajardo (@leorw)
1538 + * @since 2.3.0
1539 + */
1540 + $( '.fs-dropdown.active' ).each( function() {
1541 + toggleDropdown( $( this ), false );
1542 + } );
1543 + }
1544 +
1545 + /**
1546 + * Toggle the current dropdown.
1547 + *
1548 + * @author Leo Fajardo (@leorw)
1549 + * @since 2.3.0
1550 + */
1551 + toggleDropdown( $dropdown, ! isActive );
1552 +
1553 + return true;
1554 + }
1555 +
1556 + /**
1557 + * Close all dropdowns.
1558 + *
1559 + * @author Leo Fajardo (@leorw)
1560 + * @since 2.3.0
1561 + */
1562 + toggleDropdown( $( this ).find( '.fs-dropdown' ), false );
1563 + });
1564 +
1565 + if ( 0 !== $dropdowns.length ) {
1566 + /**
1567 + * Add the `up` class so that the bottom dropdown's content will be shown above its buttons.
1568 + *
1569 + * @author Leo Fajardo (@leorw)
1570 + * @since 2.3.0
1571 + */
1572 + $( '#plugin-information-footer' ).find( '.fs-dropdown' ).addClass( 'up' );
1573 + }
1574 +
1575 + /**
1576 + * Returns the default state of the dropdown arrow button and hides the dropdown list.
1577 + *
1578 + * @author Leo Fajardo (@leorw)
1579 + * @since 2.3.0
1580 + *
1581 + * @param {Object} [$dropdown]
1582 + * @param {Boolean} [state]
1583 + */
1584 + function toggleDropdown( $dropdown, state ) {
1585 + if ( undef === $dropdown ) {
1586 + var $activeDropdown = $dropdowns.find( '.active' );
1587 + if ( 0 !== $activeDropdown.length ) {
1588 + $dropdown = $activeDropdown;
1589 + }
1590 + }
1591 +
1592 + if ( undef === $dropdown ) {
1593 + return;
1594 + }
1595 +
1596 + if ( undef === state ) {
1597 + state = false;
1598 + }
1599 +
1600 + $dropdown.toggleClass( 'active', state );
1601 + $dropdown.find( '.fs-dropdown-list' ).toggle( state );
1602 + $dropdown.find( '.fs-dropdown-arrow-button' ).toggleClass( 'active', state );
1603 + }
1604 + } )( jQuery );
1605 + </script>
1606 + <?php
1140 1607 iframe_footer();
1141 1608 exit;
1142 1609 }
1143 1610 }