SimpleCalendarAdminUpdater

Add-ons updater.

Defined (1)

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

/includes/admin/updater.php  
  1. class Updater { 
  2.  
  3. /** 
  4. * API Url. 
  5. * @access private 
  6. * @var string 
  7. */ 
  8. private $api_url = ''; 
  9.  
  10. /** 
  11. * API data. 
  12. * @access private 
  13. * @var array|null 
  14. */ 
  15. private $api_data = array(); 
  16.  
  17. /** 
  18. * Name. 
  19. * @access private 
  20. * @var string 
  21. */ 
  22. private $name = ''; 
  23.  
  24. /** 
  25. * Slug. 
  26. * @access private 
  27. * @var string 
  28. */ 
  29. private $slug = ''; 
  30.  
  31. /** 
  32. * Version. 
  33. * @access private 
  34. * @var string 
  35. */ 
  36. private $version = ''; 
  37.  
  38. /** 
  39. * Constructor. 
  40. * @since 3.0.0 
  41. * @param string $_api_url The URL pointing to the custom API endpoint. 
  42. * @param string $_plugin_file Path to the plugin file. 
  43. * @param array $_api_data Optional data to send with API calls. 
  44. */ 
  45. public function __construct( $_api_url, $_plugin_file, $_api_data = null ) { 
  46.  
  47. $this->api_url = trailingslashit( $_api_url ); 
  48. $this->api_data = $_api_data; 
  49. $this->name = plugin_basename( $_plugin_file ); 
  50. $this->slug = basename( $_plugin_file, '.php' ); 
  51. $this->version = $_api_data['version']; 
  52.  
  53. // Set up hooks. 
  54. $this->init(); 
  55. add_action( 'admin_init', array( $this, 'show_changelog' ) ); 
  56.  
  57. /** 
  58. * Hook into WordPress update process. 
  59. * @since 3.0.0 
  60. * @return void 
  61. */ 
  62. public function init() { 
  63. add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) ); 
  64. add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 ); 
  65. remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10 ); 
  66. add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 ); 
  67.  
  68. /** 
  69. * Check for Updates at the defined API endpoint and modify the update array. 
  70. * This function dives into the update API just when WordPress creates its update array,  
  71. * then adds a custom API call and injects the custom plugin data retrieved from the API. 
  72. * It is reassembled from parts of the native WordPress plugin update code. 
  73. * See wp-includes/update.php line 121 for the original wp_update_plugins() function. 
  74. * @since 3.0.0 
  75. * @param array $_transient_data Update array build by WordPress. 
  76. * @return array|\stdClass Modified update array with custom plugin data. 
  77. */ 
  78. public function check_update( $_transient_data ) { 
  79.  
  80. global $pagenow; 
  81.  
  82. if ( ! is_object( $_transient_data ) ) { 
  83. $_transient_data = new \stdClass(); 
  84.  
  85. if ( 'plugins.php' == $pagenow && is_multisite() ) { 
  86. return $_transient_data; 
  87.  
  88. if ( empty( $_transient_data->response ) || empty( $_transient_data->response[ $this->name ] ) ) { 
  89.  
  90. $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) ); 
  91.  
  92. if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) { 
  93.  
  94. if ( version_compare( $this->version, $version_info->new_version, '<' ) ) { 
  95. $_transient_data->response[ $this->name ] = $version_info; 
  96.  
  97. $_transient_data->last_checked = time(); 
  98. $_transient_data->checked[ $this->name ] = $this->version; 
  99.  
  100.  
  101. return $_transient_data; 
  102.  
  103. /** 
  104. * Show update notification row. 
  105. * Needed for multisite subsites, because WordPress won't tell otherwise. 
  106. * @since 3.0.0 
  107. * @param string $file 
  108. * @param array $plugin 
  109. */ 
  110. public function show_update_notification( $file, $plugin ) { 
  111.  
  112. if ( ! current_user_can( 'update_plugins' ) ) { 
  113. return; 
  114.  
  115. if ( ! is_multisite() ) { 
  116. return; 
  117.  
  118. if ( $this->name != $file ) { 
  119. return; 
  120.  
  121. // Remove our filter on the site transient 
  122. remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 ); 
  123.  
  124. $update_cache = get_site_transient( 'update_plugins' ); 
  125.  
  126. if ( ! is_object( $update_cache ) || empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) { 
  127.  
  128. $cache_key = md5( 'edd_plugin_' .sanitize_key( $this->name ) . '_version_info' ); 
  129. $version_info = get_transient( $cache_key ); 
  130.  
  131. if ( false === $version_info ) { 
  132.  
  133. $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) ); 
  134.  
  135. set_transient( $cache_key, $version_info, 3600 ); 
  136.  
  137. if ( ! is_object( $version_info ) ) { 
  138. return; 
  139.  
  140. if ( version_compare( $this->version, $version_info->new_version, '<' ) ) { 
  141. $update_cache->response[ $this->name ] = $version_info; 
  142.  
  143. $update_cache->last_checked = time(); 
  144. $update_cache->checked[ $this->name ] = $this->version; 
  145.  
  146. set_site_transient( 'update_plugins', $update_cache ); 
  147.  
  148. } else { 
  149.  
  150. $version_info = $update_cache->response[ $this->name ]; 
  151.  
  152.  
  153. // Restore our filter 
  154. add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) ); 
  155.  
  156. if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) { 
  157.  
  158. // build a plugin list row, with update notification 
  159. $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' ); 
  160. echo '<tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">'; 
  161.  
  162. $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' ); 
  163.  
  164. if ( empty( $version_info->download_link ) ) { 
  165. printf( 
  166. __( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a>.', 'google-calendar-events' ),  
  167. esc_html( $version_info->name ),  
  168. esc_url( $changelog_link ),  
  169. esc_html( $version_info->new_version ) 
  170. ); 
  171. } else { 
  172. printf( 
  173. __( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a> or <a href="%4$s">update now</a>.', 'google-calendar-events' ),  
  174. esc_html( $version_info->name ),  
  175. esc_url( $changelog_link ),  
  176. esc_html( $version_info->new_version ),  
  177. esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) ) 
  178. ); 
  179.  
  180. echo '</div></td></tr>'; 
  181.  
  182.  
  183. /** 
  184. * Updates information on the "View version x.x details" page with custom data. 
  185. * @since 3.0.0 
  186. * @param mixed $_data 
  187. * @param string $_action 
  188. * @param object $_args 
  189. * @return object 
  190. */ 
  191. public function plugins_api_filter( $_data, $_action = '', $_args = null ) { 
  192.  
  193. if ( 'plugin_information' != $_action ) { 
  194. return $_data; 
  195.  
  196. if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) { 
  197. return $_data; 
  198.  
  199. $to_send = array( 
  200. 'slug' => $this->slug,  
  201. 'is_ssl' => is_ssl(),  
  202. 'fields' => array( 
  203. 'banners' => false, // These will be supported soon hopefully 
  204. 'reviews' => false 
  205. ),  
  206. ); 
  207.  
  208. $api_response = $this->api_request( 'plugin_information', $to_send ); 
  209.  
  210. if ( false !== $api_response ) { 
  211. $_data = $api_response; 
  212.  
  213. return $_data; 
  214.  
  215.  
  216. /** 
  217. * Disable SSL verification in order to prevent download update failures 
  218. * @since 3.0.0 
  219. * @param array $args 
  220. * @param string $url 
  221. * @return object|array $array 
  222. */ 
  223. public function http_request_args( $args, $url ) { 
  224. // If it is an https request and we are performing a package download, disable ssl verification 
  225. if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) { 
  226. $args['sslverify'] = false; 
  227. return $args; 
  228.  
  229. /** 
  230. * Calls the API and, if successful, returns the object delivered by the API. 
  231. * @since 3.0.0 
  232. * @param string $_action The requested action. 
  233. * @param array $_data Parameters for the API action. 
  234. * @return false|object 
  235. */ 
  236. private function api_request( $_action, $_data ) { 
  237.  
  238. global $wp_version; 
  239.  
  240. $data = array_merge( $this->api_data, $_data ); 
  241.  
  242. if ( $data['slug'] != $this->slug ) { 
  243. return; 
  244.  
  245. if ( empty( $data['license'] ) ) { 
  246. return; 
  247.  
  248. if ( $this->api_url == home_url() ) { 
  249. return false; // Don't allow a plugin to ping itself 
  250.  
  251. $api_params = array( 
  252. 'edd_action' => 'get_version',  
  253. 'license' => $data['license'],  
  254. 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,  
  255. 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,  
  256. 'slug' => $data['slug'],  
  257. 'author' => $data['author'],  
  258. 'url' => home_url() 
  259. ); 
  260.  
  261. $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) ); 
  262.  
  263. if ( ! is_wp_error( $request ) ) { 
  264. $request = json_decode( wp_remote_retrieve_body( $request ) ); 
  265.  
  266. if ( $request && isset( $request->sections ) ) { 
  267. $request->sections = maybe_unserialize( $request->sections ); 
  268. } else { 
  269. $request = false; 
  270.  
  271. return $request; 
  272.  
  273. /** 
  274. * Show changelog. 
  275. * @since 3.0.0 
  276. */ 
  277. public function show_changelog() { 
  278.  
  279. if ( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) { 
  280. return; 
  281.  
  282. if ( empty( $_REQUEST['plugin'] ) ) { 
  283. return; 
  284.  
  285. if ( empty( $_REQUEST['slug'] ) ) { 
  286. return; 
  287.  
  288. if ( ! current_user_can( 'update_plugins' ) ) { 
  289. wp_die( __( 'You do not have permission to install plugin updates', 'google-calendar-events' ), __( 'Error', 'google-calendar-events' ), array( 'response' => 403 ) ); 
  290.  
  291. $response = $this->api_request( 'plugin_latest_version', array( 'slug' => $_REQUEST['slug'] ) ); 
  292.  
  293. if ( $response && isset( $response->sections['changelog'] ) ) { 
  294. echo '<div style="background:#fff;padding:10px;">' . $response->sections['changelog'] . '</div>'; 
  295.  
  296. exit; 
  297.