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 +241 -335 1.6.7 → 1.8.13 View file →
@@ -2,16 +2,20 @@
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
7 - * @author Eric Daams
8 - * @copyright Copyright (c) 2018, Studio 164a
6 + * @version 1.8.2
7 + * @author David Bisset
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 -if ( ! defined( 'ABSPATH' ) ) { exit; }
15 +if ( ! defined( 'ABSPATH' ) ) {
16 + exit;
17 +}
14 18
15 19 if ( ! class_exists( 'Charitable_Licenses' ) ) :
16 20
17 21 /**
@@ -21,9 +25,9 @@
21 25 */
22 26 class Charitable_Licenses {
23 27
24 28 /* @var string */
25 - const UPDATE_URL = 'https://www.wpcharitable.com';
29 + const UPDATE_URL = 'https://wpcharitable.com';
26 30
27 31 /**
28 32 * The single instance of this class.
29 33 *
@@ -45,8 +49,15 @@
45 49 */
46 50 private $licenses;
47 51
48 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 + /**
49 60 * Cached update data.
50 61 *
51 62 * @var array
52 63 */
@@ -59,13 +70,9 @@
59 70 *
60 71 * @return Charitable_Licenses
61 72 */
62 73 public static function get_instance() {
63 - if ( is_null( self::$instance ) ) {
64 - self::$instance = new self();
65 - }
66 -
67 - return self::$instance;
74 + return self::$instance ??= new self();
68 75 }
69 76
70 77 /**
71 78 * Create class object.
@@ -72,88 +79,79 @@
72 79 *
73 80 * @since 1.0.0
74 81 */
75 82 private function __construct() {
76 - $this->products = array();
77 - $this->update_data = array();
78 83
79 - add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_for_updates' ) );
80 - add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
81 - add_action( 'charitable_deactivate_license', array( $this, 'deactivate_license' ) );
82 - add_filter( 'upgrader_pre_download', array( $this, 'set_upgrader_error_message' ), 10, 3 );
83 - add_filter( 'upgrader_package_options', array( $this, 'set_upgrader_package_options' ) );
84 + $registry = charitable()->registry();
85 +
86 + if ( ! $registry->has( 'charitable_licenses' ) ) {
87 + $registry->register_object( CharitableLicenses::get_instance() );
88 + }
84 89 }
85 90
86 91 /**
87 - * Checks for any Charitable extensions with updates.
92 + * Checks licenses (new and legacy) to see if any are valid.
88 93 *
89 - * @since 1.4.0
94 + * @since 1.7.0
90 95 *
91 - * @param array $_transient_data The plugin updates data.
92 - * @return array
96 + * @return boolean
93 97 */
94 - public function check_for_updates( $_transient_data ) {
95 - global $pagenow;
98 + public function is_pro() {
96 99
97 - if ( ! is_object( $_transient_data ) ) {
98 - $_transient_data = new stdClass;
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
99 102 }
100 103
101 - if ( 'plugins.php' == $pagenow && is_multisite() ) {
102 - return $_transient_data;
103 - }
104 -
105 - /* Loop over our licensed products and check whether any are missing transient data. */
106 - $missing_data = array();
107 -
108 - foreach ( $this->get_products() as $product ) {
109 - if ( $this->is_missing_version_info( $product, $_transient_data ) ) {
110 - $missing_data[] = $product;
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'] ) ) {
109 + return true;
111 110 }
112 111 }
113 112
114 - /* If we are missing data for any of our products, check whether any have an update. */
115 - if ( ! empty( $missing_data ) ) {
113 + $registry = charitable()->registry();
114 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->is_pro();
115 + }
116 116
117 - $versions = $this->get_versions();
117 + /**
118 + * Checks the "v3" license (starting Nov 2022) to see if it's valid.
119 + * If valid, normally doesn't require other license/pro checks.
120 + *
121 + * @since 1.7.0.4
122 + *
123 + * @return boolean
124 + */
125 + public function is_v3_license_valid() {
118 126
119 - unset( $versions['request_speed'] );
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
129 + }
120 130
121 - if ( ! empty( $versions ) ) {
131 + $registry = charitable()->registry();
132 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->is_v3_license_valid();
133 + }
122 134
123 - $versions_name_lookup = wp_list_pluck( $versions, 'name' );
135 + /**
136 + * Checks for any Charitable extensions with updates.
137 + *
138 + * @since 1.4.0
139 + *
140 + * @param array $_transient_data The plugin updates data.
141 + * @return array
142 + */
143 + public function check_for_updates( $_transient_data ) {
124 144
125 - foreach ( $missing_data as $product ) {
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
147 + }
126 148
127 - if ( ! in_array( $product['name'], $versions_name_lookup ) ) {
128 - continue;
129 - }
149 + $registry = charitable()->registry();
150 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->check_for_updates( $_transient_data );
151 + }
130 152
131 - $plugin_file = plugin_basename( $product['file'] );
132 - $product_key = array_search( $product['name'], wp_list_pluck( $this->get_products(), 'name' ) );
133 - $version_info = $versions[ array_search( $product['name'], $versions_name_lookup ) ];
134 - $version_info['license'] = $this->get_license_details( $product_key );
135 153
136 - if ( version_compare( $product['version'], $version_info['new_version'], '<' ) ) {
137 -
138 - if ( isset( $version_info['sections'] ) ) {
139 - $version_info['sections'] = maybe_unserialize( $version_info['sections'] );
140 - }
141 -
142 - $_transient_data->response[ $plugin_file ] = (object) $version_info;
143 -
144 - }
145 -
146 - $_transient_data->last_checked = time();
147 - $_transient_data->checked[ $plugin_file ] = $product['version'];
148 -
149 - }//end foreach
150 - }//end if
151 - }//end if
152 -
153 - return $_transient_data;
154 - }
155 -
156 154 /**
157 155 * Updates information on the "View version x.x details" page with custom data.
158 156 *
159 157 * @uses api_request()
@@ -161,33 +159,19 @@
161 159 * @since 1.4.20
162 160 *
163 161 * @param mixed $_data Default set of data.
164 162 * @param string $_action The current action.
165 - * @param object $_args Request args.
163 + * @param object $_args Request args.
166 164 * @return object $_data
167 165 */
168 166 public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
169 - if ( 'plugin_information' != $_action ) {
170 - return $_data;
171 - }
172 167
173 - if ( ! isset( $_args->slug ) ) {
174 - 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
175 170 }
176 171
177 - $plugin_key = str_replace( '-', '_', $_args->slug );
178 -
179 - if ( ! array_key_exists( $plugin_key, $this->products ) ) {
180 - return $_data;
181 - }
182 -
183 - $version_info = $this->get_version_info( plugin_basename( $this->products[ $plugin_key ]['file'] ) );
184 -
185 - if ( $version_info ) {
186 - $_data = $version_info;
187 - }
188 -
189 - return $_data;
172 + $registry = charitable()->registry();
173 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->plugins_api_filter( $_data, $_action, $_args );
190 174 }
191 175
192 176 /**
193 177 * Return whether a particular plugin is missing version info.
@@ -198,9 +182,15 @@
198 182 * @param false|object $update_cache Optional argument to pass update cache.
199 183 * @return boolean
200 184 */
201 185 public function is_missing_version_info( $product, $update_cache = false ) {
202 - 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 );
203 193 }
204 194
205 195 /**
206 196 * Return the version update info for a particular plugin.
@@ -211,128 +201,71 @@
211 201 * @param false|object $update_cache Optional argument to pass update cache.
212 202 * @return array|false Array if an update is available. False otherwise.
213 203 */
214 204 public function get_version_info( $slug, $update_cache = false ) {
215 - if ( ! $update_cache ) {
216 - $update_cache = get_site_transient( 'update_plugins' );
217 - }
218 205
219 - if ( ! is_object( $update_cache ) || empty( $update_cache->response ) || ! array_key_exists( $slug, $update_cache->response ) ) {
220 - 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
221 208 }
222 209
223 - return $update_cache->response[ $slug ];
210 + $registry = charitable()->registry();
211 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->get_version_info( $slug, $update_cache );
224 212 }
225 213
226 214 /**
227 - * Display an error message when users attempt to update a plugin
228 - * without a license or with an expired license.
215 + * Checks whether the given plugin can be updated.
229 216 *
230 - * @since 1.4.20
231 - *
232 - * @param false|WP_Error $reply The messaage to return. Set to false by default.
233 - * @param string $package Package URL. For Charitable extensions without a
234 - * license or that have expired, we set this to a
235 - * key. Kind of a hack to pass a message to this hook.
236 - * @param Plugin_Upgrader $upgrader The Plugin_Upgrader object.
237 - * @return false|WP_Error
217 + * @since 1.6.14
218 + *
219 + * @param array $version_info Version information.
220 + * @return true|array If it can be updated, returns true. Otherwise
221 + * returns an array with a reason_code and description.
238 222 */
239 - public function set_upgrader_error_message( $reply, $package, $upgrader ) {
240 - $ajax_skin = 'WP_Ajax_Upgrader_Skin' == get_class( $upgrader->skin );
223 + protected function able_to_update( $version_info ) {
241 224
242 - if ( 'missing_license' == $package ) {
243 - if ( $ajax_skin ) {
244 - $message = sprintf( __( 'You have not activated your license key. Activate your license to update: %s', 'charitable' ),
245 - admin_url( 'admin.php?page=charitable-settings&tab=licenses' )
246 - );
247 - } else {
248 - $message = sprintf( __( 'You have not activated your license key. <a href="%s" target="_top">Activate your license to update.</a>', 'charitable' ),
249 - admin_url( 'admin.php?page=charitable-settings&tab=licenses' )
250 - );
251 - }
252 -
253 - return new WP_Error( 'missing_license_key', $message );
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
254 227 }
255 228
256 - if ( false !== strpos( $package, 'expired_license:' ) ) {
257 -
258 - $renewal_link = str_replace( 'expired_license:', '', $package );
259 -
260 - if ( $ajax_skin ) {
261 - $message = sprintf( __( 'Your license has expired. Renew your license key: %s', 'charitable' ),
262 - $renewal_link
263 - );
264 - } else {
265 - $message = sprintf( __( 'Your license has expired. <a href="%s" target="_blank">Renew your license key.</a>', 'charitable' ),
266 - esc_url( $renewal_link )
267 - );
268 - }
269 -
270 - return new WP_Error( 'expired_license_key', $message );
271 - }
272 -
273 - return $reply;
229 + $registry = charitable()->registry();
230 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->able_to_update( $version_info );
274 231 }
275 232
276 233 /**
277 - * Set upgrader package options.
234 + * Return the package string for an expired license.
278 235 *
279 - * This is used for expired licenses and in certain cases for products that do
280 - * not have a license activated.
281 - *
282 236 * @since 1.4.20
283 237 *
284 - * @param array $options Upgrader package options.
285 - * @return array
286 - */
287 - public function set_upgrader_package_options( $options ) {
288 - if ( 'expired_license' != $options['package'] && empty( $options['package'] ) ) {
289 - return $options;
290 - }
238 + * @param string $plugin Plugin basename.
239 + * @return string
240 + */
241 + public function get_expired_license_package( $plugin ) {
291 242
292 - if ( ! array_key_exists( 'hook_extra', $options ) || ! array_key_exists( 'plugin', $options['hook_extra'] ) ) {
293 - return $options;
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
294 245 }
295 246
296 - list( $plugin_key, ) = explode( '/', str_replace( '-', '_', $options['hook_extra']['plugin'] ) );
247 + $registry = charitable()->registry();
248 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->get_expired_license_package( $plugin );
249 + }
297 250
298 - if ( ! array_key_exists( $plugin_key, $this->products ) ) {
299 - return $options;
300 - }
301 251
302 - /* Set up the renewal link for expired licenses. */
303 - if ( 'expired_license' == $options['package'] ) {
304 - $options['package'] = $this->get_expired_license_package( $options['hook_extra']['plugin'] );
305 -
306 - return $options;
307 - }
308 -
309 - $license_details = $this->get_license_details( $plugin_key );
310 -
311 - if ( ! is_array( $license_details ) || ! array_key_exists( 'license', $license_details ) || empty( $license_details['license'] ) ) {
312 - $options['package'] = 'missing_license';
313 - }
314 -
315 - return $options;
316 - }
317 -
318 252 /**
319 - * Return the package string for an expired license.
253 + * Return the package string for a plugin missing requirements.
320 254 *
321 - * @since 1.4.20
255 + * @since 1.6.14
322 256 *
323 257 * @param string $plugin Plugin basename.
324 258 * @return string
325 259 */
326 - public function get_expired_license_package( $plugin ) {
327 - $version_info = $this->get_version_info( $plugin );
328 - $base_renewal_url = isset( $version_info->renewal_link ) ? $version_info->renewal_link : 'https://www.wpcharitable.com/account';
260 + public function get_missing_requirements_package( $plugin ) {
329 261
330 - return sprintf( 'expired_license:%s', add_query_arg( array(
331 - 'utm_source' => 'plugin-upgrades',
332 - 'utm_medium' => 'wordpress-dashboard',
333 - 'utm_campaign' => 'expired-license',
334 - ), $base_renewal_url ) );
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 );
335 268 }
336 269
337 270 /**
338 271 * Register a product that requires licensing.
@@ -346,31 +279,15 @@
346 279 * @param string $url The base URL where the plugin is licensed. Defaults to Charitable_Licenses::UPDATE_URL.
347 280 * @return void
348 281 */
349 282 public function register_licensed_product( $item_name, $author, $version, $file, $url = false ) {
350 - if ( ! $url ) {
351 - $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
352 286 }
353 287
354 - $product_key = $this->get_item_key( $item_name );
355 -
356 - $this->products[ $product_key ] = array(
357 - 'name' => $item_name,
358 - 'author' => $author,
359 - 'version' => $version,
360 - 'url' => $url,
361 - 'file' => $file,
362 - );
363 -
364 - $licenses = $this->get_licenses();
365 - $license = isset( $licenses[ $product_key ]['license'] ) ? trim( $licenses[ $product_key ]['license'] ) : '';
366 -
367 - new Charitable_Plugin_Updater( $url, $file, array(
368 - 'version' => $version,
369 - 'license' => $license,
370 - 'item_name' => $item_name,
371 - 'author' => $author,
372 - ) );
288 + $registry = charitable()->registry();
289 + $registry->get( 'CharitableLicenses\CharitableLicenses' )->register_licensed_product( $item_name, $author, $version, $file, $url );
373 290 }
374 291
375 292 /**
376 293 * Return the list of products requiring licensing.
@@ -379,9 +296,15 @@
379 296 *
380 297 * @return array[]
381 298 */
382 299 public function get_products() {
383 - 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();
384 307 }
385 308
386 309 /**
387 310 * Return a specific product's details.
@@ -391,9 +314,15 @@
391 314 * @param string $item The item for which we are getting product details.
392 315 * @return string[]
393 316 */
394 317 public function get_product_license_details( $item ) {
395 - 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 );
396 325 }
397 326
398 327 /**
399 328 * Returns whether the given product has a valid license.
@@ -403,15 +332,15 @@
403 332 * @param string $item The item to check.
404 333 * @return boolean
405 334 */
406 335 public function has_valid_license( $item ) {
407 - $license = $this->get_license_details( $item );
408 336
409 - if ( ! $license || ! isset( $license['valid'] ) ) {
410 - 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
411 339 }
412 340
413 - return $license['valid'];
341 + $registry = charitable()->registry();
342 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->has_valid_license( $item );
414 343 }
415 344
416 345 /**
417 346 * Returns the license details for the given product.
@@ -421,15 +350,15 @@
421 350 * @param string $item The item to get the license for.
422 351 * @return mixed[]
423 352 */
424 353 public function get_license( $item ) {
425 - $license = $this->get_license_details( $item );
426 354
427 - if ( ! $license || ! is_array( $license ) ) {
428 - 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
429 357 }
430 358
431 - return $license['license'];
359 + $registry = charitable()->registry();
360 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->get_license( $item );
432 361 }
433 362
434 363 /**
435 364 * Returns the active license details for the given product.
@@ -439,15 +368,15 @@
439 368 * @param string $item The item to get active licensing details for.
440 369 * @return mixed[]
441 370 */
442 371 public function get_license_details( $item ) {
443 - $licenses = $this->get_licenses();
444 372
445 - if ( ! isset( $licenses[ $item ] ) ) {
446 - 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
447 375 }
448 376
449 - return $licenses[ $item ];
377 + $registry = charitable()->registry();
378 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->get_license_details( $item );
450 379 }
451 380
452 381 /**
453 382 * Return the list of licenses.
@@ -459,13 +388,15 @@
459 388 *
460 389 * @return array[]
461 390 */
462 391 public function get_licenses() {
463 - if ( ! isset( $this->licenses ) ) {
464 - $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
465 395 }
466 396
467 - return $this->licenses;
397 + $registry = charitable()->registry();
398 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->get_licenses();
468 399 }
469 400
470 401 /**
471 402 * Verify a license.
@@ -474,53 +405,19 @@
474 405 *
475 406 * @param string $item The item to verify.
476 407 * @param string $license The license key for the item.
477 408 * @param boolean $force Whether to force the verification check.
409 + * @param boolean $legacy Whether to use the legacy API (?).
478 410 * @return mixed[]
479 411 */
480 - public function verify_license( $item, $license, $force = false ) {
481 - $license = trim( $license );
412 + public function verify_license( $item, $license, $force = false, $legacy = false ) {
482 413
483 - if ( $license === $this->get_license( $item ) && ! $force ) {
484 - 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
485 416 }
486 417
487 - $product_details = $this->get_product_license_details( $item );
488 -
489 - /* This product was not correctly registered. */
490 - if ( ! $product_details ) {
491 - return;
492 - }
493 -
494 - /* Data to send in our API request */
495 - $api_params = array(
496 - 'edd_action' => 'activate_license',
497 - 'license' => $license,
498 - 'item_name' => urlencode( $product_details['name'] ),
499 - 'url' => home_url(),
500 - );
501 -
502 - /* Call the custom API */
503 - $response = wp_remote_post( $product_details['url'], array(
504 - 'timeout' => 15,
505 - 'sslverify' => false,
506 - 'body' => $api_params,
507 - ) );
508 -
509 - /* Make sure the response came back okay */
510 - if ( is_wp_error( $response ) ) {
511 - return;
512 - }
513 -
514 - $this->flush_update_cache();
515 -
516 - $license_data = json_decode( wp_remote_retrieve_body( $response ) );
517 -
518 - return array(
519 - 'license' => $license,
520 - 'expiration_date' => $license_data->expires,
521 - 'valid' => ( 'valid' === $license_data->license ),
522 - );
418 + $registry = charitable()->registry();
419 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->verify_license( $item, $license, $force, $legacy );
523 420 }
524 421
525 422 /**
526 423 * Return the URL to deactivate a specific license.
@@ -530,13 +427,15 @@
530 427 * @param string $item The item to deactivate.
531 428 * @return string
532 429 */
533 430 public function get_license_deactivation_url( $item ) {
534 - return esc_url( add_query_arg( array(
535 - 'charitable_action' => 'deactivate_license',
536 - 'product_key' => $item,
537 - '_nonce' => wp_create_nonce( 'license' ),
538 - ), admin_url( 'admin.php?page=charitable-settings&tab=licenses' ) ) );
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 );
539 438 }
540 439
541 440 /**
542 441 * Deactivate a license.
@@ -545,66 +444,33 @@
545 444 *
546 445 * @return void
547 446 */
548 447 public function deactivate_license() {
549 - if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'license' ) ) {
550 - wp_die( esc_attr__( 'Cheatin\' eh?!', 'charitable' ) );
551 - }
552 448
553 - $product_key = isset( $_REQUEST['product_key'] ) ? $_REQUEST['product_key'] : false;
554 -
555 - /* Product key must be set */
556 - if ( false === $product_key ) {
557 - 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
558 451 }
559 452
560 - $product = $this->get_product_license_details( $product_key );
561 -
562 - /* Make sure we have a valid product with a valid license. */
563 - if ( ! $product || ! $this->has_valid_license( $product_key ) ) {
564 - wp_die( esc_attr__( 'This product is not valid or does not have a valid license key.', 'charitable' ) );
565 - }
566 -
567 - $license = $this->get_license( $product_key );
568 -
569 - /* Data to send to wpcharitable.com to deactivate the license. */
570 - $api_params = array(
571 - 'edd_action' => 'deactivate_license',
572 - 'license' => $license,
573 - 'item_name' => urlencode( $product['name'] ),
574 - 'url' => home_url(),
575 - );
576 -
577 - /* Call the custom API. */
578 - $response = wp_remote_post( $product['url'], array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
579 -
580 - /* Make sure the response came back okay */
581 - if ( is_wp_error( $response ) ) {
582 - return;
583 - }
584 -
585 - $this->flush_update_cache();
586 -
587 - /* Decode the license data */
588 - $license_data = json_decode( wp_remote_retrieve_body( $response ) );
589 -
590 - $settings = get_option( 'charitable_settings' );
591 -
592 - unset( $settings['licenses'][ $product_key ] );
593 -
594 - update_option( 'charitable_settings', $settings );
453 + $registry = charitable()->registry();
454 + $registry->get( 'CharitableLicenses\CharitableLicenses' )->deactivate_license();
595 455 }
596 456
597 457 /**
598 458 * Flush the version update cache.
599 459 *
600 - * @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.
601 462 *
602 463 * @return void
603 464 */
604 465 protected function flush_update_cache() {
605 - wp_cache_delete( 'plugin_versions', 'charitable' );
606 - 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();
607 473 }
608 474
609 475 /**
610 476 * Return a key for the item, based on the item name.
@@ -614,51 +480,91 @@
614 480 * @param string $item_name Name of the item.
615 481 * @return string
616 482 */
617 483 protected function get_item_key( $item_name ) {
618 - 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 );
619 491 }
620 492
621 493 /**
622 494 * Return the latest versions of Charitable plugins.
623 495 *
624 - * @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.
625 499 *
626 500 * @return array
627 501 */
628 502 protected function get_versions() {
629 - $versions = wp_cache_get( 'plugin_versions', 'charitable' );
630 503
631 - 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 + }
632 507
633 - $licenses = array();
508 + $registry = charitable()->registry();
509 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->get_versions();
510 + }
634 511
635 - foreach ( $this->get_licenses() as $license ) {
636 - if ( isset( $license['license'] ) ) {
637 - $licenses[] = $license['license'];
638 - }
639 - }
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() {
640 525
641 - $response = wp_remote_post(
642 - Charitable_Licenses::UPDATE_URL . '/edd-api/versions-v2/',
643 - array(
644 - 'sslverify' => false,
645 - 'timeout' => 15,
646 - 'body' => array(
647 - 'licenses' => $licenses,
648 - 'url' => home_url(),
649 - ),
650 - )
651 - );
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
528 + }
652 529
653 - $versions = wp_remote_retrieve_body( $response );
530 + $registry = charitable()->registry();
531 + $registry->get( 'CharitableLicenses\CharitableLicenses' )->log_failed_request();
532 + }
654 533
655 - $versions = json_decode( $versions, true );
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() {
656 542
657 - wp_cache_set( 'plugin_versions', $versions, 'charitable' );
658 - }//end if
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
545 + }
659 546
660 - return $versions;
547 + $registry = charitable()->registry();
548 + return $registry->get( 'CharitableLicenses\CharitableLicenses' )->request_recently_failed();
549 + }
550 +
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() {
560 +
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
563 + }
564 +
565 + $registry = charitable()->registry();
566 + $registry->get( 'CharitableLicenses\CharitableLicenses' )->ajax_license_check();
661 567 }
662 568 }
663 569
664 570 endif;