← All changes
|
libraries/freemius/includes/class-fs-plugin-updater.php
+77
-41
2.4
→
3.4
View file →
| @@ -105,8 +105,10 @@ | ||
| 105 | 105 | ), 11, 2 ); |
| 106 | 106 | |
| 107 | 107 | if ( ! $this->_fs->has_any_active_valid_license() ) { |
| 108 | 108 | add_action( 'admin_head', array( &$this, 'catch_plugin_information_dialog_contents' ) ); |
| 109 | + } else { | |
| 110 | + add_action( 'admin_footer', array( &$this, '_add_fs_allow_updater_and_dialog_request_param' ) ); | |
| 109 | 111 | } |
| 110 | 112 | |
| 111 | 113 | if ( ! WP_FS__IS_PRODUCTION_MODE ) { |
| 112 | 114 | add_filter( 'http_request_host_is_external', array( |
| @@ -130,15 +132,48 @@ | ||
| 130 | 132 | } |
| 131 | 133 | |
| 132 | 134 | /** |
| 133 | 135 | * @author Leo Fajardo (@leorw) |
| 136 | + * @since 2.7.4 | |
| 137 | + */ | |
| 138 | + function _add_fs_allow_updater_and_dialog_request_param() { | |
| 139 | + if ( ! $this->is_plugin_information_dialog_for_plugin() ) { | |
| 140 | + return; | |
| 141 | + } | |
| 142 | + ?> | |
| 143 | + <script type="text/javascript"> | |
| 144 | + if ( typeof jQuery !== 'undefined' ) { | |
| 145 | + jQuery( document ).on( 'wp-plugin-updating', function( event, args ) { | |
| 146 | + if ( typeof args === 'object' && args.slug && typeof args.slug === 'string' ) { | |
| 147 | + if ( <?php echo json_encode( $this->_fs->get_slug() ) ?> === args.slug ) { | |
| 148 | + args.fs_allow_updater_and_dialog = true; | |
| 149 | + } | |
| 150 | + } | |
| 151 | + } ); | |
| 152 | + } | |
| 153 | + </script> | |
| 154 | + <?php | |
| 155 | + } | |
| 156 | + | |
| 157 | + /** | |
| 158 | + * @author Leo Fajardo (@leorw) | |
| 159 | + * @since 2.7.4 | |
| 160 | + * | |
| 161 | + * @return bool | |
| 162 | + */ | |
| 163 | + private function is_plugin_information_dialog_for_plugin() { | |
| 164 | + return ( | |
| 165 | + 'plugin-information' === fs_request_get( 'tab', false ) && | |
| 166 | + $this->_fs->get_slug() === fs_request_get_raw( 'plugin', false ) | |
| 167 | + ); | |
| 168 | + } | |
| 169 | + | |
| 170 | + /** | |
| 171 | + * @author Leo Fajardo (@leorw) | |
| 134 | 172 | * @since 2.1.4 |
| 135 | 173 | */ |
| 136 | 174 | function catch_plugin_information_dialog_contents() { |
| 137 | - if ( | |
| 138 | - 'plugin-information' !== fs_request_get( 'tab', false ) || | |
| 139 | - $this->_fs->get_slug() !== fs_request_get_raw( 'plugin', false ) | |
| 140 | - ) { | |
| 175 | + if ( ! $this->is_plugin_information_dialog_for_plugin() ) { | |
| 141 | 176 | return; |
| 142 | 177 | } |
| 143 | 178 | |
| 144 | 179 | add_action( 'admin_footer', array( &$this, 'edit_and_echo_plugin_information_dialog_contents' ), 0, 1 ); |
| @@ -504,38 +539,40 @@ | ||
| 504 | 539 | ) { |
| 505 | 540 | return $transient_data; |
| 506 | 541 | } |
| 507 | 542 | |
| 543 | + // Alias. | |
| 544 | + $basename = $this->_fs->premium_plugin_basename(); | |
| 545 | + | |
| 508 | 546 | global $wp_current_filter; |
| 509 | 547 | |
| 510 | - $current_plugin_version = $this->_fs->get_plugin_version(); | |
| 511 | - | |
| 512 | - if ( ! empty( $wp_current_filter ) && 'upgrader_process_complete' === $wp_current_filter[0] ) { | |
| 513 | - if ( | |
| 514 | - is_null( $this->_update_details ) || | |
| 515 | - ( is_object( $this->_update_details ) && $this->_update_details->new_version !== $current_plugin_version ) | |
| 516 | - ) { | |
| 548 | + /** | |
| 549 | + * During bulk updates, avoid re-injecting update data for the plugin itself once it has already been updated. | |
| 550 | + * | |
| 551 | + * If the custom package is re-added to the transient after the plugin update, WordPress may detect the package again and incorrectly report "The plugin is at the latest version" for a pending update, since the custom package version matches the currently installed version. | |
| 552 | + * | |
| 553 | + * Behavior differs depending on how the bulk update is triggered. Please refer to the inline comments for each flow below for details. | |
| 554 | + */ | |
| 555 | + if ( | |
| 556 | + ! empty( $wp_current_filter ) && ( | |
| 517 | 557 | /** |
| 518 | - * After an update, clear the stored update details and reparse the plugin's main file in order to get | |
| 519 | - * the updated version's information and prevent the previous update information from showing up on the | |
| 520 | - * updates page. | |
| 521 | - * | |
| 522 | - * @author Leo Fajardo (@leorw) | |
| 523 | - * @since 2.3.1 | |
| 558 | + * update-core.php and other upgrader pages: | |
| 559 | + * The `upgrader_process_complete` action fires only once after all updates have finished. In this case, it is the current action (`$wp_current_filter[0]`), while `self::$_upgrade_basename` may contain any plugin basename. | |
| 524 | 560 | */ |
| 525 | - $this->_update_details = null; | |
| 526 | - $current_plugin_version = $this->_fs->get_plugin_version( true ); | |
| 527 | - } | |
| 561 | + 'upgrader_process_complete' === $wp_current_filter[0] || | |
| 562 | + /** | |
| 563 | + * AJAX bulk updates (e.g., from the Plugins page): | |
| 564 | + * The `upgrader_process_complete` action fires multiple times — once for each plugin after it finishes updating. In this flow, it is not the current action (`$wp_current_filter[0]`) because it is triggered from another action. Instead, we compare `self::$_upgrade_basename` with the basename of the plugin currently being updated, since the `upgrader_process_complete` action runs separately for each plugin. | |
| 565 | + */ | |
| 566 | + ( in_array( 'upgrader_process_complete', $wp_current_filter ) && self::$_upgrade_basename === $basename ) | |
| 567 | + ) | |
| 568 | + ) { | |
| 569 | + return $transient_data; | |
| 528 | 570 | } |
| 529 | 571 | |
| 530 | 572 | if ( ! isset( $this->_update_details ) ) { |
| 531 | 573 | // Get plugin's newest update. |
| 532 | - $new_version = $this->_fs->get_update( | |
| 533 | - false, | |
| 534 | - fs_request_get_bool( 'force-check' ), | |
| 535 | - FS_Plugin_Updater::UPDATES_CHECK_CACHE_EXPIRATION, | |
| 536 | - $current_plugin_version | |
| 537 | - ); | |
| 574 | + $new_version = $this->_fs->get_update( false, fs_request_get_bool( 'force-check' ) ); | |
| 538 | 575 | |
| 539 | 576 | $this->_update_details = false; |
| 540 | 577 | |
| 541 | 578 | if ( is_object( $new_version ) && $this->is_new_version_premium( $new_version ) ) { |
| @@ -551,11 +588,8 @@ | ||
| 551 | 588 | $this->_update_details = $this->get_update_details( $new_version ); |
| 552 | 589 | } |
| 553 | 590 | } |
| 554 | 591 | |
| 555 | - // Alias. | |
| 556 | - $basename = $this->_fs->premium_plugin_basename(); | |
| 557 | - | |
| 558 | 592 | if ( is_object( $this->_update_details ) ) { |
| 559 | 593 | if ( isset( $transient_data->no_update ) ) { |
| 560 | 594 | unset( $transient_data->no_update[ $basename ] ); |
| 561 | 595 | } |
| @@ -615,9 +649,9 @@ | ||
| 615 | 649 | } |
| 616 | 650 | |
| 617 | 651 | $slug = $this->_fs->get_slug(); |
| 618 | 652 | |
| 619 | - if ( $this->_fs->is_org_repo_compliant() && $this->_fs->is_freemium() ) { | |
| 653 | + if ( $this->can_fetch_data_from_wp_org() ) { | |
| 620 | 654 | if ( ! isset( $this->_translation_updates ) ) { |
| 621 | 655 | $this->_translation_updates = array(); |
| 622 | 656 | |
| 623 | 657 | $translation_updates = $this->fetch_wp_org_module_translation_updates( $module_type, $slug ); |
| @@ -684,18 +718,10 @@ | ||
| 684 | 718 | 'default' => $icon, |
| 685 | 719 | ); |
| 686 | 720 | } |
| 687 | 721 | |
| 688 | - if ( $this->_fs->is_premium() ) { | |
| 689 | - $latest_tag = $this->_fs->_fetch_latest_version( $this->_fs->get_id(), false ); | |
| 690 | - | |
| 691 | - if ( | |
| 692 | - isset( $latest_tag->readme ) && | |
| 693 | - isset( $latest_tag->readme->upgrade_notice ) && | |
| 694 | - ! empty( $latest_tag->readme->upgrade_notice ) | |
| 695 | - ) { | |
| 696 | - $update->upgrade_notice = $latest_tag->readme->upgrade_notice; | |
| 697 | - } | |
| 722 | + if ( $this->_fs->is_premium() && ! empty( $new_version->upgrade_notice ) ) { | |
| 723 | + $update->upgrade_notice = $new_version->upgrade_notice; | |
| 698 | 724 | } |
| 699 | 725 | |
| 700 | 726 | $update->{$this->_fs->get_module_type()} = $this->_fs->get_plugin_basename(); |
| 701 | 727 | |
| @@ -873,8 +899,18 @@ | ||
| 873 | 899 | return $res; |
| 874 | 900 | } |
| 875 | 901 | |
| 876 | 902 | /** |
| 903 | + * Returns true if the product can fetch data from WordPress.org. | |
| 904 | + * | |
| 905 | + * @author Leo Fajardo (@leorw) | |
| 906 | + * @since 2.7.4 | |
| 907 | + */ | |
| 908 | + private function can_fetch_data_from_wp_org() { | |
| 909 | + return ( $this->_fs->is_org_repo_compliant() && $this->_fs->is_freemium() ); | |
| 910 | + } | |
| 911 | + | |
| 912 | + /** | |
| 877 | 913 | * Fetches module translation updates from wordpress.org. |
| 878 | 914 | * |
| 879 | 915 | * @author Leo Fajardo (@leorw) |
| 880 | 916 | * @since 2.1.2 |
| @@ -1056,9 +1092,9 @@ | ||
| 1056 | 1092 | $is_addon = true; |
| 1057 | 1093 | } |
| 1058 | 1094 | |
| 1059 | 1095 | $plugin_in_repo = false; |
| 1060 | - if ( ! $is_addon ) { | |
| 1096 | + if ( ! $is_addon && $this->can_fetch_data_from_wp_org() ) { | |
| 1061 | 1097 | // Try to fetch info from .org repository. |
| 1062 | 1098 | $data = self::_fetch_plugin_info_from_repository( $action, $args ); |
| 1063 | 1099 | |
| 1064 | 1100 | $plugin_in_repo = ( false !== $data ); |