PluginProbe
Polylang / 2.3
Polylang v2.3
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
← All changes | install/plugin-updater.php +34 -175 2.82.3 View file →
@@ -1,8 +1,5 @@
1 1 <?php
2 -/**
3 - * @package Polylang
4 - */
5 2
6 3 // Exit if accessed directly
7 4 if ( ! defined( 'ABSPATH' ) ) {
8 5 exit;
@@ -12,9 +9,9 @@
12 9 * Allows plugins to use their own update API.
13 10 * Modified version with 'polylang' text domain and comments for translators
14 11 *
15 12 * @author Easy Digital Downloads
16 - * @version 1.7.1
13 + * @version 1.6.15
17 14 */
18 15 class PLL_Plugin_Updater {
19 16
20 17 private $api_url = '';
@@ -24,10 +21,8 @@
24 21 private $version = '';
25 22 private $wp_override = false;
26 23 private $cache_key = '';
27 24
28 - private $health_check_timeout = 5;
29 -
30 25 /**
31 26 * Class constructor.
32 27 *
33 28 * @uses plugin_basename()
@@ -51,17 +46,8 @@
51 46 $this->cache_key = 'edd_sl_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
52 47
53 48 $edd_plugin_data[ $this->slug ] = $this->api_data;
54 49
55 - /**
56 - * Fires after the $edd_plugin_data is setup.
57 - *
58 - * @since x.x.x
59 - *
60 - * @param array $edd_plugin_data Array of EDD SL plugin data.
61 - */
62 - do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );
63 -
64 50 // Set up hooks.
65 51 $this->init();
66 52
67 53 }
@@ -122,35 +108,17 @@
122 108 }
123 109
124 110 if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
125 111
126 - $no_update = false;
127 112 if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
128 113
129 114 $_transient_data->response[ $this->name ] = $version_info;
130 115
131 - // Make sure the plugin property is set to the plugin's name/location. See issue 1463 on Software Licensing's GitHub repo.
132 - $_transient_data->response[ $this->name ]->plugin = $this->name;
133 -
134 - } else {
135 - $no_update = new stdClass();
136 - $no_update->id = '';
137 - $no_update->slug = $this->slug;
138 - $no_update->plugin = $this->name;
139 - $no_update->new_version = $version_info->new_version;
140 - $no_update->url = $version_info->homepage;
141 - $no_update->package = isset( $version_info->package ) ? $version_info->package : ''; #modified#
142 - $no_update->icons = $version_info->icons;
143 - $no_update->banners = $version_info->banners;
144 - $no_update->banners_rtl = array();
145 116 }
146 117
147 - $_transient_data->last_checked = time();
118 + $_transient_data->last_checked = current_time( 'timestamp' );
148 119 $_transient_data->checked[ $this->name ] = $this->version;
149 120
150 - if ( $no_update ) {
151 - $_transient_data->no_update[ $this->name ] = $no_update;
152 - }
153 121 }
154 122
155 123 return $_transient_data;
156 124 }
@@ -192,25 +160,8 @@
192 160
193 161 if ( false === $version_info ) {
194 162 $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => $this->beta ) );
195 163
196 - // Since we disabled our filter for the transient, we aren't running our object conversion on banners, sections, or icons. Do this now:
197 - if ( isset( $version_info->banners ) && ! is_array( $version_info->banners ) ) {
198 - $version_info->banners = $this->convert_object_to_array( $version_info->banners );
199 - }
200 -
201 - if ( isset( $version_info->sections ) && ! is_array( $version_info->sections ) ) {
202 - $version_info->sections = $this->convert_object_to_array( $version_info->sections );
203 - }
204 -
205 - if ( isset( $version_info->icons ) && ! is_array( $version_info->icons ) ) {
206 - $version_info->icons = $this->convert_object_to_array( $version_info->icons );
207 - }
208 -
209 - if ( isset( $version_info->contributors ) && ! is_array( $version_info->contributors ) ) {
210 - $version_info->contributors = $this->convert_object_to_array( $version_info->contributors );
211 - }
212 -
213 164 $this->set_version_info_cache( $version_info );
214 165 }
215 166
216 167 if ( ! is_object( $version_info ) ) {
@@ -216,31 +167,16 @@
216 167 if ( ! is_object( $version_info ) ) {
217 168 return;
218 169 }
219 170
220 - $no_update = false;
221 171 if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
222 172
223 173 $update_cache->response[ $this->name ] = $version_info;
224 174
225 - } else {
226 - $no_update = new stdClass();
227 - $no_update->id = '';
228 - $no_update->slug = $this->slug;
229 - $no_update->plugin = $this->name;
230 - $no_update->new_version = $version_info->new_version;
231 - $no_update->url = $version_info->homepage;
232 - $no_update->package = isset( $version_info->package ) ? $version_info->package : ''; #modified#
233 - $no_update->icons = $version_info->icons;
234 - $no_update->banners = $version_info->banners;
235 - $no_update->banners_rtl = array();
236 175 }
237 176
238 - $update_cache->last_checked = time();
177 + $update_cache->last_checked = current_time( 'timestamp' );
239 178 $update_cache->checked[ $this->name ] = $this->version;
240 - if ( $no_update ) {
241 - $update_cache->no_update[ $this->name ] = $no_update;
242 - }
243 179
244 180 set_site_transient( 'update_plugins', $update_cache );
245 181
246 182 } else {
@@ -265,9 +201,9 @@
265 201
266 202 if ( empty( $version_info->download_link ) ) {
267 203 printf(
268 204 /* translators: %1$s plugin name, %3$s plugin version, %2$s is link start tag, %4$s is link end tag. */
269 - __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'polylang' ),
205 + esc_html__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'polylang' ),
270 206 esc_html( $version_info->name ),
271 207 '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
272 208 esc_html( $version_info->new_version ),
273 209 '</a>'
@@ -274,9 +210,9 @@
274 210 );
275 211 } else {
276 212 printf(
277 213 /* translators: %1$s plugin name, %3$s plugin version, %2$s and %5$s are link start tags, %4$s and %6$s are link end tags. */
278 - __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'polylang' ),
214 + esc_html__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'polylang' ),
279 215 esc_html( $version_info->name ),
280 216 '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
281 217 esc_html( $version_info->new_version ),
282 218 '</a>',
@@ -319,15 +255,16 @@
319 255 'slug' => $this->slug,
320 256 'is_ssl' => is_ssl(),
321 257 'fields' => array(
322 258 'banners' => array(),
323 - 'reviews' => false,
324 - 'icons' => array(),
259 + 'reviews' => false
325 260 )
326 261 );
327 262
263 + $cache_key = 'edd_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
264 +
328 265 // Get the transient where we store the api request for this plugin for 24 hours
329 - $edd_api_request_transient = $this->get_cached_version_info();
266 + $edd_api_request_transient = $this->get_cached_version_info( $cache_key );
330 267
331 268 //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.
332 269 if ( empty( $edd_api_request_transient ) ) {
333 270
@@ -333,9 +270,9 @@
333 270
334 271 $api_response = $this->api_request( 'plugin_information', $to_send );
335 272
336 273 // Expires in 3 hours
337 - $this->set_version_info_cache( $api_response );
274 + $this->set_version_info_cache( $api_response, $cache_key );
338 275
339 276 if ( false !== $api_response ) {
340 277 $_data = $api_response;
341 278 }
@@ -345,55 +282,30 @@
345 282 }
346 283
347 284 // Convert sections into an associative array, since we're getting an object, but Core expects an array.
348 285 if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
349 - $_data->sections = $this->convert_object_to_array( $_data->sections );
286 + $new_sections = array();
287 + foreach ( $_data->sections as $key => $value ) {
288 + $new_sections[ $key ] = $value;
289 + }
290 +
291 + $_data->sections = $new_sections;
350 292 }
351 293
352 294 // Convert banners into an associative array, since we're getting an object, but Core expects an array.
353 295 if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
354 - $_data->banners = $this->convert_object_to_array( $_data->banners );
355 - }
296 + $new_banners = array();
297 + foreach ( $_data->banners as $key => $value ) {
298 + $new_banners[ $key ] = $value;
299 + }
356 300
357 - // Convert icons into an associative array, since we're getting an object, but Core expects an array.
358 - if ( isset( $_data->icons ) && ! is_array( $_data->icons ) ) {
359 - $_data->icons = $this->convert_object_to_array( $_data->icons );
301 + $_data->banners = $new_banners;
360 302 }
361 303
362 - // Convert contributors into an associative array, since we're getting an object, but Core expects an array.
363 - if ( isset( $_data->contributors ) && ! is_array( $_data->contributors ) ) {
364 - $_data->contributors = $this->convert_object_to_array( $_data->contributors );
365 - }
366 -
367 - if( ! isset( $_data->plugin ) ) {
368 - $_data->plugin = $this->name;
369 - }
370 -
371 304 return $_data;
372 305 }
373 306
374 307 /**
375 - * Convert some objects to arrays when injecting data into the update API
376 - *
377 - * Some data like sections, banners, and icons are expected to be an associative array, however due to the JSON
378 - * decoding, they are objects. This method allows us to pass in the object and return an associative array.
379 - *
380 - * @since 3.6.5
381 - *
382 - * @param stdClass $data
383 - *
384 - * @return array
385 - */
386 - private function convert_object_to_array( $data ) {
387 - $new_data = array();
388 - foreach ( $data as $key => $value ) {
389 - $new_data[ $key ] = is_object( $value ) ? $this->convert_object_to_array( $value ) : $value;
390 - }
391 -
392 - return $new_data;
393 - }
394 -
395 - /**
396 308 * Disable SSL verification in order to prevent download update failures
397 309 *
398 310 * @param array $args
399 311 * @param string $url
@@ -421,34 +333,10 @@
421 333 * @return false|object
422 334 */
423 335 private function api_request( $_action, $_data ) {
424 336
425 - global $wp_version, $edd_plugin_url_available;
337 + global $wp_version;
426 338
427 - $verify_ssl = $this->verify_ssl();
428 -
429 - // Do a quick status check on this domain if we haven't already checked it.
430 - $store_hash = md5( $this->api_url );
431 - if ( ! is_array( $edd_plugin_url_available ) || ! isset( $edd_plugin_url_available[ $store_hash ] ) ) {
432 - $test_url_parts = parse_url( $this->api_url );
433 -
434 - $scheme = ! empty( $test_url_parts['scheme'] ) ? $test_url_parts['scheme'] : 'http';
435 - $host = ! empty( $test_url_parts['host'] ) ? $test_url_parts['host'] : '';
436 - $port = ! empty( $test_url_parts['port'] ) ? ':' . $test_url_parts['port'] : '';
437 -
438 - if ( empty( $host ) ) {
439 - $edd_plugin_url_available[ $store_hash ] = false;
440 - } else {
441 - $test_url = $scheme . '://' . $host . $port;
442 - $response = wp_remote_get( $test_url, array( 'timeout' => $this->health_check_timeout, 'sslverify' => $verify_ssl ) );
443 - $edd_plugin_url_available[ $store_hash ] = is_wp_error( $response ) ? false : true;
444 - }
445 - }
446 -
447 - if ( false === $edd_plugin_url_available[ $store_hash ] ) {
448 - return;
449 - }
450 -
451 339 $data = array_merge( $this->api_data, $_data );
452 340
453 341 if ( $data['slug'] != $this->slug ) {
454 342 return;
@@ -453,9 +341,9 @@
453 341 if ( $data['slug'] != $this->slug ) {
454 342 return;
455 343 }
456 344
457 - if( $this->api_url == trailingslashit ( home_url() ) ) {
345 + if( $this->api_url == trailingslashit (home_url() ) ) {
458 346 return false; // Don't allow a plugin to ping itself
459 347 }
460 348
461 349 $api_params = array(
@@ -469,8 +357,9 @@
469 357 'url' => home_url(),
470 358 'beta' => ! empty( $data['beta'] ),
471 359 );
472 360
361 + $verify_ssl = $this->verify_ssl();
473 362 $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
474 363
475 364 if ( ! is_wp_error( $request ) ) {
476 365 $request = json_decode( wp_remote_retrieve_body( $request ) );
@@ -485,12 +374,8 @@
485 374 if ( $request && isset( $request->banners ) ) {
486 375 $request->banners = maybe_unserialize( $request->banners );
487 376 }
488 377
489 - if ( $request && isset( $request->icons ) ) {
490 - $request->icons = maybe_unserialize( $request->icons );
491 - }
492 -
493 378 if( ! empty( $request->sections ) ) {
494 379 foreach( $request->sections as $key => $section ) {
495 380 $request->$key = (array) $section;
496 381 }
@@ -498,11 +383,8 @@
498 383
499 384 return $request;
500 385 }
501 386
502 - /**
503 - * If available, show the changelog for sites in a multisite install.
504 - */
505 387 public function show_changelog() {
506 388
507 389 global $edd_plugin_data;
508 390
@@ -522,9 +404,11 @@
522 404 wp_die( __( 'You do not have permission to install plugin updates', 'polylang' ), __( 'Error', 'polylang' ), array( 'response' => 403 ) );
523 405 }
524 406
525 407 $data = $edd_plugin_data[ $_REQUEST['slug'] ];
526 - $version_info = $this->get_cached_version_info();
408 + $beta = ! empty( $data['beta'] ) ? true : false;
409 + $cache_key = md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_' . $beta . '_version_info' );
410 + $version_info = $this->get_cached_version_info( $cache_key );
527 411
528 412 if( false === $version_info ) {
529 413
530 414 $api_params = array(
@@ -543,8 +427,9 @@
543 427 if ( ! is_wp_error( $request ) ) {
544 428 $version_info = json_decode( wp_remote_retrieve_body( $request ) );
545 429 }
546 430
431 +
547 432 if ( ! empty( $version_info ) && isset( $version_info->sections ) ) {
548 433 $version_info->sections = maybe_unserialize( $version_info->sections );
549 434 } else {
550 435 $version_info = false;
@@ -555,30 +440,19 @@
555 440 $version_info->$key = (array) $section;
556 441 }
557 442 }
558 443
559 - $this->set_version_info_cache( $version_info );
444 + $this->set_version_info_cache( $version_info, $cache_key );
560 445
561 - // Delete the unneeded option
562 - delete_option( md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_' . $this->beta . '_version_info' ) );
563 446 }
564 447
565 - if ( isset( $version_info->sections ) ) {
566 - $sections = $this->convert_object_to_array( $version_info->sections );
567 - if ( ! empty( $sections['changelog'] ) ) {
568 - echo '<div style="background:#fff;padding:10px;">' . wp_kses_post( $sections['changelog'] ) . '</div>';
569 - }
448 + if( ! empty( $version_info ) && isset( $version_info->sections['changelog'] ) ) {
449 + echo '<div style="background:#fff;padding:10px;">' . $version_info->sections['changelog'] . '</div>';
570 450 }
571 451
572 452 exit;
573 453 }
574 454
575 - /**
576 - * Gets the plugin's cached version information from the database.
577 - *
578 - * @param string $cache_key
579 - * @return boolean|string
580 - */
581 455 public function get_cached_version_info( $cache_key = '' ) {
582 456
583 457 if( empty( $cache_key ) ) {
584 458 $cache_key = $this->cache_key;
@@ -585,28 +459,16 @@
585 459 }
586 460
587 461 $cache = get_option( $cache_key );
588 462
589 - if( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) {
463 + if( empty( $cache['timeout'] ) || current_time( 'timestamp' ) > $cache['timeout'] ) {
590 464 return false; // Cache is expired
591 465 }
592 466
593 - // We need to turn the icons into an array, thanks to WP Core forcing these into an object at some point.
594 - $cache['value'] = json_decode( $cache['value'] );
595 - if ( ! empty( $cache['value']->icons ) ) {
596 - $cache['value']->icons = (array) $cache['value']->icons;
597 - }
467 + return json_decode( $cache['value'] );
598 468
599 - return $cache['value'];
600 -
601 469 }
602 470
603 - /**
604 - * Adds the plugin version information to the database.
605 - *
606 - * @param string $value
607 - * @param string $cache_key
608 - */
609 471 public function set_version_info_cache( $value = '', $cache_key = '' ) {
610 472
611 473 if( empty( $cache_key ) ) {
612 474 $cache_key = $this->cache_key;
@@ -612,16 +474,14 @@
612 474 $cache_key = $this->cache_key;
613 475 }
614 476
615 477 $data = array(
616 - 'timeout' => strtotime( '+3 hours', time() ),
478 + 'timeout' => strtotime( '+3 hours', current_time( 'timestamp' ) ),
617 479 'value' => json_encode( $value )
618 480 );
619 481
620 482 update_option( $cache_key, $data, 'no' );
621 483
622 - // Delete the duplicate option
623 - delete_option( 'edd_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) ) );
624 484 }
625 485
626 486 /**
627 487 * Returns if the SSL of the store should be verified.
@@ -633,5 +493,4 @@
633 493 return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
634 494 }
635 495
636 496 }
637 -