PluginProbe ʕ •ᴥ•ʔ
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel / trunk
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel vtrunk
trunk 0.9.0 0.9.1 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0 1.2.1 1.2.10 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.14 1.4.15 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0
wp-all-export / addon-api / classes / updater.php
wp-all-export / addon-api / classes Last commit date
base.php 4 weeks ago exporter.php 4 weeks ago helpers.php 4 weeks ago resolver.php 4 weeks ago updater.php 4 weeks ago view.php 4 weeks ago
updater.php
400 lines
1 <?php
2
3 namespace Wpae\AddonAPI;
4
5 if ( ! defined( 'ABSPATH' ) ) exit;
6
7 class PMXE_Addon_Updater {
8 private $api_url = '';
9 private $api_data = array();
10 private $name = '';
11 private $slug = '';
12 private $_plugin_file = '';
13 private $did_check = false;
14 private $version;
15
16 /**
17 * Class constructor.
18 *
19 * @param string $_api_url The URL pointing to the custom API endpoint.
20 * @param string $_plugin_file Path to the plugin file.
21 * @param array $_api_data Optional data to send with API calls.
22 *
23 * @return void
24 * @uses plugin_basename()
25 * @uses hook()
26 *
27 */
28 function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
29 $this->api_url = trailingslashit( $_api_url );
30 $this->api_data = urlencode_deep( $_api_data );
31 $this->name = plugin_basename( $_plugin_file );
32 $this->slug = basename( $_plugin_file, '.php' );
33
34 $this->version = $_api_data['version'];
35 $this->_plugin_file = $_plugin_file;
36
37 // Set up hooks.
38 $this->init();
39 add_action( 'admin_init', array( $this, 'show_changelog' ) );
40 }
41
42 /**
43 * Set up WordPress filters to hook into WP's update process.
44 *
45 * @return void
46 * @uses add_filter()
47 *
48 */
49 public function init() {
50
51 add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 21 );
52 add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
53
54 add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
55 add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 );
56 }
57
58 /**
59 * Show row meta on the plugin screen.
60 *
61 * @param mixed $links Plugin Row Meta
62 * @param mixed $file Plugin Base file
63 *
64 * @return array
65 */
66 public function plugin_row_meta( $links, $file ) {
67 if ( $file == $this->name ) {
68 $row_meta = array(
69 'changelog' => '<a href="' . admin_url( 'plugin-install.php?tab=plugin-information&plugin=wpai-acf-add-on&section=changelog&TB_iframe=true&width=600&height=800' ) . '" class="thickbox open-plugin-details-modal" title="' . esc_attr( __( 'View WP All Import - ACF Add-On Pro Changelog', 'wp-all-export' ) ) . '">' . __( 'Changelog', 'wp-all-export' ) . '</a>',
70 );
71
72 return array_merge( $links, $row_meta );
73 }
74
75 return (array) $links;
76 }
77
78 /**
79 * Check for Updates at the defined API endpoint and modify the update array.
80 *
81 * This function dives into the update API just when WordPress creates its update array,
82 * then adds a custom API call and injects the custom plugin data retrieved from the API.
83 * It is reassembled from parts of the native WordPress plugin update code.
84 * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
85 *
86 * @param array $_transient_data Update array build by WordPress.
87 *
88 * @return array Modified update array with custom plugin data.
89 * @uses api_request()
90 *
91 */
92 function check_update( $_transient_data ) {
93
94 global $pagenow;
95
96 if ( ! is_object( $_transient_data ) ) {
97 $_transient_data = new \stdClass;
98 }
99
100 if ( 'plugins.php' == $pagenow && is_multisite() ) {
101 return $_transient_data;
102 }
103
104 if ( empty( $_transient_data ) ) {
105 return $_transient_data;
106 }
107
108 if ( empty( $_transient_data->response ) || empty( $_transient_data->response[ $this->name ] ) ) {
109
110 $cache_key = md5( 'edd_plugin_' . sanitize_key( $this->name ) . '_version_info' );
111 $version_info = get_transient( $cache_key );
112
113 if ( false === $version_info ) {
114
115 $version_info = $this->api_request( 'check_update', array( 'slug' => $this->slug ) );
116 set_transient( $cache_key, $version_info, 3600 * 24 );
117 }
118
119 if ( ! is_object( $version_info ) ) {
120 return $_transient_data;
121 }
122
123 if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
124
125 $this->did_check = true;
126
127 if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
128
129 $_transient_data->response[ $this->name ] = $version_info;
130 }
131
132 $_transient_data->last_checked = time();
133 $_transient_data->checked[ $this->name ] = $this->version;
134 }
135 }
136
137 return $_transient_data;
138 }
139
140 /**
141 * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
142 *
143 * @param string $file
144 * @param array $plugin
145 */
146 public function show_update_notification( $file, $plugin ) {
147
148 if ( ! current_user_can( 'update_plugins' ) ) {
149 return;
150 }
151
152 if ( ! is_multisite() ) {
153 return;
154 }
155
156 if ( $this->name != $file ) {
157 return;
158 }
159
160 // Remove our filter on the site transient
161 remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 21 );
162
163 $update_cache = get_site_transient( 'update_plugins' );
164
165 if ( ! is_object( $update_cache ) || empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
166
167 $cache_key = md5( 'edd_plugin_' . sanitize_key( $this->name ) . '_version_info' );
168 $version_info = get_transient( $cache_key );
169
170 if ( false === $version_info ) {
171
172 $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
173
174 set_transient( $cache_key, $version_info, 3600 * 24 );
175 }
176
177
178 if ( ! is_object( $version_info ) ) {
179 return;
180 }
181
182 if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
183
184 $update_cache->response[ $this->name ] = $version_info;
185 }
186
187 $update_cache->last_checked = time();
188 $update_cache->checked[ $this->name ] = $this->version;
189
190 set_site_transient( 'update_plugins', $update_cache );
191 } else {
192
193 $version_info = $update_cache->response[ $this->name ];
194 }
195
196 // Restore our filter
197 add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 21 );
198
199 if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) {
200
201 // build a plugin list row, with update notification
202 $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
203 echo '<tr class="plugin-update-tr"><td colspan="' . esc_attr( $wp_list_table->get_column_count() ) . '" class="plugin-update colspanchange"><div class="update-message">';
204
205 $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' );
206
207 if ( empty( $version_info->download_link ) ) {
208 echo wp_kses_post( sprintf(
209 /* translators: 1: plugin name, 2: changelog link, 3: new version */
210 __( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a>.', 'wp-all-export' ),
211 esc_html( $version_info->name ),
212 esc_url( $changelog_link ),
213 esc_html( $version_info->new_version )
214 ) );
215 } else {
216 echo wp_kses_post( sprintf(
217 /* translators: 1: plugin name, 2: changelog link, 3: new version, 4: update link */
218 __( '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>.', 'wp-all-export' ),
219 esc_html( $version_info->name ),
220 esc_url( $changelog_link ),
221 esc_html( $version_info->new_version ),
222 esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) )
223 ) );
224 }
225
226 echo '</div></td></tr>';
227 }
228 }
229
230 /**
231 * Updates information on the "View version x.x details" page with custom data.
232 *
233 * @param mixed $_data
234 * @param string $_action
235 * @param object $_args
236 *
237 * @return object $_data
238 * @uses api_request()
239 *
240 */
241 function plugins_api_filter( $_data, $_action = '', $_args = null ) {
242
243
244 if ( $_action != 'plugin_information' ) {
245
246 return $_data;
247 }
248
249 if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
250
251 return $_data;
252 }
253
254 $cache_key = md5( 'edd_plugin_' . sanitize_key( $this->name ) . '_version_info' );
255 $_data = get_transient( $cache_key );
256
257 if ( false === $_data ) {
258
259 $to_send = array(
260 'slug' => $this->slug,
261 'is_ssl' => is_ssl(),
262 'fields' => array(
263 'banners' => false, // These will be supported soon hopefully
264 'reviews' => false
265 )
266 );
267
268 $api_response = $this->api_request( 'plugin_information', $to_send );
269
270 if ( false !== $api_response ) {
271 $_data = $api_response;
272 set_transient( $cache_key, $_data, 3600 * 24 );
273 }
274 }
275
276 return $_data;
277 }
278
279
280 /**
281 * Disable SSL verification in order to prevent download update failures
282 *
283 * @param array $args
284 * @param string $url
285 *
286 * @return object $array
287 */
288 function http_request_args( $args, $url ) {
289 // If it is an https request and we are performing a package download, disable ssl verification
290 if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
291 $args['sslverify'] = false;
292 }
293
294 return $args;
295 }
296
297 /**
298 * Calls the API and, if successfull, returns the object delivered by the API.
299 *
300 * @param string $_action The requested action.
301 * @param array $_data Parameters for the API action.
302 *
303 * @return false||object
304 * @uses get_bloginfo()
305 * @uses wp_remote_post()
306 * @uses is_wp_error()
307 *
308 */
309 private function api_request( $_action, $_data ) {
310
311 global $wp_version;
312
313 $data = array_merge( $this->api_data, $_data );
314
315 if ( $data['slug'] != $this->slug ) {
316 return;
317 }
318
319 /*if ( empty( $data['license'] ) )
320 return;*/
321
322 if ( $this->api_url == home_url() ) {
323 return false; // Don't allow a plugin to ping itself
324 }
325
326 $api_params = array(
327 'edd_action' => 'get_version',
328 'license' => false,
329 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
330 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
331 'slug' => $data['slug'],
332 'plugin' => $this->_plugin_file,
333 'author' => $data['author'],
334 'url' => home_url(),
335 'version' => $this->version
336 );
337
338 // Send request based on provided API URL.
339 if ( strpos( $this->api_url, 'update.' ) !== false ) {
340 $request = wp_remote_get( esc_url_raw( add_query_arg( $api_params, $this->api_url . 'check_version/?' ) ), array( 'timeout' => 15,
341 'sslverify' => true
342 ) );
343 } else {
344 $request = wp_remote_post( $this->api_url, array( 'timeout' => 15,
345 'sslverify' => true,
346 'body' => $api_params
347 ) );
348 }
349
350 if ( ! is_wp_error( $request ) ) {
351 $request = json_decode( wp_remote_retrieve_body( $request ) );
352 }
353
354 if ( $request && isset( $request->banners ) ) {
355 $request->banners = maybe_unserialize( $request->banners );
356 }
357
358 if ( $request && isset( $request->sections ) ) {
359 $request->sections = maybe_unserialize( $request->sections );
360 } else {
361 $request = false;
362 }
363
364 return $request;
365 }
366
367 public function show_changelog() {
368
369
370 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- capability check via current_user_can; nonce handled by WP core update flow
371 if ( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
372 return;
373 }
374
375 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- capability check via current_user_can; nonce handled by WP core update flow
376 if ( empty( $_REQUEST['plugin'] ) ) {
377 return;
378 }
379
380 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- capability check via current_user_can; nonce handled by WP core update flow
381 if ( empty( $_REQUEST['slug'] ) ) {
382 return;
383 }
384
385 if ( ! current_user_can( 'update_plugins' ) ) {
386 wp_die( esc_html__( 'You do not have permission to install plugin updates', 'wp-all-export' ), esc_html__( 'Error', 'wp-all-export' ), array( 'response' => 403 ) );
387 }
388
389 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- capability check via current_user_can; nonce handled by WP core update flow
390 $response = $this->api_request( 'show_changelog', array( 'slug' => sanitize_text_field( wp_unslash( $_REQUEST['slug'] ) ) ) );
391
392 if ( $response && isset( $response->sections['changelog'] ) ) {
393 echo '<div style="background:#fff;padding:10px;">' . wp_kses_post( $response->sections['changelog'] ) . '</div>';
394 }
395
396
397 exit;
398 }
399 }
400