PluginProbe ʕ •ᴥ•ʔ
PixelYourSite – Your smart PIXEL (TAG) & API Manager / 11.2.0.6
PixelYourSite – Your smart PIXEL (TAG) & API Manager v11.2.0.6
11.2.0.6 trunk 1.0 1.01 1.02 1.03 1.04 1.05 1.05.1 10.0.0 10.0.1 10.0.1.1 10.0.1.2 10.0.2 10.0.3 10.0.3.1 10.0.4 10.1.0 10.1.1 10.1.1.1 10.1.1.2 10.1.2.1 10.1.3 10.2.0 10.2.0.1 10.2.0.2 10.2.1 11.0.0 11.0.0.1 11.0.0.2 11.0.0.3 11.0.0.4 11.0.1 11.0.1.1 11.0.1.2 11.0.2 11.1.0 11.1.1 11.1.2 11.1.3 11.1.4 11.1.4.1 11.1.4.2 11.1.5 11.1.5.1 11.1.5.2 11.2.0 11.2.0.1 11.2.0.2 11.2.0.3 11.2.0.4 11.2.0.5 2.0 2.1 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.7 2.8.10 2.8.9 3.0 3.0.1 3.0.2 3.0.3 3.1.0 4.0.0 4.0.1 4.0.2 4.0.3 5.0.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5.2 5.0.6 5.0.7 5.0.8 5.0.9 5.1.0 5.2.0 5.2.1 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 7.0.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1.0 7.1.1 7.1.10 7.1.11 7.1.12 7.1.13 7.1.14 7.1.2 7.1.3 7.1.4 7.1.5 7.1.6 7.1.7 7.1.8 7.1.9 7.2.0 7.2.1 7.2.1.1 7.3.0 8.0.0 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.0.6 8.0.7 8.0.8 8.0.9 8.1.0 8.1.1 8.2.0 8.2.1 8.2.10 8.2.11 8.2.12 8.2.13 8.2.14 8.2.15 8.2.16 8.2.17 8.2.18 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.2.7 8.2.8 9.0.0 9.1.0 9.1.1 9.2.0 9.2.1 9.2.2 9.3.0 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.3.7 9.3.8 9.3.8.1 9.3.9 9.4.0 9.4.0.1 9.4.1 9.4.2 9.4.3 9.4.5 9.4.5.1 9.4.6 9.4.7 9.4.7.1 9.5.0 9.5.0.1 9.5.1 9.5.1.1 9.5.3 9.5.4 9.5.5 9.6.0 9.6.0.1 9.6.1 9.6.1.1 9.6.2 9.7.0 9.7.0.1 9.7.1 9.7.2
pixelyoursite / includes / class-plugin-updater.php
pixelyoursite / includes Last commit date
enrich 3 weeks ago event-definitions 4 months ago events 1 week ago formEvents 1 year ago logger 4 months ago views 1 week ago class-consent.php 6 months ago class-custom-event-factory.php 1 year ago class-custom-event.php 3 weeks ago class-event-definitions.php 4 months ago class-event-id-generator.php 5 years ago class-events-manager-ajax_hook.php 3 weeks ago class-events-manager.php 3 weeks ago class-fixed-notices.php 1 year ago class-optin-notices.php 1 year ago class-pixel.php 7 years ago class-plugin-updater.php 9 months ago class-plugin.php 7 years ago class-pys.php 1 week ago class-settings.php 4 months ago functions-admin.php 3 weeks ago functions-buttons.php 1 year ago functions-common.php 3 weeks ago functions-custom-event.php 1 week ago functions-edd.php 2 years ago functions-gdpr.php 11 months ago functions-license.php 3 weeks ago functions-migrate.php 9 months ago functions-promo-notices.php 1 year ago functions-system-report.php 7 years ago functions-update-plugin.php 6 years ago functions-woo.php 3 weeks ago options_defaults.json 3 weeks ago options_fields.json 3 weeks ago
class-plugin-updater.php
566 lines
1 <?php
2
3 namespace PixelYourSite;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit; // Exit if accessed directly.
7 }
8
9 // uncomment this line for testing
10 //set_site_transient( 'update_plugins', null );
11
12 /**
13 * Allows plugins to use their own update API.
14 *
15 * This is used strictly for add-on updates, NOT for updating the core plugin itself (PixelYourSite).
16 * If you decide to download and install free or paid add-ons from our site (Pinterest Tag, Bing Tag), we will perform checks for updates.
17 * If you hold a valid license for the add-on, we will download the update from our server.
18 *
19 * @author Easy Digital Downloads
20 * @version 1.6.14
21 */
22 class Plugin_Updater {
23
24 private $api_url = '';
25 private $api_data = array();
26 private $name = '';
27 private $slug = '';
28 private $version = '';
29 private $wp_override = false;
30 private $cache_key = '';
31
32 private $beta = false;
33
34 private $plugin_data = [];
35 /**
36 * Class constructor.
37 *
38 * @uses plugin_basename()
39 * @uses hook()
40 *
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 $this->api_url = trailingslashit( $_api_url );
47 $this->api_data = $_api_data;
48 $this->name = plugin_basename( $_plugin_file );
49 $this->slug = basename( $_plugin_file, '.php' );
50 $this->version = $_api_data['version'];
51 $this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
52 $this->beta = ! empty( $this->api_data['beta'] ) ? true : false;
53 $this->cache_key = 'pys_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
54
55 $this->plugin_data[ $this->slug ] = $this->api_data;
56
57 // Set up hooks.
58 $this->init();
59
60 }
61
62 /**
63 * Set up WordPress filters to hook into WP's update process.
64 *
65 * @uses add_filter()
66 *
67 * @return void
68 */
69 public function init() {
70
71 add_filter( 'site_transient_update_plugins', array( $this, 'check_update' ) );
72 add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
73 remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10 );
74 add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
75 add_action( 'admin_init', array( $this, 'show_changelog' ) );
76
77 }
78
79 /**
80 * Check for Updates at the defined API endpoint and modify the update array.
81 *
82 * This function dives into the update API just when WordPress creates its update array,
83 * then adds a custom API call and injects the custom plugin data retrieved from the API.
84 * It is reassembled from parts of the native WordPress plugin update code.
85 * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
86 *
87 * @uses api_request()
88 *
89 * @param array $_transient_data Update array build by WordPress.
90 *
91 * @return array Modified update array with custom plugin data.
92 */
93 public function check_update( $_transient_data ) {
94
95 global $pagenow;
96
97 if ( ! is_object( $_transient_data ) ) {
98 $_transient_data = new \stdClass;
99 }
100
101 if ( 'plugins.php' == $pagenow && is_multisite() ) {
102 return $_transient_data;
103 }
104
105 if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) {
106 return $_transient_data;
107 }
108
109 $version_info = $this->get_cached_version_info();
110
111 $need_refresh = false;
112
113 // Check if version_info is missing or incomplete || Cache expired
114 if ( ! $version_info || $this->is_cache_expired() ) {
115 $need_refresh = true;
116 }
117
118 if ( $need_refresh ) {
119 $version_info = $this->api_request( 'plugin_latest_version',
120 array( 'slug' => $this->slug, 'beta' => $this->beta ) );
121 $timeout = $this->get_timeout();
122 $this->set_version_info_cache( $version_info,"",$timeout );
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 = current_time( 'timestamp' );
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( '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 $need_refresh = false;
178
179 // Check if version_info is missing or incomplete || Cache expired
180 if ( ! $version_info || $this->is_cache_expired() ) {
181 $need_refresh = true;
182 }
183
184 if ( $need_refresh ) {
185 $version_info = $this->api_request( 'plugin_latest_version',
186 array( 'slug' => $this->slug, 'beta' => $this->beta ) );
187 $timeout = $this->get_timeout();
188 $this->set_version_info_cache( $version_info,"",$timeout );
189 }
190
191 if ( ! is_object( $version_info ) ) {
192 return;
193 }
194
195 if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
196
197 $update_cache->response[ $this->name ] = $version_info;
198
199 }
200
201 $update_cache->last_checked = current_time( 'timestamp' );
202 $update_cache->checked[ $this->name ] = $this->version;
203
204 set_site_transient( 'update_plugins', $update_cache );
205
206 } else {
207
208 $version_info = $update_cache->response[ $this->name ];
209
210 }
211
212 // Restore our filter
213 add_filter( 'site_transient_update_plugins', array( $this, 'check_update' ) );
214
215 if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version,
216 $version_info->new_version, '<' ) ) {
217
218 // build a plugin list row, with update notification
219 $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
220 # <tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange">
221 echo '<tr class="plugin-update-tr" id="' . $this->slug . '-update" data-slug="' . $this->slug . '" data-plugin="' . $this->slug . '/' . $file . '">';
222 echo '<td colspan="3" class="plugin-update colspanchange">';
223 echo '<div class="update-message notice inline notice-warning notice-alt">';
224
225 $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' );
226
227 if ( empty( $version_info->download_link ) ) {
228 printf(
229 __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.',
230 'easy-digital-downloads' ),
231 esc_html( $version_info->name ),
232 '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
233 esc_html( $version_info->new_version ),
234 '</a>'
235 );
236 } else {
237 printf(
238 __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.',
239 'easy-digital-downloads' ),
240 esc_html( $version_info->name ),
241 '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
242 esc_html( $version_info->new_version ),
243 '</a>',
244 '<a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name,
245 'upgrade-plugin_' . $this->name ) ) . '">',
246 '</a>'
247 );
248 }
249
250 do_action( "in_plugin_update_message-{$file}", $plugin, $version_info );
251
252 echo '</div></td></tr>';
253 }
254 }
255
256 /**
257 * Updates information on the "View version x.x details" page with custom data.
258 *
259 * @uses api_request()
260 *
261 * @param mixed $_data
262 * @param string $_action
263 * @param object $_args
264 *
265 * @return object $_data
266 */
267 public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
268
269 if ( $_action != 'plugin_information' ) {
270
271 return $_data;
272
273 }
274
275 if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
276
277 return $_data;
278
279 }
280
281 $to_send = array(
282 'slug' => $this->slug,
283 'is_ssl' => is_ssl(),
284 'fields' => array(
285 'banners' => array(),
286 'reviews' => false
287 )
288 );
289
290 $cache_key = 'pys_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
291
292 // Get the transient where we store the api request for this plugin for 24 hours
293 $edd_api_request_transient = $this->get_cached_version_info( $cache_key );
294
295 //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.
296 if ( empty( $edd_api_request_transient ) || $this->is_cache_expired($cache_key) ) {
297
298 $api_response = $this->api_request( 'plugin_information', $to_send );
299
300 // Expires in 3 hours
301 $timeout = $this->get_timeout();
302 $this->set_version_info_cache( $api_response, $cache_key,$timeout );
303
304 if ( false !== $api_response ) {
305 $_data = $api_response;
306 }
307
308 } else {
309 $_data = $edd_api_request_transient;
310 }
311
312 // Convert sections into an associative array, since we're getting an object, but Core expects an array.
313 if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
314 $new_sections = array();
315 foreach ( $_data->sections as $key => $value ) {
316 $new_sections[ $key ] = $value;
317 }
318
319 $_data->sections = $new_sections;
320 }
321
322 // Convert banners into an associative array, since we're getting an object, but Core expects an array.
323 if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
324 $new_banners = array();
325 foreach ( $_data->banners as $key => $value ) {
326 $new_banners[ $key ] = $value;
327 }
328
329 $_data->banners = $new_banners;
330 }
331
332 return $_data;
333 }
334
335 /**
336 * Disable SSL verification in order to prevent download update failures
337 *
338 * @param array $args
339 * @param string $url
340 *
341 * @return object $array
342 */
343 public function http_request_args( $args, $url ) {
344
345 $verify_ssl = $this->verify_ssl();
346 if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
347 $args['sslverify'] = $verify_ssl;
348 }
349
350 return $args;
351
352 }
353
354 /**
355 * Calls the API and, if successfull, returns the object delivered by the API.
356 *
357 * @uses get_bloginfo()
358 * @uses wp_remote_post()
359 * @uses is_wp_error()
360 *
361 * @param string $_action The requested action.
362 * @param array $_data Parameters for the API action.
363 *
364 * @return false|object
365 */
366 private function api_request( $_action, $_data ) {
367
368 global $wp_version;
369
370 $data = array_merge( $this->api_data, $_data );
371
372 if ( $data['slug'] != $this->slug ) {
373 return;
374 }
375
376 if ( $this->api_url == trailingslashit( home_url() ) ) {
377 return false; // Don't allow a plugin to ping itself
378 }
379
380 $api_params = array(
381 'edd_action' => 'get_version',
382 'license' => ! empty( $data['license'] ) ? $data['license'] : '',
383 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
384 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
385 'version' => isset( $data['version'] ) ? $data['version'] : false,
386 'slug' => $data['slug'],
387 'author' => $data['author'],
388 'url' => home_url(),
389 'beta' => ! empty( $data['beta'] ),
390 );
391
392 $verify_ssl = $this->verify_ssl();
393 $request = wp_remote_post( $this->api_url,
394 array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
395
396 if ( ! is_wp_error( $request ) ) {
397 $request = json_decode( wp_remote_retrieve_body( $request ) );
398 }
399
400 if ( $request && isset( $request->sections ) ) {
401 $request->sections = maybe_unserialize( $request->sections );
402 }
403
404 if ( $request && isset( $request->banners ) ) {
405 $request->banners = maybe_unserialize( $request->banners );
406 }
407
408 if ( ! empty( $request->sections ) ) {
409 foreach ( $request->sections as $key => $section ) {
410 $request->$key = (array) $section;
411 }
412 }
413
414 return $request;
415 }
416
417 public function show_changelog() {
418
419 if ( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
420 return;
421 }
422
423 if ( empty( $_REQUEST['plugin'] ) ) {
424 return;
425 }
426
427 if ( empty( $_REQUEST['slug'] ) ) {
428 return;
429 }
430
431 if ( ! current_user_can( 'update_plugins' ) ) {
432 wp_die( __( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ),
433 __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
434 }
435 $edd_plugin_data_slag = sanitize_text_field($_REQUEST['slug']);
436 $data = $this->plugin_data[ $edd_plugin_data_slag ];
437 $beta = ! empty( $data['beta'] ) ? true : false;
438 $cache_key = 'pys_api_request_' . md5( serialize( $_REQUEST['plugin'] . $this->api_data['license'] . $this->beta ) );
439 $version_info = $this->get_cached_version_info( $cache_key );
440
441 if ( false === $version_info || $this->is_cache_expired($cache_key)) {
442
443 $api_params = array(
444 'edd_action' => 'get_version',
445 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
446 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
447 'slug' => $edd_plugin_data_slag,
448 'author' => $data['author'],
449 'url' => home_url(),
450 'beta' => ! empty( $data['beta'] )
451 );
452
453 $verify_ssl = $this->verify_ssl();
454 $request = wp_remote_post( $this->api_url,
455 array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
456
457 if ( ! is_wp_error( $request ) ) {
458 $version_info = json_decode( wp_remote_retrieve_body( $request ) );
459 }
460
461
462 if ( ! empty( $version_info ) && isset( $version_info->sections ) ) {
463 $version_info->sections = maybe_unserialize( $version_info->sections );
464 } else {
465 $version_info = false;
466 }
467
468 if ( ! empty( $version_info ) ) {
469 foreach ( $version_info->sections as $key => $section ) {
470 $version_info->$key = (array) $section;
471 }
472 }
473 $timeout = $this->get_timeout();
474 $this->set_version_info_cache( $version_info, $cache_key,$timeout );
475
476 }
477
478 $allowed_html = [
479 'p' => [],
480 'ul' => [],
481 'li' => [],
482 'strong' => [],
483 'em' => [],
484 'a' => ['href' => [], 'title' => []],
485 ];
486
487 if ( ! empty( $version_info ) && isset( $version_info->sections['changelog'] ) ) {
488 echo '<div style="background:#fff;padding:10px;">' . wp_kses($version_info->sections['changelog'], $allowed_html) . '</div>';
489 }
490
491 exit;
492 }
493
494 public function is_cache_expired( $cache_key = '' ){
495 if ( empty( $cache_key ) ) {
496 $cache_key = $this->cache_key;
497 }
498 $cache = pys_get_option( $cache_key );
499
500 if ( empty( $cache['timeout'] ) || current_time( 'timestamp' ) > $cache['timeout'] ) {
501 return true; // Cache is expired
502 }
503 return false;
504 }
505 public function get_cached_version_info( $cache_key = '' ) {
506
507 if ( empty( $cache_key ) ) {
508 $cache_key = $this->cache_key;
509 }
510 $cache = pys_get_option( $cache_key );
511
512 if ( isset( $cache['value'] ) && is_string( $cache['value'] ) ) {
513 return json_decode( $cache['value'] );
514 }
515
516 return false;
517
518 }
519
520 public function set_version_info_cache( $value = '', $cache_key = '',$timeout = null ) {
521
522 if ( empty( $cache_key ) ) {
523 $cache_key = $this->cache_key;
524 }
525
526 if($timeout == null) {
527 $timeout = $this->get_timeout();
528 }
529
530 $data = array(
531 'timeout' => $timeout,
532 'value' => json_encode( $value )
533 );
534
535 pys_update_option( $cache_key, $data, 'no' );
536
537 }
538
539 /**
540 * Returns if the SSL of the store should be verified.
541 *
542 * @since 1.6.13
543 * @return bool
544 */
545 private function verify_ssl() {
546 return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
547 }
548 private function get_timeout() {
549 return ($this->slug == "pixelyoursite-pinterest")
550 ? strtotime('+48 hours', current_time('timestamp'))
551 : strtotime('+24 hours', current_time('timestamp'));
552 }
553 private function is_url_working( $url ): bool {
554 $response = wp_remote_head( $url, [
555 'timeout' => 10,
556 'sslverify' => $this->verify_ssl(),
557 ]);
558
559 if ( is_wp_error( $response ) ) {
560 return false;
561 }
562
563 $status_code = wp_remote_retrieve_response_code( $response );
564 return $status_code >= 200 && $status_code < 400;
565 }
566 }