EDD_SL_Plugin_Updater

Allows plugins to use their own update API.

Defined (2)

The class is defined in the following location(s).

/deprecated/includes/EDD_SL_Plugin_Updater.php  
  1. class EDD_SL_Plugin_Updater { 
  2. private $api_url = ''; 
  3. private $api_data = array(); 
  4. private $name = ''; 
  5. private $slug = ''; 
  6. private $version = ''; 
  7. private $wp_override = false; 
  8. /** 
  9. * Class constructor. 
  10. * @uses plugin_basename() 
  11. * @uses hook() 
  12. * @param string $_api_url The URL pointing to the custom API endpoint. 
  13. * @param string $_plugin_file Path to the plugin file. 
  14. * @param array $_api_data Optional data to send with API calls. 
  15. */ 
  16. public function __construct( $_api_url, $_plugin_file, $_api_data = null ) { 
  17. global $edd_plugin_data; 
  18. $this->api_url = trailingslashit( $_api_url ); 
  19. $this->api_data = $_api_data; 
  20. $this->name = plugin_basename( $_plugin_file ); 
  21. $this->slug = basename( $_plugin_file, '.php' ); 
  22. $this->version = $_api_data['version']; 
  23. $this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false; 
  24. $edd_plugin_data[ $this->slug ] = $this->api_data; 
  25. // Set up hooks. 
  26. $this->init(); 
  27. /** 
  28. * Set up WordPress filters to hook into WP's update process. 
  29. * @uses add_filter() 
  30. * @return void 
  31. */ 
  32. public function init() { 
  33. add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) ); 
  34. add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 ); 
  35. remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10 ); 
  36. add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 ); 
  37. add_action( 'admin_init', array( $this, 'show_changelog' ) ); 
  38. /** 
  39. * Check for Updates at the defined API endpoint and modify the update array. 
  40. * This function dives into the update API just when WordPress creates its update array,  
  41. * then adds a custom API call and injects the custom plugin data retrieved from the API. 
  42. * It is reassembled from parts of the native WordPress plugin update code. 
  43. * See wp-includes/update.php line 121 for the original wp_update_plugins() function. 
  44. * @uses api_request() 
  45. * @param array $_transient_data Update array build by WordPress. 
  46. * @return array Modified update array with custom plugin data. 
  47. */ 
  48. public function check_update( $_transient_data ) { 
  49. global $pagenow; 
  50. if ( ! is_object( $_transient_data ) ) { 
  51. $_transient_data = new stdClass; 
  52. if ( 'plugins.php' == $pagenow && is_multisite() ) { 
  53. return $_transient_data; 
  54. if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) { 
  55. return $_transient_data; 
  56. $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) ); 
  57. if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) { 
  58. if ( version_compare( $this->version, $version_info->new_version, '<' ) ) { 
  59. $_transient_data->response[ $this->name ] = $version_info; 
  60. $_transient_data->last_checked = current_time( 'timestamp' ); 
  61. $_transient_data->checked[ $this->name ] = $this->version; 
  62. return $_transient_data; 
  63. /** 
  64. * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise! 
  65. * @param string $file 
  66. * @param array $plugin 
  67. */ 
  68. public function show_update_notification( $file, $plugin ) { 
  69. if ( is_network_admin() ) { 
  70. return; 
  71. if( ! current_user_can( 'update_plugins' ) ) { 
  72. return; 
  73. if( ! is_multisite() ) { 
  74. return; 
  75. if ( $this->name != $file ) { 
  76. return; 
  77. // Remove our filter on the site transient 
  78. remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 ); 
  79. $update_cache = get_site_transient( 'update_plugins' ); 
  80. $update_cache = is_object( $update_cache ) ? $update_cache : new stdClass(); 
  81. if ( empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) { 
  82. $cache_key = md5( 'edd_plugin_' . sanitize_key( $this->name ) . '_version_info' ); 
  83. $version_info = get_transient( $cache_key ); 
  84. if( false === $version_info ) { 
  85. $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) ); 
  86. set_transient( $cache_key, $version_info, 3600 ); 
  87. if( ! is_object( $version_info ) ) { 
  88. return; 
  89. if( version_compare( $this->version, $version_info->new_version, '<' ) ) { 
  90. $update_cache->response[ $this->name ] = $version_info; 
  91. $update_cache->last_checked = current_time( 'timestamp' ); 
  92. $update_cache->checked[ $this->name ] = $this->version; 
  93. set_site_transient( 'update_plugins', $update_cache ); 
  94. } else { 
  95. $version_info = $update_cache->response[ $this->name ]; 
  96. // Restore our filter 
  97. add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) ); 
  98. if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) { 
  99. // build a plugin list row, with update notification 
  100. $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' ); 
  101. # <tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"> 
  102. echo '<tr class="plugin-update-tr" id="' . $this->slug . '-update" data-slug="' . $this->slug . '" data-plugin="' . $this->slug . '/' . $file . '">'; 
  103. echo '<td colspan="3" class="plugin-update colspanchange">'; 
  104. echo '<div class="update-message notice inline notice-warning notice-alt">'; 
  105. $changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911' ); 
  106. if ( empty( $version_info->download_link ) ) { 
  107. printf( 
  108. __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'easy-digital-downloads' ),  
  109. esc_html( $version_info->name ),  
  110. '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',  
  111. esc_html( $version_info->new_version ),  
  112. '</a>' 
  113. ); 
  114. } else { 
  115. printf( 
  116. __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'easy-digital-downloads' ),  
  117. esc_html( $version_info->name ),  
  118. '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',  
  119. esc_html( $version_info->new_version ),  
  120. '</a>',  
  121. '<a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) ) .'">',  
  122. '</a>' 
  123. ); 
  124. do_action( "in_plugin_update_message-{$file}", $plugin, $version_info ); 
  125. echo '</div></td></tr>'; 
  126. /** 
  127. * Updates information on the "View version x.x details" page with custom data. 
  128. * @uses api_request() 
  129. * @param mixed $_data 
  130. * @param string $_action 
  131. * @param object $_args 
  132. * @return object $_data 
  133. */ 
  134. public function plugins_api_filter( $_data, $_action = '', $_args = null ) { 
  135. if ( $_action != 'plugin_information' ) { 
  136. return $_data; 
  137. if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) { 
  138. return $_data; 
  139. $to_send = array( 
  140. 'slug' => $this->slug,  
  141. 'is_ssl' => is_ssl(),  
  142. 'fields' => array( 
  143. 'banners' => false, // These will be supported soon hopefully 
  144. 'reviews' => false 
  145. ); 
  146. $cache_key = 'edd_api_request_' . substr( md5( serialize( $this->slug ) ), 0, 15 ); 
  147. //Get the transient where we store the api request for this plugin for 24 hours 
  148. $edd_api_request_transient = get_site_transient( $cache_key ); 
  149. //If we have no transient-saved value, run the API, set a fresh transient with the API value, and return that value too right now. 
  150. if ( empty( $edd_api_request_transient ) ) { 
  151. $api_response = $this->api_request( 'plugin_information', $to_send ); 
  152. //Expires in 1 day 
  153. set_site_transient( $cache_key, $api_response, DAY_IN_SECONDS ); 
  154. if ( false !== $api_response ) { 
  155. $_data = $api_response; 
  156. return $_data; 
  157. /** 
  158. * Disable SSL verification in order to prevent download update failures 
  159. * @param array $args 
  160. * @param string $url 
  161. * @return object $array 
  162. */ 
  163. public function http_request_args( $args, $url ) { 
  164. // If it is an https request and we are performing a package download, disable ssl verification 
  165. if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) { 
  166. $args['sslverify'] = false; 
  167. return $args; 
  168. /** 
  169. * Calls the API and, if successfull, returns the object delivered by the API. 
  170. * @uses get_bloginfo() 
  171. * @uses wp_remote_post() 
  172. * @uses is_wp_error() 
  173. * @param string $_action The requested action. 
  174. * @param array $_data Parameters for the API action. 
  175. * @return false|object 
  176. */ 
  177. private function api_request( $_action, $_data ) { 
  178. global $wp_version; 
  179. $data = array_merge( $this->api_data, $_data ); 
  180. if ( $data['slug'] != $this->slug ) { 
  181. return; 
  182. if( $this->api_url == trailingslashit (home_url() ) ) { 
  183. return false; // Don't allow a plugin to ping itself 
  184. $api_params = array( 
  185. 'edd_action' => 'get_version',  
  186. 'license' => ! empty( $data['license'] ) ? $data['license'] : '',  
  187. 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,  
  188. 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,  
  189. 'slug' => $data['slug'],  
  190. 'author' => $data['author'],  
  191. 'url' => home_url() 
  192. ); 
  193. $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) ); 
  194. if ( ! is_wp_error( $request ) ) { 
  195. $request = json_decode( wp_remote_retrieve_body( $request ) ); 
  196. if ( $request && isset( $request->sections ) ) { 
  197. $request->sections = maybe_unserialize( $request->sections ); 
  198. } else { 
  199. $request = false; 
  200. return $request; 
  201. public function show_changelog() { 
  202. global $edd_plugin_data; 
  203. if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) { 
  204. return; 
  205. if( empty( $_REQUEST['plugin'] ) ) { 
  206. return; 
  207. if( empty( $_REQUEST['slug'] ) ) { 
  208. return; 
  209. if( ! current_user_can( 'update_plugins' ) ) { 
  210. wp_die( __( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) ); 
  211. $data = $edd_plugin_data[ $_REQUEST['slug'] ]; 
  212. $cache_key = md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_version_info' ); 
  213. $version_info = get_transient( $cache_key ); 
  214. if( false === $version_info ) { 
  215. $api_params = array( 
  216. 'edd_action' => 'get_version',  
  217. 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,  
  218. 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,  
  219. 'slug' => $_REQUEST['slug'],  
  220. 'author' => $data['author'],  
  221. 'url' => home_url() 
  222. ); 
  223. $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) ); 
  224. if ( ! is_wp_error( $request ) ) { 
  225. $version_info = json_decode( wp_remote_retrieve_body( $request ) ); 
  226. if ( ! empty( $version_info ) && isset( $version_info->sections ) ) { 
  227. $version_info->sections = maybe_unserialize( $version_info->sections ); 
  228. } else { 
  229. $version_info = false; 
  230. set_transient( $cache_key, $version_info, 3600 ); 
  231. if( ! empty( $version_info ) && isset( $version_info->sections['changelog'] ) ) { 
  232. echo '<div style="background:#fff;padding:10px;">' . $version_info->sections['changelog'] . '</div>'; 
  233. exit; 
/includes/Integrations/EDD/EDD_SL_Plugin_Updater.php  
  1. class EDD_SL_Plugin_Updater { 
  2.  
  3. private $api_url = ''; 
  4. private $api_data = array(); 
  5. private $name = ''; 
  6. private $slug = ''; 
  7. private $version = ''; 
  8. private $wp_override = false; 
  9. private $cache_key = ''; 
  10.  
  11. /** 
  12. * Class constructor. 
  13. * @uses plugin_basename() 
  14. * @uses hook() 
  15. * @param string $_api_url The URL pointing to the custom API endpoint. 
  16. * @param string $_plugin_file Path to the plugin file. 
  17. * @param array $_api_data Optional data to send with API calls. 
  18. */ 
  19. public function __construct( $_api_url, $_plugin_file, $_api_data = null ) { 
  20.  
  21. global $edd_plugin_data; 
  22.  
  23. $this->api_url = trailingslashit( $_api_url ); 
  24. $this->api_data = $_api_data; 
  25. $this->name = plugin_basename( $_plugin_file ); 
  26. $this->slug = basename( $_plugin_file, '.php' ); 
  27. $this->version = $_api_data['version']; 
  28. $this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false; 
  29.  
  30. $this->cache_key = md5( serialize( $this->slug . $this->api_data['license'] ) ); 
  31.  
  32. $edd_plugin_data[ $this->slug ] = $this->api_data; 
  33.  
  34. // Set up hooks. 
  35. $this->init(); 
  36.  
  37.  
  38. /** 
  39. * Set up WordPress filters to hook into WP's update process. 
  40. * @uses add_filter() 
  41. * @return void 
  42. */ 
  43. public function init() { 
  44.  
  45. add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) ); 
  46. add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 ); 
  47. remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10 ); 
  48. add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 ); 
  49. add_action( 'admin_init', array( $this, 'show_changelog' ) ); 
  50.  
  51.  
  52. /** 
  53. * Check for Updates at the defined API endpoint and modify the update array. 
  54. * This function dives into the update API just when WordPress creates its update array,  
  55. * then adds a custom API call and injects the custom plugin data retrieved from the API. 
  56. * It is reassembled from parts of the native WordPress plugin update code. 
  57. * See wp-includes/update.php line 121 for the original wp_update_plugins() function. 
  58. * @uses api_request() 
  59. * @param array $_transient_data Update array build by WordPress. 
  60. * @return array Modified update array with custom plugin data. 
  61. */ 
  62. public function check_update( $_transient_data ) { 
  63.  
  64. global $pagenow; 
  65.  
  66. if ( ! is_object( $_transient_data ) ) { 
  67. $_transient_data = new stdClass; 
  68.  
  69. if ( 'plugins.php' == $pagenow && is_multisite() ) { 
  70. return $_transient_data; 
  71.  
  72. if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) { 
  73. return $_transient_data; 
  74.  
  75. $version_info = $this->get_cached_version_info(); 
  76.  
  77. if ( false === $version_info ) { 
  78. $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => ! empty( $this->api_data['beta'] ) ) ); 
  79.  
  80. $this->set_version_info_cache( $version_info ); 
  81.  
  82.  
  83. if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) { 
  84.  
  85. if ( version_compare( $this->version, $version_info->new_version, '<' ) ) { 
  86.  
  87. $_transient_data->response[ $this->name ] = $version_info; 
  88.  
  89.  
  90. $_transient_data->last_checked = current_time( 'timestamp' ); 
  91. $_transient_data->checked[ $this->name ] = $this->version; 
  92.  
  93.  
  94. return $_transient_data; 
  95.  
  96. /** 
  97. * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise! 
  98. * @param string $file 
  99. * @param array $plugin 
  100. */ 
  101. public function show_update_notification( $file, $plugin ) { 
  102.  
  103. if ( is_network_admin() ) { 
  104. return; 
  105.  
  106. if( ! current_user_can( 'update_plugins' ) ) { 
  107. return; 
  108.  
  109. if( ! is_multisite() ) { 
  110. return; 
  111.  
  112. if ( $this->name != $file ) { 
  113. return; 
  114.  
  115. // Remove our filter on the site transient 
  116. remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 ); 
  117.  
  118. $update_cache = get_site_transient( 'update_plugins' ); 
  119.  
  120. $update_cache = is_object( $update_cache ) ? $update_cache : new stdClass(); 
  121.  
  122. if ( empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) { 
  123.  
  124. $version_info = $this->get_cached_version_info(); 
  125.  
  126. if ( false === $version_info ) { 
  127. $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => ! empty( $this->api_data['beta'] ) ) ); 
  128.  
  129. $this->set_version_info_cache( $version_info ); 
  130.  
  131. if ( ! is_object( $version_info ) ) { 
  132. return; 
  133.  
  134. if ( version_compare( $this->version, $version_info->new_version, '<' ) ) { 
  135.  
  136. $update_cache->response[ $this->name ] = $version_info; 
  137.  
  138.  
  139. $update_cache->last_checked = current_time( 'timestamp' ); 
  140. $update_cache->checked[ $this->name ] = $this->version; 
  141.  
  142. set_site_transient( 'update_plugins', $update_cache ); 
  143.  
  144. } else { 
  145.  
  146. $version_info = $update_cache->response[ $this->name ]; 
  147.  
  148.  
  149. // Restore our filter 
  150. add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) ); 
  151.  
  152. if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) { 
  153.  
  154. // build a plugin list row, with update notification 
  155. $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' ); 
  156. # <tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"> 
  157. echo '<tr class="plugin-update-tr" id="' . $this->slug . '-update" data-slug="' . $this->slug . '" data-plugin="' . $this->slug . '/' . $file . '">'; 
  158. echo '<td colspan="3" class="plugin-update colspanchange">'; 
  159. echo '<div class="update-message notice inline notice-warning notice-alt">'; 
  160.  
  161. $changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911' ); 
  162.  
  163. if ( empty( $version_info->download_link ) ) { 
  164. printf( 
  165. __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'easy-digital-downloads' ),  
  166. esc_html( $version_info->name ),  
  167. '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',  
  168. esc_html( $version_info->new_version ),  
  169. '</a>' 
  170. ); 
  171. } else { 
  172. printf( 
  173. __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'easy-digital-downloads' ),  
  174. esc_html( $version_info->name ),  
  175. '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',  
  176. esc_html( $version_info->new_version ),  
  177. '</a>',  
  178. '<a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) ) .'">',  
  179. '</a>' 
  180. ); 
  181.  
  182. do_action( "in_plugin_update_message-{$file}", $plugin, $version_info ); 
  183.  
  184. echo '</div></td></tr>'; 
  185.  
  186. /** 
  187. * Updates information on the "View version x.x details" page with custom data. 
  188. * @uses api_request() 
  189. * @param mixed $_data 
  190. * @param string $_action 
  191. * @param object $_args 
  192. * @return object $_data 
  193. */ 
  194. public function plugins_api_filter( $_data, $_action = '', $_args = null ) { 
  195.  
  196. if ( $_action != 'plugin_information' ) { 
  197.  
  198. return $_data; 
  199.  
  200.  
  201. if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) { 
  202.  
  203. return $_data; 
  204.  
  205.  
  206. $to_send = array( 
  207. 'slug' => $this->slug,  
  208. 'is_ssl' => is_ssl(),  
  209. 'fields' => array( 
  210. 'banners' => array(),  
  211. 'reviews' => false 
  212. ); 
  213.  
  214. $cache_key = 'edd_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] ) ); 
  215.  
  216. // Get the transient where we store the api request for this plugin for 24 hours 
  217. $edd_api_request_transient = $this->get_cached_version_info( $cache_key ); 
  218.  
  219. //If we have no transient-saved value, run the API, set a fresh transient with the API value, and return that value too right now. 
  220. if ( empty( $edd_api_request_transient ) ) { 
  221.  
  222. $api_response = $this->api_request( 'plugin_information', $to_send ); 
  223.  
  224. // Expires in 3 hours 
  225. $this->set_version_info_cache( $api_response, $cache_key ); 
  226.  
  227. if ( false !== $api_response ) { 
  228. $_data = $api_response; 
  229.  
  230. } else { 
  231. $_data = $edd_api_request_transient; 
  232.  
  233. return $_data; 
  234.  
  235. /** 
  236. * Disable SSL verification in order to prevent download update failures 
  237. * @param array $args 
  238. * @param string $url 
  239. * @return object $array 
  240. */ 
  241. public function http_request_args( $args, $url ) { 
  242. // If it is an https request and we are performing a package download, disable ssl verification 
  243. if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) { 
  244. $args['sslverify'] = false; 
  245. return $args; 
  246.  
  247. /** 
  248. * Calls the API and, if successfull, returns the object delivered by the API. 
  249. * @uses get_bloginfo() 
  250. * @uses wp_remote_post() 
  251. * @uses is_wp_error() 
  252. * @param string $_action The requested action. 
  253. * @param array $_data Parameters for the API action. 
  254. * @return false|object 
  255. */ 
  256. private function api_request( $_action, $_data ) { 
  257.  
  258. global $wp_version; 
  259.  
  260. $data = array_merge( $this->api_data, $_data ); 
  261.  
  262. if ( $data['slug'] != $this->slug ) { 
  263. return; 
  264.  
  265. if( $this->api_url == trailingslashit (home_url() ) ) { 
  266. return false; // Don't allow a plugin to ping itself 
  267.  
  268. $api_params = array( 
  269. 'edd_action' => 'get_version',  
  270. 'license' => ! empty( $data['license'] ) ? $data['license'] : '',  
  271. 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,  
  272. 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,  
  273. 'slug' => $data['slug'],  
  274. 'author' => $data['author'],  
  275. 'url' => home_url(),  
  276. 'beta' => ! empty( $data['beta'] ),  
  277. ); 
  278.  
  279. $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) ); 
  280.  
  281. if ( ! is_wp_error( $request ) ) { 
  282. $request = json_decode( wp_remote_retrieve_body( $request ) ); 
  283.  
  284. if ( $request && isset( $request->sections ) ) { 
  285. $request->sections = maybe_unserialize( $request->sections ); 
  286. } else { 
  287. $request = false; 
  288.  
  289. if ( $request && isset( $request->banners ) ) { 
  290. $request->banners = maybe_unserialize( $request->banners ); 
  291.  
  292. if( ! empty( $request ) && is_array( $request->sections ) ) { 
  293. foreach( $request->sections as $key => $section ) { 
  294. $request->$key = (array) $section; 
  295.  
  296. return $request; 
  297.  
  298. public function show_changelog() { 
  299.  
  300. global $edd_plugin_data; 
  301.  
  302. if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) { 
  303. return; 
  304.  
  305. if( empty( $_REQUEST['plugin'] ) ) { 
  306. return; 
  307.  
  308. if( empty( $_REQUEST['slug'] ) ) { 
  309. return; 
  310.  
  311. if( ! current_user_can( 'update_plugins' ) ) { 
  312. wp_die( __( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) ); 
  313.  
  314. $data = $edd_plugin_data[ $_REQUEST['slug'] ]; 
  315. $cache_key = md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_version_info' ); 
  316. $version_info = $this->get_cached_version_info( $cache_key ); 
  317.  
  318. if( false === $version_info ) { 
  319.  
  320. $api_params = array( 
  321. 'edd_action' => 'get_version',  
  322. 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,  
  323. 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,  
  324. 'slug' => $_REQUEST['slug'],  
  325. 'author' => $data['author'],  
  326. 'url' => home_url(),  
  327. 'beta' => ! empty( $data['beta'] ) 
  328. ); 
  329.  
  330. $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) ); 
  331.  
  332. if ( ! is_wp_error( $request ) ) { 
  333. $version_info = json_decode( wp_remote_retrieve_body( $request ) ); 
  334.  
  335.  
  336. if ( ! empty( $version_info ) && isset( $version_info->sections ) ) { 
  337. $version_info->sections = maybe_unserialize( $version_info->sections ); 
  338. } else { 
  339. $version_info = false; 
  340.  
  341. if( ! empty( $version_info ) ) { 
  342. foreach( $version_info->sections as $key => $section ) { 
  343. $version_info->$key = (array) $section; 
  344.  
  345. $this->set_version_info_cache( $version_info, $cache_key ); 
  346.  
  347.  
  348. if( ! empty( $version_info ) && isset( $version_info->sections['changelog'] ) ) { 
  349. echo '<div style="background:#fff;padding:10px;">' . $version_info->sections['changelog'] . '</div>'; 
  350.  
  351. exit; 
  352.  
  353. public function get_cached_version_info( $cache_key = '' ) { 
  354. return false; 
  355. if( empty( $cache_key ) ) { 
  356. $cache_key = $this->cache_key; 
  357.  
  358. $cache = get_option( $cache_key ); 
  359.  
  360. if( empty( $cache['timeout'] ) || current_time( 'timestamp' ) > $cache['timeout'] ) { 
  361. return false; // Cache is expired 
  362.  
  363. return json_decode( $cache['value'] ); 
  364.  
  365.  
  366. public function set_version_info_cache( $value = '', $cache_key = '' ) { 
  367.  
  368. if( empty( $cache_key ) ) { 
  369. $cache_key = $this->cache_key; 
  370.  
  371. $data = array( 
  372. 'timeout' => strtotime( '+3 hours', current_time( 'timestamp' ) ),  
  373. 'value' => json_encode( $value ) 
  374. ); 
  375.  
  376. update_option( $cache_key, $data ); 
  377.  
  378.