PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
← All changes | libraries/freemius/includes/class-fs-plugin-updater.php +81 -48 2.1.7 → 3.4 View file →
@@ -36,8 +36,10 @@
36 36 private $_translation_updates;
37 37
38 38 private static $_upgrade_basename = null;
39 39
40 + const UPDATES_CHECK_CACHE_EXPIRATION = ( WP_FS__TIME_24_HOURS_IN_SEC / 24 );
41 +
40 42 #--------------------------------------------------------------------------------
41 43 #region Singleton
42 44 #--------------------------------------------------------------------------------
43 45
@@ -103,8 +105,10 @@
103 105 ), 11, 2 );
104 106
105 107 if ( ! $this->_fs->has_any_active_valid_license() ) {
106 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' ) );
107 111 }
108 112
109 113 if ( ! WP_FS__IS_PRODUCTION_MODE ) {
110 114 add_filter( 'http_request_host_is_external', array(
@@ -128,15 +132,48 @@
128 132 }
129 133
130 134 /**
131 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)
132 172 * @since 2.1.4
133 173 */
134 174 function catch_plugin_information_dialog_contents() {
135 - if (
136 - 'plugin-information' !== fs_request_get( 'tab', false ) ||
137 - $this->_fs->get_slug() !== fs_request_get_raw( 'plugin', false )
138 - ) {
175 + if ( ! $this->is_plugin_information_dialog_for_plugin() ) {
139 176 return;
140 177 }
141 178
142 179 add_action( 'admin_footer', array( &$this, 'edit_and_echo_plugin_information_dialog_contents' ), 0, 1 );
@@ -502,38 +539,40 @@
502 539 ) {
503 540 return $transient_data;
504 541 }
505 542
543 + // Alias.
544 + $basename = $this->_fs->premium_plugin_basename();
545 +
506 546 global $wp_current_filter;
507 547
508 - $current_plugin_version = $this->_fs->get_plugin_version();
509 -
510 - if ( ! empty( $wp_current_filter ) && 'upgrader_process_complete' === $wp_current_filter[0] ) {
511 - if (
512 - is_null( $this->_update_details ) ||
513 - ( is_object( $this->_update_details ) && $this->_update_details->new_version !== $current_plugin_version )
514 - ) {
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 ) && (
515 557 /**
516 - * After an update, clear the stored update details and reparse the plugin's main file in order to get
517 - * the updated version's information and prevent the previous update information from showing up on the
518 - * updates page.
519 - *
520 - * @author Leo Fajardo (@leorw)
521 - * @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.
522 560 */
523 - $this->_update_details = null;
524 - $current_plugin_version = $this->_fs->get_plugin_version( true );
525 - }
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;
526 570 }
527 571
528 572 if ( ! isset( $this->_update_details ) ) {
529 573 // Get plugin's newest update.
530 - $new_version = $this->_fs->get_update(
531 - false,
532 - fs_request_get_bool( 'force-check' ),
533 - WP_FS__TIME_24_HOURS_IN_SEC / 24,
534 - $current_plugin_version
535 - );
574 + $new_version = $this->_fs->get_update( false, fs_request_get_bool( 'force-check' ) );
536 575
537 576 $this->_update_details = false;
538 577
539 578 if ( is_object( $new_version ) && $this->is_new_version_premium( $new_version ) ) {
@@ -549,11 +588,8 @@
549 588 $this->_update_details = $this->get_update_details( $new_version );
550 589 }
551 590 }
552 591
553 - // Alias.
554 - $basename = $this->_fs->premium_plugin_basename();
555 -
556 592 if ( is_object( $this->_update_details ) ) {
557 593 if ( isset( $transient_data->no_update ) ) {
558 594 unset( $transient_data->no_update[ $basename ] );
559 595 }
@@ -613,9 +649,9 @@
613 649 }
614 650
615 651 $slug = $this->_fs->get_slug();
616 652
617 - if ( $this->_fs->is_org_repo_compliant() && $this->_fs->is_freemium() ) {
653 + if ( $this->can_fetch_data_from_wp_org() ) {
618 654 if ( ! isset( $this->_translation_updates ) ) {
619 655 $this->_translation_updates = array();
620 656
621 657 $translation_updates = $this->fetch_wp_org_module_translation_updates( $module_type, $slug );
@@ -682,18 +718,10 @@
682 718 'default' => $icon,
683 719 );
684 720 }
685 721
686 - if ( $this->_fs->is_premium() ) {
687 - $latest_tag = $this->_fs->_fetch_latest_version( $this->_fs->get_id(), false );
688 -
689 - if (
690 - isset( $latest_tag->readme ) &&
691 - isset( $latest_tag->readme->upgrade_notice ) &&
692 - ! empty( $latest_tag->readme->upgrade_notice )
693 - ) {
694 - $update->upgrade_notice = $latest_tag->readme->upgrade_notice;
695 - }
722 + if ( $this->_fs->is_premium() && ! empty( $new_version->upgrade_notice ) ) {
723 + $update->upgrade_notice = $new_version->upgrade_notice;
696 724 }
697 725
698 726 $update->{$this->_fs->get_module_type()} = $this->_fs->get_plugin_basename();
699 727
@@ -708,15 +736,10 @@
708 736 *
709 737 * @return bool
710 738 */
711 739 private function is_new_version_premium( FS_Plugin_Tag $new_version ) {
712 - $query_str = parse_url( $new_version->url, PHP_URL_QUERY );
713 - if ( empty( $query_str ) ) {
714 - return false;
715 - }
740 + $params = fs_parse_url_params( $new_version->url );
716 741
717 - parse_str( $query_str, $params );
718 -
719 742 return ( isset( $params['is_premium'] ) && 'true' == $params['is_premium'] );
720 743 }
721 744
722 745 /**
@@ -876,8 +899,18 @@
876 899 return $res;
877 900 }
878 901
879 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 + /**
880 913 * Fetches module translation updates from wordpress.org.
881 914 *
882 915 * @author Leo Fajardo (@leorw)
883 916 * @since 2.1.2
@@ -1059,9 +1092,9 @@
1059 1092 $is_addon = true;
1060 1093 }
1061 1094
1062 1095 $plugin_in_repo = false;
1063 - if ( ! $is_addon ) {
1096 + if ( ! $is_addon && $this->can_fetch_data_from_wp_org() ) {
1064 1097 // Try to fetch info from .org repository.
1065 1098 $data = self::_fetch_plugin_info_from_repository( $action, $args );
1066 1099
1067 1100 $plugin_in_repo = ( false !== $data );
@@ -1192,9 +1225,9 @@
1192 1225 *
1193 1226 * @return object
1194 1227 */
1195 1228 private function get_latest_download_details( $addon_id = false, $newer_than = false, $fetch_readme = true ) {
1196 - return $this->_fs->_fetch_latest_version( $addon_id, true, WP_FS__TIME_24_HOURS_IN_SEC, $newer_than, $fetch_readme );
1229 + return $this->_fs->_fetch_latest_version( $addon_id, true, FS_Plugin_Updater::UPDATES_CHECK_CACHE_EXPIRATION, $newer_than, $fetch_readme );
1197 1230 }
1198 1231
1199 1232 /**
1200 1233 * Checks if a given basename has a matching folder name