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