PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.2.4
GiveWP – Donation Plugin and Fundraising Platform v2.2.4
4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / admin / EDD_SL_Plugin_Updater.php
give / includes / admin Last commit date
donors 7 years ago emails 7 years ago forms 7 years ago payments 7 years ago reports 7 years ago settings 7 years ago shortcodes 7 years ago tools 7 years ago upgrades 7 years ago views 8 years ago EDD_SL_Plugin_Updater.php 7 years ago abstract-admin-settings-page.php 8 years ago add-ons.php 8 years ago admin-actions.php 7 years ago admin-filters.php 8 years ago admin-footer.php 8 years ago admin-pages.php 8 years ago class-addon-activation-banner.php 7 years ago class-admin-settings.php 7 years ago class-api-keys-table.php 8 years ago class-blank-slate.php 8 years ago class-give-settings.php 7 years ago class-i18n-module.php 8 years ago dashboard-widgets.php 8 years ago give-metabox-functions.php 7 years ago plugins.php 7 years ago welcome.php 8 years ago
EDD_SL_Plugin_Updater.php
526 lines
1 <?php
2
3 // Exit if accessed directly
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * Allows plugins to use their own update API.
10 *
11 * @author Easy Digital Downloads
12 * @version 1.6.17
13 */
14 class EDD_SL_Plugin_Updater {
15
16 private $api_url = '';
17 private $api_data = array();
18 private $name = '';
19 private $slug = '';
20 private $version = '';
21 private $wp_override = false;
22 private $cache_key = '';
23
24 private $health_check_timeout = 5;
25
26 /**
27 * Class constructor.
28 *
29 * @uses plugin_basename()
30 * @uses hook()
31 *
32 * @param string $_api_url The URL pointing to the custom API endpoint.
33 * @param string $_plugin_file Path to the plugin file.
34 * @param array $_api_data Optional data to send with API calls.
35 */
36 public function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
37
38 global $edd_plugin_data, $edd_plugin_url_available;
39
40 $this->api_url = trailingslashit( $_api_url );
41
42 $this->api_data = $_api_data;
43 $this->name = plugin_basename( $_plugin_file );
44 $this->slug = basename( $_plugin_file, '.php' );
45 $this->version = $_api_data['version'];
46 $this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
47 $this->beta = ! empty( $this->api_data['beta'] ) ? true : false;
48 $this->cache_key = 'edd_sl_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
49
50 $edd_plugin_data[ $this->slug ] = $this->api_data;
51
52 /**
53 * Fires after the $edd_plugin_data is setup.
54 *
55 * @since x.x.x
56 *
57 * @param array $edd_plugin_data Array of EDD SL plugin data.
58 */
59 do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );
60
61 // Set up hooks.
62 $this->init();
63
64 }
65
66 /**
67 * Set up WordPress filters to hook into WP's update process.
68 *
69 * @uses add_filter()
70 *
71 * @return void
72 */
73 public function init() {
74
75 add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
76 add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
77 remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10 );
78 add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
79 add_action( 'admin_init', array( $this, 'show_changelog' ) );
80
81 }
82
83 /**
84 * Check for Updates at the defined API endpoint and modify the update array.
85 *
86 * This function dives into the update API just when WordPress creates its update array,
87 * then adds a custom API call and injects the custom plugin data retrieved from the API.
88 * It is reassembled from parts of the native WordPress plugin update code.
89 * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
90 *
91 * @uses api_request()
92 *
93 * @param array $_transient_data Update array build by WordPress.
94 * @return array Modified update array with custom plugin data.
95 */
96 public function check_update( $_transient_data ) {
97
98 global $pagenow;
99
100 if ( ! is_object( $_transient_data ) ) {
101 $_transient_data = new stdClass();
102 }
103
104 if ( 'plugins.php' == $pagenow && is_multisite() ) {
105 return $_transient_data;
106 }
107
108 if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) {
109 return $_transient_data;
110 }
111
112 $version_info = $this->get_cached_version_info();
113
114 if ( false === $version_info ) {
115 $version_info = $this->api_request(
116 'plugin_latest_version', array(
117 'slug' => $this->slug,
118 'beta' => $this->beta,
119 )
120 );
121
122 $this->set_version_info_cache( $version_info );
123
124 }
125
126 if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
127
128 if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
129
130 $_transient_data->response[ $this->name ] = $version_info;
131
132 }
133
134 $_transient_data->last_checked = time();
135 $_transient_data->checked[ $this->name ] = $this->version;
136
137 }
138
139 return $_transient_data;
140 }
141
142 /**
143 * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
144 *
145 * @param string $file
146 * @param array $plugin
147 */
148 public function show_update_notification( $file, $plugin ) {
149
150 if ( is_network_admin() ) {
151 return;
152 }
153
154 if ( ! current_user_can( 'update_plugins' ) ) {
155 return;
156 }
157
158 if ( ! is_multisite() ) {
159 return;
160 }
161
162 if ( $this->name != $file ) {
163 return;
164 }
165
166 // Remove our filter on the site transient
167 remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
168
169 $update_cache = get_site_transient( 'update_plugins' );
170
171 $update_cache = is_object( $update_cache ) ? $update_cache : new stdClass();
172
173 if ( empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
174
175 $version_info = $this->get_cached_version_info();
176
177 if ( false === $version_info ) {
178 $version_info = $this->api_request(
179 'plugin_latest_version', array(
180 'slug' => $this->slug,
181 'beta' => $this->beta,
182 )
183 );
184
185 $this->set_version_info_cache( $version_info );
186 }
187
188 if ( ! is_object( $version_info ) ) {
189 return;
190 }
191
192 if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
193
194 $update_cache->response[ $this->name ] = $version_info;
195
196 }
197
198 $update_cache->last_checked = time();
199 $update_cache->checked[ $this->name ] = $this->version;
200
201 set_site_transient( 'update_plugins', $update_cache );
202
203 } else {
204
205 $version_info = $update_cache->response[ $this->name ];
206
207 }
208
209 // Restore our filter
210 add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
211
212 if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) {
213
214 // build a plugin list row, with update notification
215 $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
216 // <tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange">
217 echo '<tr class="plugin-update-tr" id="' . $this->slug . '-update" data-slug="' . $this->slug . '" data-plugin="' . $this->slug . '/' . $file . '">';
218 echo '<td colspan="3" class="plugin-update colspanchange">';
219 echo '<div class="update-message notice inline notice-warning notice-alt">';
220
221 $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' );
222
223 if ( empty( $version_info->download_link ) ) {
224 printf(
225 __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'give' ),
226 esc_html( $version_info->name ),
227 '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
228 esc_html( $version_info->new_version ),
229 '</a>'
230 );
231 } else {
232 printf(
233 __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'give' ),
234 esc_html( $version_info->name ),
235 '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
236 esc_html( $version_info->new_version ),
237 '</a>',
238 '<a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) ) . '">',
239 '</a>'
240 );
241 }
242
243 do_action( "in_plugin_update_message-{$file}", $plugin, $version_info );
244
245 echo '</div></td></tr>';
246 }
247 }
248
249 /**
250 * Updates information on the "View version x.x details" page with custom data.
251 *
252 * @uses api_request()
253 *
254 * @param mixed $_data
255 * @param string $_action
256 * @param object $_args
257 * @return object $_data
258 */
259 public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
260
261 if ( $_action != 'plugin_information' ) {
262
263 return $_data;
264
265 }
266
267 if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
268
269 return $_data;
270
271 }
272
273 $to_send = array(
274 'slug' => $this->slug,
275 'is_ssl' => is_ssl(),
276 'fields' => array(
277 'banners' => array(),
278 'reviews' => false,
279 ),
280 );
281
282 $cache_key = 'edd_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
283
284 // Get the transient where we store the api request for this plugin for 24 hours
285 $edd_api_request_transient = $this->get_cached_version_info( $cache_key );
286
287 // 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.
288 if ( empty( $edd_api_request_transient ) ) {
289
290 $api_response = $this->api_request( 'plugin_information', $to_send );
291
292 // Expires in 3 hours
293 $this->set_version_info_cache( $api_response, $cache_key );
294
295 if ( false !== $api_response ) {
296 $_data = $api_response;
297 }
298 } else {
299 $_data = $edd_api_request_transient;
300 }
301
302 // Convert sections into an associative array, since we're getting an object, but Core expects an array.
303 if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
304 $new_sections = array();
305 foreach ( $_data->sections as $key => $value ) {
306 $new_sections[ $key ] = $value;
307 }
308
309 $_data->sections = $new_sections;
310 }
311
312 // Convert banners into an associative array, since we're getting an object, but Core expects an array.
313 if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
314 $new_banners = array();
315 foreach ( $_data->banners as $key => $value ) {
316 $new_banners[ $key ] = $value;
317 }
318
319 $_data->banners = $new_banners;
320 }
321
322 return $_data;
323 }
324
325 /**
326 * Disable SSL verification in order to prevent download update failures
327 *
328 * @param array $args
329 * @param string $url
330 * @return object $array
331 */
332 public function http_request_args( $args, $url ) {
333
334 $verify_ssl = $this->verify_ssl();
335 if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
336 $args['sslverify'] = $verify_ssl;
337 }
338 return $args;
339
340 }
341
342 /**
343 * Calls the API and, if successfull, returns the object delivered by the API.
344 *
345 * @uses get_bloginfo()
346 * @uses wp_remote_post()
347 * @uses is_wp_error()
348 *
349 * @param string $_action The requested action.
350 * @param array $_data Parameters for the API action.
351 * @return false|object
352 */
353 private function api_request( $_action, $_data ) {
354
355 global $wp_version;
356
357 $data = array_merge( $this->api_data, $_data );
358
359 if ( $data['slug'] != $this->slug ) {
360 return;
361 }
362
363 if ( $this->api_url == trailingslashit( home_url() ) ) {
364 return false; // Don't allow a plugin to ping itself
365 }
366
367 $api_params = array(
368 'edd_action' => 'get_version',
369 'license' => ! empty( $data['license'] ) ? $data['license'] : '',
370 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
371 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
372 'version' => isset( $data['version'] ) ? $data['version'] : false,
373 'slug' => $data['slug'],
374 'author' => $data['author'],
375 'url' => home_url(),
376 'beta' => ! empty( $data['beta'] ),
377 );
378
379 $verify_ssl = $this->verify_ssl();
380 $request = wp_remote_post(
381 $this->api_url, array(
382 'timeout' => 15,
383 'sslverify' => $verify_ssl,
384 'body' => $api_params,
385 )
386 );
387
388 if ( ! is_wp_error( $request ) ) {
389 $request = json_decode( wp_remote_retrieve_body( $request ) );
390 }
391
392 if ( $request && isset( $request->sections ) ) {
393 $request->sections = maybe_unserialize( $request->sections );
394 } else {
395 $request = false;
396 }
397
398 if ( $request && isset( $request->banners ) ) {
399 $request->banners = maybe_unserialize( $request->banners );
400 }
401
402 if ( ! empty( $request->sections ) ) {
403 foreach ( $request->sections as $key => $section ) {
404 $request->$key = (array) $section;
405 }
406 }
407
408 return $request;
409 }
410
411 public function show_changelog() {
412
413 global $edd_plugin_data;
414
415 if ( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
416 return;
417 }
418
419 if ( empty( $_REQUEST['plugin'] ) ) {
420 return;
421 }
422
423 if ( empty( $_REQUEST['slug'] ) ) {
424 return;
425 }
426
427 if ( ! current_user_can( 'update_plugins' ) ) {
428 wp_die( __( 'You do not have permission to install plugin updates', 'give' ), __( 'Error', 'give' ), array( 'response' => 403 ) );
429 }
430
431 $data = $edd_plugin_data[ $_REQUEST['slug'] ];
432 $beta = ! empty( $data['beta'] ) ? true : false;
433 $cache_key = md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_' . $beta . '_version_info' );
434 $version_info = $this->get_cached_version_info( $cache_key );
435
436 if ( false === $version_info ) {
437
438 $api_params = array(
439 'edd_action' => 'get_version',
440 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
441 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
442 'slug' => $_REQUEST['slug'],
443 'author' => $data['author'],
444 'url' => home_url(),
445 'beta' => ! empty( $data['beta'] ),
446 );
447
448 $verify_ssl = $this->verify_ssl();
449 $request = wp_remote_post(
450 $this->api_url, array(
451 'timeout' => 15,
452 'sslverify' => $verify_ssl,
453 'body' => $api_params,
454 )
455 );
456
457 if ( ! is_wp_error( $request ) ) {
458 $version_info = json_decode( wp_remote_retrieve_body( $request ) );
459 }
460
461 if ( ! empty( $version_info ) && isset( $version_info->sections ) ) {
462 $version_info->sections = maybe_unserialize( $version_info->sections );
463 } else {
464 $version_info = false;
465 }
466
467 if ( ! empty( $version_info ) ) {
468 foreach ( $version_info->sections as $key => $section ) {
469 $version_info->$key = (array) $section;
470 }
471 }
472
473 $this->set_version_info_cache( $version_info, $cache_key );
474
475 }
476
477 if ( ! empty( $version_info ) && isset( $version_info->sections['changelog'] ) ) {
478 echo '<div style="background:#fff;padding:10px;">' . $version_info->sections['changelog'] . '</div>';
479 }
480
481 exit;
482 }
483
484 public function get_cached_version_info( $cache_key = '' ) {
485
486 if ( empty( $cache_key ) ) {
487 $cache_key = $this->cache_key;
488 }
489
490 $cache = get_option( $cache_key );
491
492 if ( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) {
493 return false; // Cache is expired
494 }
495
496 return json_decode( $cache['value'] );
497
498 }
499
500 public function set_version_info_cache( $value = '', $cache_key = '' ) {
501
502 if ( empty( $cache_key ) ) {
503 $cache_key = $this->cache_key;
504 }
505
506 $data = array(
507 'timeout' => strtotime( '+3 hours', time() ),
508 'value' => json_encode( $value ),
509 );
510
511 update_option( $cache_key, $data, 'no' );
512
513 }
514
515 /**
516 * Returns if the SSL of the store should be verified.
517 *
518 * @since 1.6.13
519 * @return bool
520 */
521 private function verify_ssl() {
522 return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
523 }
524
525 }
526