PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.7.0.2
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.7.0.2
1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 All 211 releases
charitable / includes / licensing / class-charitable-licenses.php

class-charitable-licenses.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.7.0.2, at includes/licensing/class-charitable-licenses.php

859 lines 23.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class to assist with the setup of extension licenses.
4 *
5 * @package Charitable/Classes/Charitable_Licenses
6 * @version 1.4.20
7 * @author David Bisset
8 * @copyright Copyright (c) 2022, WP Charitable LLC
9 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 if ( ! class_exists( 'Charitable_Licenses' ) ) :
18
19 /**
20 * Charitable_Licenses
21 *
22 * @since 1.0.0
23 */
24 class Charitable_Licenses {
25
26 /* @var string */
27 const UPDATE_URL = 'https://www.wpcharitable.com';
28
29 /**
30 * The single instance of this class.
31 *
32 * @var Charitable_Licenses|null
33 */
34 private static $instance = null;
35
36 /**
37 * All the registered products requiring licensing.
38 *
39 * @var array
40 */
41 private $products;
42
43 /**
44 * All the stored licenses.
45 *
46 * @var array
47 */
48 private $licenses;
49
50 /**
51 * Cached update data.
52 *
53 * @var array
54 */
55 private $update_data;
56
57 /**
58 * Returns and/or create the single instance of this class.
59 *
60 * @since 1.2.0
61 *
62 * @return Charitable_Licenses
63 */
64 public static function get_instance() {
65 if ( is_null( self::$instance ) ) {
66 self::$instance = new self();
67 }
68
69 return self::$instance;
70 }
71
72 /**
73 * Create class object.
74 *
75 * @since 1.0.0
76 */
77 private function __construct() {
78 $this->products = array();
79 $this->update_data = array();
80
81 add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_for_updates' ) );
82 add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
83 add_action( 'charitable_deactivate_license', array( $this, 'deactivate_license' ) );
84 add_filter( 'upgrader_pre_download', array( $this, 'set_upgrader_error_message' ), 10, 3 );
85 add_filter( 'upgrader_package_options', array( $this, 'set_upgrader_package_options' ) );
86 }
87
88 /**
89 * Checks licenses to see if any are valid.
90 *
91 * @since 1.7.0
92 *
93 * @return boolean
94 */
95 public function is_pro() {
96
97 $products = $this->get_products();
98
99 if ( is_multisite() ) {
100
101 // get the main blog id to check for license
102 $network = get_network();
103 if ( ! $network ) {
104 return 0;
105 }
106
107 $blog_id = $network->site_id;
108
109 switch_to_blog( $blog_id );
110
111 $licenses = charitable_get_option( 'licenses', array() );
112
113 // go through licenses - if there is at least ONE VALID ADDON LICNESE then it's pro.
114 foreach ( $licenses as $slug => $license ) {
115 if ( isset( $license['valid'] ) && 1 === intval( $license['valid'] ) ) {
116 restore_current_blog();
117 return true;
118 }
119 }
120
121 restore_current_blog();
122
123 } else {
124
125 if ( empty( $products ) ) {
126 return false;
127 }
128
129 // go through licenses - if there is at least ONE VALID ADDON LICNESE then it's pro.
130 foreach ( $products as $slug => $item ) {
131 $valid = $this->has_valid_license( $slug );
132 if ( $valid ) {
133 return true;
134 }
135 }
136 }
137 }
138
139 /**
140 * Checks for any Charitable extensions with updates.
141 *
142 * @since 1.4.0
143 *
144 * @param array $_transient_data The plugin updates data.
145 * @return array
146 */
147 public function check_for_updates( $_transient_data ) {
148 global $pagenow;
149
150 if ( ! is_object( $_transient_data ) ) {
151 $_transient_data = new stdClass;
152 }
153
154 if ( 'plugins.php' == $pagenow && is_multisite() ) {
155 return $_transient_data;
156 }
157
158 /* Loop over our licensed products and check whether any are missing transient data. */
159 $missing_data = array();
160
161 foreach ( $this->get_products() as $product ) {
162 if ( $this->is_missing_version_info( $product, $_transient_data ) ) {
163 $missing_data[] = $product;
164 }
165 }
166
167 /* If we are missing data for any of our products, check whether any have an update. */
168 if ( ! empty( $missing_data ) ) {
169
170 $versions = $this->get_versions();
171
172 unset( $versions['request_speed'] );
173
174 if ( ! empty( $versions ) ) {
175
176 $versions_name_lookup = wp_list_pluck( $versions, 'name' );
177
178 foreach ( $missing_data as $product ) {
179
180 if ( ! in_array( $product['name'], $versions_name_lookup ) ) {
181 continue;
182 }
183
184 $plugin_file = plugin_basename( $product['file'] );
185 $product_key = array_search( $product['name'], wp_list_pluck( $this->get_products(), 'name' ) );
186 $version_info = $versions[ array_search( $product['name'], $versions_name_lookup ) ];
187 $version_info['license'] = $this->get_license_details( $product_key );
188
189 if ( version_compare( $product['version'], $version_info['new_version'], '<' ) ) {
190
191 if ( isset( $version_info['sections'] ) ) {
192 $version_info['sections'] = maybe_unserialize( $version_info['sections'] );
193 }
194
195 $can_update = $this->able_to_update( $version_info );
196
197 if ( is_array( $can_update ) ) {
198 $version_info['package'] = $can_update['reason_code'];
199 $version_info['download_link'] = $can_update['reason_code'];
200 $version_info['package_download_restriction'] = $can_update['description'];
201 }
202
203 $_transient_data->response[ $plugin_file ] = (object) $version_info;
204 }
205
206 $_transient_data->last_checked = time();
207 $_transient_data->checked[ $plugin_file ] = $product['version'];
208
209 }//end foreach
210 }//end if
211 }//end if
212
213 return $_transient_data;
214 }
215
216 /**
217 * Updates information on the "View version x.x details" page with custom data.
218 *
219 * @uses api_request()
220 *
221 * @since 1.4.20
222 *
223 * @param mixed $_data Default set of data.
224 * @param string $_action The current action.
225 * @param object $_args Request args.
226 * @return object $_data
227 */
228 public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
229 if ( 'plugin_information' != $_action ) {
230 return $_data;
231 }
232
233 if ( ! isset( $_args->slug ) ) {
234 return $_data;
235 }
236
237 $plugin_key = str_replace( '-', '_', $_args->slug );
238
239 if ( ! array_key_exists( $plugin_key, $this->products ) ) {
240 return $_data;
241 }
242
243 $version_info = $this->get_version_info( plugin_basename( $this->products[ $plugin_key ]['file'] ) );
244
245 if ( $version_info ) {
246 $_data = $version_info;
247 }
248
249 return $_data;
250 }
251
252 /**
253 * Return whether a particular plugin is missing version info.
254 *
255 * @since 1.4.20
256 *
257 * @param array $product Product details array.
258 * @param false|object $update_cache Optional argument to pass update cache.
259 * @return boolean
260 */
261 public function is_missing_version_info( $product, $update_cache = false ) {
262 return ! $this->get_version_info( plugin_basename( $product['file'] ), $update_cache );
263 }
264
265 /**
266 * Return the version update info for a particular plugin.
267 *
268 * @since 1.4.20
269 *
270 * @param string $slug The plugin slug.
271 * @param false|object $update_cache Optional argument to pass update cache.
272 * @return array|false Array if an update is available. False otherwise.
273 */
274 public function get_version_info( $slug, $update_cache = false ) {
275 if ( ! $update_cache ) {
276 $update_cache = get_site_transient( 'update_plugins' );
277 }
278
279 if ( ! is_object( $update_cache ) || empty( $update_cache->response ) || ! array_key_exists( $slug, $update_cache->response ) ) {
280 return false;
281 }
282
283 return $update_cache->response[ $slug ];
284 }
285
286 /**
287 * Display an error message when users attempt to update a plugin
288 * without a license or with an expired license.
289 *
290 * @since 1.4.20
291 *
292 * @param false|WP_Error $reply The messaage to return. Set to false by default.
293 * @param string $package Package URL. For Charitable extensions without a
294 * license or that have expired, we set this to a
295 * key. Kind of a hack to pass a message to this hook.
296 * @param Plugin_Upgrader $upgrader The Plugin_Upgrader object.
297 * @return false|WP_Error
298 */
299 public function set_upgrader_error_message( $reply, $package, $upgrader ) {
300 $ajax_skin = 'WP_Ajax_Upgrader_Skin' == get_class( $upgrader->skin );
301
302 if ( 'missing_license' == $package ) {
303 if ( $ajax_skin ) {
304 $message = sprintf( __( 'You have not activated your license key. Activate your license to update: %s', 'charitable' ),
305 admin_url( 'admin.php?page=charitable-settings&tab=licenses' )
306 );
307 } else {
308 $message = sprintf( __( 'You have not activated your license key. <a href="%s" target="_top">Activate your license to update.</a>', 'charitable' ),
309 admin_url( 'admin.php?page=charitable-settings&tab=licenses' )
310 );
311 }
312
313 return new WP_Error( 'missing_license_key', $message );
314 }
315
316 if ( false !== strpos( $package, 'expired_license:' ) ) {
317
318 $renewal_link = str_replace( 'expired_license:', '', $package );
319
320 if ( $ajax_skin ) {
321 $message = sprintf( __( 'Your license has expired. Renew your license key: %s', 'charitable' ),
322 $renewal_link
323 );
324 } else {
325 $message = sprintf( __( 'Your license has expired. <a href="%s" target="_blank">Renew your license key.</a>', 'charitable' ),
326 esc_url( $renewal_link )
327 );
328 }
329
330 return new WP_Error( 'expired_license_key', $message );
331 }
332
333 if ( false !== strpos( $package, 'missing_requirements:' ) ) {
334 $message = str_replace( 'missing_requirements:', '', htmlspecialchars_decode( $package ) );
335
336 return new WP_Error( 'missing_requirements_key', $message );
337 }
338
339 return $reply;
340 }
341
342 /**
343 * Checks whether the given plugin can be updated.
344 *
345 * @since 1.6.14
346 *
347 * @param array $version_info Version information.
348 * @return true|array If it can be updated, returns true. Otherwise
349 * returns an array with a reason_code and description.
350 */
351 protected function able_to_update( $version_info ) {
352 $changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $version_info['name'] . '&slug=' . $version_info['slug'] . '&TB_iframe=true&width=772&height=911' );
353
354 switch ( $version_info['package'] ) {
355
356 case 'missing_license':
357 return array(
358 'reason_code' => 'missing_license',
359 'description' => sprintf(
360 __( '<p>There is a new version of %1$s available but you have not activated your license. <a target="_top" href="%2$s">Activate your license</a> or <a target="_blank" class="thickbox" href="%3$s">view version %4$s details</a>.</p>', 'charitable' ),
361 esc_html( $version_info['name'] ),
362 admin_url( 'admin.php?page=charitable-settings&tab=licenses' ),
363 esc_url( $changelog_link ),
364 esc_html( $version_info['new_version'] )
365 ),
366 );
367
368 case 'expired_license':
369 $base_renewal_url = isset( $version_info['renewal_link'] ) ? $version_info['renewal_link'] : 'https://www.wpcharitable.com/account';
370
371 return array(
372 'reason_code' => 'expired_license',
373 'description' => sprintf(
374 __( '<p>There is a new version of %1$s available but your license has expired. <a target="_blank" href="%2$s">Renew your license</a> or <a target="_blank" class="thickbox" href="%3$s">view version %4$s details</a>.</p>', 'charitable' ),
375 esc_html( $version_info['name'] ),
376 charitable_ga_url(
377 $base_renewal_url,
378 urlencode( 'Expired License Notice'),
379 urlencode( 'Renew your license' )
380 ),
381 esc_url( $changelog_link ),
382 esc_html( $version_info['new_version'] )
383 ),
384 );
385
386 default:
387 if ( ! isset( $version_info['requirements'] ) ) {
388 return true;
389 }
390
391 $messages = array();
392
393 foreach ( $version_info['requirements'] as $type => $details ) {
394
395 switch ( $type ) {
396 case 'php':
397 if ( version_compare( phpversion(), $details, '<' ) ) {
398 $messages[] = esc_html(
399 sprintf(
400 __( '<li>Requires PHP version %s or greater.</li>' ),
401 $details
402 )
403 );
404 }
405 break;
406
407 case 'charitable':
408 if ( version_compare( charitable()->get_version(), $details, '<' ) ) {
409 $messages[] = esc_html(
410 sprintf(
411 __( 'Requires Charitable version %s or greater.' ),
412 $details
413 )
414 );
415 }
416 break;
417 }
418
419 if ( empty( $messages ) ) {
420 return true;
421 }
422
423 return array(
424 'reason_code' => 'missing_requirements',
425 'description' => sprintf(
426 __( '<p>There is a new version of %1$s available but you are missing the following minimum requirements:</p>%2$s', 'charitable' ),
427 esc_html( $version_info['name'] ),
428 '<ul>' . implode( '<br/>', $messages ) . '</ul>'
429 ),
430 );
431 }
432
433 return true;
434 }
435 }
436
437 /**
438 * Set upgrader package options.
439 *
440 * This is used for expired licenses and in certain cases for products that do
441 * not have a license activated.
442 *
443 * @since 1.4.20
444 *
445 * @param array $options Upgrader package options.
446 * @return array
447 */
448 public function set_upgrader_package_options( $options ) {
449 if ( 'expired_license' != $options['package'] && empty( $options['package'] ) ) {
450 return $options;
451 }
452
453 if ( ! array_key_exists( 'hook_extra', $options ) || ! array_key_exists( 'plugin', $options['hook_extra'] ) ) {
454 return $options;
455 }
456
457 list( $plugin_key, ) = explode( '/', str_replace( '-', '_', $options['hook_extra']['plugin'] ) );
458
459 if ( ! array_key_exists( $plugin_key, $this->products ) ) {
460 return $options;
461 }
462
463 /* Set up the renewal link for expired licenses. */
464 if ( 'expired_license' == $options['package'] ) {
465 $options['package'] = $this->get_expired_license_package( $options['hook_extra']['plugin'] );
466
467 return $options;
468 }
469
470 /* Set up the renewal link for plugins where minimum requirements haven't been met. */
471 if ( 'missing_requirements' == $options['package'] ) {
472 $options['package'] = $this->get_missing_requirements_package( $options['hook_extra']['plugin'] );
473
474 return $options;
475 }
476
477 $license_details = $this->get_license_details( $plugin_key );
478
479 if ( ! is_array( $license_details ) || ! array_key_exists( 'license', $license_details ) || empty( $license_details['license'] ) ) {
480 $options['package'] = 'missing_license';
481 }
482
483 return $options;
484 }
485
486 /**
487 * Return the package string for an expired license.
488 *
489 * @since 1.4.20
490 *
491 * @param string $plugin Plugin basename.
492 * @return string
493 */
494 public function get_expired_license_package( $plugin ) {
495 $version_info = $this->get_version_info( $plugin );
496 $base_renewal_url = isset( $version_info->renewal_link ) ? $version_info->renewal_link : 'https://www.wpcharitable.com/account';
497
498 return sprintf( 'expired_license:%s', charitable_ga_url(
499 $base_renewal_url,
500 urlencode( 'WordPress Dashboard'),
501 urlencode( 'Expired License' )
502 ));
503
504 }
505
506 /**
507 * Return the package string for a plugin missing requirements.
508 *
509 * @since 1.6.14
510 *
511 * @param string $plugin Plugin basename.
512 * @return string
513 */
514 public function get_missing_requirements_package( $plugin ) {
515 $version_info = $this->get_version_info( $plugin );
516
517 return sprintf(
518 'missing_requirements:%s',
519 $version_info->package_download_restriction
520 );
521 }
522
523 /**
524 * Register a product that requires licensing.
525 *
526 * @since 1.0.0
527 *
528 * @param string $item_name The title of the product.
529 * @param string $author The author of the product.
530 * @param string $version The current product version we have installed.
531 * @param string $file The path to the plugin file.
532 * @param string $url The base URL where the plugin is licensed. Defaults to Charitable_Licenses::UPDATE_URL.
533 * @return void
534 */
535 public function register_licensed_product( $item_name, $author, $version, $file, $url = false ) {
536 if ( ! $url ) {
537 $url = Charitable_Licenses::UPDATE_URL;
538 }
539
540 $product_key = $this->get_item_key( $item_name );
541
542 $this->products[ $product_key ] = array(
543 'name' => $item_name,
544 'author' => $author,
545 'version' => $version,
546 'url' => $url,
547 'file' => $file,
548 );
549
550 $licenses = $this->get_licenses();
551 $license = isset( $licenses[ $product_key ]['license'] ) ? trim( $licenses[ $product_key ]['license'] ) : '';
552
553 new Charitable_Plugin_Updater( $url, $file, array(
554 'version' => $version,
555 'license' => $license,
556 'item_name' => $item_name,
557 'author' => $author,
558 ) );
559
560 }
561
562 /**
563 * Return the list of products requiring licensing.
564 *
565 * @since 1.0.0
566 *
567 * @return array[]
568 */
569 public function get_products() {
570 return $this->products;
571 }
572
573 /**
574 * Return a specific product's details.
575 *
576 * @since 1.0.0
577 *
578 * @param string $item The item for which we are getting product details.
579 * @return string[]
580 */
581 public function get_product_license_details( $item ) {
582 return isset( $this->products[ $item ] ) ? $this->products[ $item ] : false;
583 }
584
585 /**
586 * Returns whether the given product has a valid license.
587 *
588 * @since 1.0.0
589 *
590 * @param string $item The item to check.
591 * @return boolean
592 */
593 public function has_valid_license( $item ) {
594 $license = $this->get_license_details( $item );
595
596 if ( ! $license || ! isset( $license['valid'] ) ) {
597 return false;
598 }
599
600 return $license['valid'];
601 }
602
603 /**
604 * Returns the license details for the given product.
605 *
606 * @since 1.0.0
607 *
608 * @param string $item The item to get the license for.
609 * @return mixed[]
610 */
611 public function get_license( $item ) {
612 $license = $this->get_license_details( $item );
613
614 if ( ! $license || ! is_array( $license ) ) {
615 return false;
616 }
617
618 return $license['license'];
619 }
620
621 /**
622 * Returns the active license details for the given product.
623 *
624 * @since 1.0.0
625 *
626 * @param string $item The item to get active licensing details for.
627 * @return mixed[]
628 */
629 public function get_license_details( $item ) {
630 $licenses = $this->get_licenses();
631
632 if ( ! isset( $licenses[ $item ] ) ) {
633 return false;
634 }
635
636 return $licenses[ $item ];
637 }
638
639 /**
640 * Return the list of licenses.
641 *
642 * Note: The licenses are not necessarily valid. If a user enters an invalid
643 * license, the license will be stored but it will be flagged as invalid.
644 *
645 * @since 1.0.0
646 *
647 * @return array[]
648 */
649 public function get_licenses() {
650 if ( ! isset( $this->licenses ) ) {
651 $this->licenses = charitable_get_option( 'licenses', array() );
652 }
653
654 return $this->licenses;
655 }
656
657 /**
658 * Verify a license.
659 *
660 * @since 1.0.0
661 *
662 * @param string $item The item to verify.
663 * @param string $license The license key for the item.
664 * @param boolean $force Whether to force the verification check.
665 * @return mixed[]
666 */
667 public function verify_license( $item, $license, $force = false ) {
668 $license = trim( $license );
669
670 if ( $license === $this->get_license( $item ) && ! $force ) {
671 return $this->get_license_details( $item );
672 }
673
674 $product_details = $this->get_product_license_details( $item );
675
676 /* This product was not correctly registered. */
677 if ( ! $product_details ) {
678 return;
679 }
680
681 /* Data to send in our API request */
682 $api_params = array(
683 'edd_action' => 'activate_license',
684 'license' => $license,
685 'item_name' => urlencode( $product_details['name'] ),
686 'url' => home_url(),
687 );
688
689 /* Call the custom API */
690 $response = wp_remote_post(
691 $product_details['url'],
692 array(
693 'timeout' => 15,
694 'sslverify' => false,
695 'body' => $api_params,
696 )
697 );
698
699 /* Make sure the response came back okay */
700 if ( is_wp_error( $response ) ) {
701 return;
702 }
703
704 $this->flush_update_cache();
705
706 $license_data = json_decode( wp_remote_retrieve_body( $response ) );
707
708 return array(
709 'license' => $license,
710 'expiration_date' => $license_data->expires,
711 'valid' => ( 'valid' === $license_data->license ),
712 );
713 }
714
715 /**
716 * Return the URL to deactivate a specific license.
717 *
718 * @since 1.0.0
719 *
720 * @param string $item The item to deactivate.
721 * @return string
722 */
723 public function get_license_deactivation_url( $item ) {
724 return esc_url( add_query_arg( array(
725 'charitable_action' => 'deactivate_license',
726 'product_key' => $item,
727 '_nonce' => wp_create_nonce( 'license' ),
728 ), admin_url( 'admin.php?page=charitable-settings&tab=licenses' ) ) );
729 }
730
731 /**
732 * Deactivate a license.
733 *
734 * @since 1.0.0
735 *
736 * @return void
737 */
738 public function deactivate_license() {
739 if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'license' ) ) {
740 wp_die( esc_attr__( 'Cheatin\' eh?!', 'charitable' ) );
741 }
742
743 $product_key = isset( $_REQUEST['product_key'] ) ? $_REQUEST['product_key'] : false;
744
745 /* Product key must be set */
746 if ( false === $product_key ) {
747 wp_die( esc_attr__( 'Missing product key', 'charitable' ) );
748 }
749
750 $product = $this->get_product_license_details( $product_key );
751
752 /* Make sure we have a valid product with a valid license. */
753 if ( ! $product || ! $this->has_valid_license( $product_key ) ) {
754 wp_die( esc_attr__( 'This product is not valid or does not have a valid license key.', 'charitable' ) );
755 }
756
757 $license = $this->get_license( $product_key );
758
759 /* Data to send to wpcharitable.com to deactivate the license. */
760 $api_params = array(
761 'edd_action' => 'deactivate_license',
762 'license' => $license,
763 'item_name' => urlencode( $product['name'] ),
764 'url' => home_url(),
765 );
766
767 /* Call the custom API. */
768 $response = wp_remote_post( $product['url'], array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
769
770 /* Make sure the response came back okay */
771 if ( is_wp_error( $response ) ) {
772 return;
773 }
774
775 $this->flush_update_cache();
776
777 /* Decode the license data */
778 $license_data = json_decode( wp_remote_retrieve_body( $response ) );
779
780 $settings = get_option( 'charitable_settings' );
781
782 unset( $settings['licenses'][ $product_key ] );
783
784 update_option( 'charitable_settings', $settings );
785
786 wp_redirect( add_query_arg( array( 'tab' => 'licenses' ), admin_url( 'admin.php?page=charitable-settings' ) ) );
787 exit;
788
789 }
790
791 /**
792 * Flush the version update cache.
793 *
794 * @since 1.4.20
795 *
796 * @return void
797 */
798 protected function flush_update_cache() {
799 wp_cache_delete( 'plugin_versions', 'charitable' );
800 set_site_transient( 'update_plugins', null );
801 }
802
803 /**
804 * Return a key for the item, based on the item name.
805 *
806 * @since 1.0.0
807 *
808 * @param string $item_name Name of the item.
809 * @return string
810 */
811 protected function get_item_key( $item_name ) {
812 return strtolower( str_replace( ' ', '_', $item_name ) );
813 }
814
815 /**
816 * Return the latest versions of Charitable plugins.
817 *
818 * @since 1.4.0
819 *
820 * @return array
821 */
822 protected function get_versions() {
823 $versions = wp_cache_get( 'plugin_versions', 'charitable' );
824
825 if ( false === $versions ) {
826
827 $licenses = array();
828
829 foreach ( $this->get_licenses() as $license ) {
830 if ( isset( $license['license'] ) ) {
831 $licenses[] = $license['license'];
832 }
833 }
834
835 $response = wp_remote_post(
836 Charitable_Licenses::UPDATE_URL . '/edd-api/versions-v2/',
837 array(
838 'sslverify' => false,
839 'timeout' => 15,
840 'body' => array(
841 'licenses' => $licenses,
842 'url' => home_url(),
843 ),
844 )
845 );
846
847 $versions = wp_remote_retrieve_body( $response );
848
849 $versions = json_decode( $versions, true );
850
851 wp_cache_set( 'plugin_versions', $versions, 'charitable' );
852 }//end if
853
854 return $versions;
855 }
856 }
857
858 endif;
859