PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 2.0.5
Advanced Ads – Ad Manager & AdSense v2.0.5
2.0.25 2.0.24 2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / admin / includes / class-licenses.php
advanced-ads / admin / includes Last commit date
ad-health-notices.php 1 year ago class-ad-network-ad-unit.php 1 year ago class-ad-network.php 1 year ago class-licenses.php 1 year ago class-notices.php 1 year ago class-overview-widgets.php 1 year ago notices.php 1 year ago
class-licenses.php
696 lines
1 <?php // phpcs:ignoreFile
2 /**
3 * Handle add-on licenses
4 *
5 * @package AdvancedAds
6 * @author Advanced Ads <info@wpadvancedads.com>
7 * @since 1.x.x
8 */
9
10 use AdvancedAds\Utilities\Data;
11
12 defined( 'ABSPATH' ) || exit;
13
14 /**
15 * Handle add-on licenses
16 */
17 class Advanced_Ads_Admin_Licenses {
18 /**
19 * License API endpoint URL
20 *
21 * @const string
22 */
23 const API_ENDPOINT = 'https://wpadvancedads.com/license-api/';
24
25 /**
26 * Add-on slugs and their EDD ID
27 *
28 * @const array
29 */
30 const ADDON_SLUGS_ID = [
31 'advanced-ads-gam' => 215545,
32 'advanced-ads-layer' => 686,
33 'advanced-ads-pro' => 1742,
34 'advanced-ads-responsive' => 678,
35 'advanced-ads-selling' => 35300,
36 'advanced-ads-sticky' => 683,
37 'advanced-ads-tracking' => 638,
38 ];
39
40 /**
41 * Advanced_Ads_Admin_Licenses constructor.
42 */
43 private function __construct() {
44 add_action( 'plugins_loaded', [ $this, 'wp_plugins_loaded' ] );
45
46 // todo: check if this is loaded late enough and all add-ons are registered already.
47 add_filter( 'upgrader_pre_download', [ $this, 'addon_upgrade_filter' ], 10, 3 );
48 }
49
50 /**
51 * Actions and filter available after all plugins are initialized
52 */
53 public function wp_plugins_loaded() {
54 add_action( 'http_api_debug', [ $this, 'update_license_after_version_info' ], 10, 5 );
55 }
56
57 /**
58 * Return an instance of this class.
59 *
60 * @return self object A single instance of this class.
61 */
62 public static function get_instance() {
63 static $instance;
64
65 // If the single instance hasn't been set, set it now.
66 if ( null === $instance ) {
67 $instance = new self();
68 }
69
70 return $instance;
71 }
72
73 /**
74 * Save license key
75 *
76 * @param string $addon string with add-on identifier.
77 * @param string $plugin_name name of the add-on.
78 * @param string $options_slug slug of the option in the database.
79 * @param string $license_key license key.
80 *
81 * @return string
82 * @since 1.2.0
83 */
84 public function activate_license( $addon = '', $plugin_name = '', $options_slug = '', $license_key = '' ) {
85 if ( '' === $addon || '' === $plugin_name || '' === $options_slug ) {
86 return __( 'Error while trying to register the license. Please contact support.', 'advanced-ads' );
87 }
88
89 $license_key = esc_attr( trim( $license_key ) );
90 if ( '' === $license_key ) {
91 return __( 'Please enter a valid license key', 'advanced-ads' );
92 }
93
94 if ( has_filter( 'advanced_ads_license_' . $options_slug ) ) {
95 return apply_filters( 'advanced_ads_license_' . $options_slug, false, __METHOD__, $plugin_name, $options_slug, $license_key );
96 }
97
98 /**
99 * We need to remove the mltlngg_get_url_translated filter added by Multilanguage by BestWebSoft, https://wordpress.org/plugins/multilanguage/
100 * it causes the URL to look much different than it originally is
101 * we are adding it again later
102 */
103 remove_filter( 'home_url', 'mltlngg_get_url_translated' );
104
105 $api_params = [
106 'edd_action' => 'activate_license',
107 'license' => $license_key,
108 'item_id' => self::ADDON_SLUGS_ID[ $options_slug ] ?? false,
109 'item_name' => rawurlencode( $plugin_name ),
110 'url' => home_url(),
111 ];
112
113 /**
114 * Re-add the filter removed from above
115 */
116 if ( function_exists( 'mltlngg_get_url_translated' ) ) {
117 add_filter( 'home_url', 'mltlngg_get_url_translated' );
118 }
119
120 // Call the custom API.
121 $response = wp_remote_post(
122 self::API_ENDPOINT,
123 [
124 'timeout' => 15,
125 'sslverify' => false,
126 'body' => $api_params,
127 ]
128 );
129
130 // show license debug output if constant is set.
131 if ( defined( 'ADVANCED_ADS_SHOW_LICENSE_RESPONSE' ) ) {
132 return '<p><strong>' . esc_html__( 'The license status does not change as long as ADVANCED_ADS_SHOW_LICENSE_RESPONSE is enabled in wp-config.php.', 'advanced-ads' ) . '</strong></p>' .
133 '<pre>' . print_r( $response, true ) . '</pre>'; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
134 }
135
136 /**
137 * Send the user to our support when his request is blocked by our firewall
138 */
139 $error = $this->blocked_by_firewall( $response );
140 if ( $error ) {
141 return $error;
142 }
143
144 if ( is_wp_error( $response ) ) {
145 $body = wp_remote_retrieve_body( $response );
146 if ( $body ) {
147 return $body;
148 } else {
149 $curl = curl_version();
150
151 return __( 'License couldn’t be activated. Please try again later.', 'advanced-ads' ) . " (cURL {$curl['version']})";
152 }
153 }
154
155 $license_data = json_decode( wp_remote_retrieve_body( $response ) );
156 // save license status.
157 if ( ! empty( $license_data->license ) ) {
158 $this->clear_license_cache();
159 update_option( $options_slug . '-license-status', $license_data->license, false );
160 }
161 if ( ! empty( $license_data->expires ) ) {
162 $this->clear_license_cache();
163 update_option( $options_slug . '-license-expires', $license_data->expires, false );
164 }
165
166 // display activation problem.
167 if ( ! empty( $license_data->error ) ) {
168 // user friendly texts for errors.
169 $errors = [
170 'license_not_activable' => __( 'This is the bundle license key.', 'advanced-ads' ),
171 'item_name_mismatch' => __( 'This is not the correct key for this add-on.', 'advanced-ads' ),
172 'no_activations_left' => __( 'There are no activations left.', 'advanced-ads' )
173 . '&nbsp;'
174 . sprintf(
175 /* translators: %1$s is a starting link tag, %2$s is the closing one. */
176 __( 'You can manage activations in %1$syour account%2$s.', 'advanced-ads' ),
177 '<a href="https://wpadvancedads.com/account/?utm_source=advanced-ads&utm_medium=link&utm_campaign=settings-licenses-activations-left" target="_blank">',
178 '</a>'
179 ) . '&nbsp;'
180 . sprintf(
181 /* translators: %1$s is a starting link tag, %2$s is the closing one. */
182 __( '%1$sUpgrade%2$s for more activations.', 'advanced-ads' ),
183 '<a href="https://wpadvancedads.com/account/upgrades/?utm_source=advanced-ads&utm_medium=link&utm_campaign=settings-licenses-activations-left" target="_blank">',
184 '</a>'
185 ),
186 ];
187 $error = isset( $errors[ $license_data->error ] ) ? $errors[ $license_data->error ] : $license_data->error;
188 if ( 'expired' === $license_data->error ) {
189 return 'ex';
190 } else { // phpcs:ignore
191 if ( isset( $errors[ $license_data->error ] ) ) {
192 return $error;
193 } else {
194 return sprintf(
195 /* translators: %s is a string containing information about the issue. */
196 __( 'License is invalid. Reason: %s', 'advanced-ads' ),
197 $error
198 );
199 }
200 }
201 } else {
202 // reset license_expires admin notification.
203 Advanced_Ads_Admin_Notices::get_instance()->remove_from_queue( 'license_expires' ); // this one is no longer added, but we keep the check here in case it is still in the queue for some users.
204 Advanced_Ads_Admin_Notices::get_instance()->remove_from_queue( 'license_expired' ); // this one is no longer added, but we keep the check here in case it is still in the queue for some users.
205 Advanced_Ads_Admin_Notices::get_instance()->remove_from_queue( 'license_invalid' );
206 // save license key.
207 $licenses = $this->get_licenses();
208 $licenses[ $addon ] = $license_key;
209 $this->save_licenses( $licenses );
210 }
211
212 return 1;
213 }
214
215 /**
216 * Check if a request was blocked by our firewall
217 *
218 * @param array $response response from license call.
219 *
220 * @return mixed message or false
221 */
222 public function blocked_by_firewall( $response ) {
223 $response_code = wp_remote_retrieve_response_code( $response );
224 if ( 403 === $response_code ) {
225 $blocked_information = '';
226 if ( isset( $response['body'] ) ) {
227 // look for the IP address in this line: `<td><span>95.90.238.103</span></td>`.
228 $pattern = '/<span>([.0-9]*)<\/span>/';
229 $matches = [];
230 preg_match( $pattern, $response['body'], $matches );
231 $ip = isset( $matches[1] ) ? $matches[1] : '';
232 $blocked_information = 'IP: ' . $ip;
233 }
234
235 /* translators: %s is a list of server information like IP address. Just keep it as is. */
236 return sprintf( __( 'Your request was blocked by our firewall. Please send us the following information to unblock you: %s.', 'advanced-ads' ), $blocked_information );
237 }
238
239 return false;
240 }
241
242 /**
243 * Check if a specific license key was already activated for the current page
244 *
245 * @param string $license_key license key.
246 * @param string $plugin_name name of the add-on.
247 * @param string $options_slug slug of the option in the database.
248 *
249 * @return bool true if already activated
250 * @since 1.6.17
251 * @deprecated since version 1.7.2 because it only checks if a key is valid, not if the url registered with that key
252 */
253 public function check_license( $license_key = '', $plugin_name = '', $options_slug = '' ) {
254 if ( has_filter( 'advanced_ads_license_' . $options_slug ) ) {
255 return apply_filters( 'advanced_ads_license_' . $options_slug, false, __METHOD__, $plugin_name, $options_slug, $license_key );
256 }
257
258 $api_params = [
259 'edd_action' => 'check_license',
260 'license' => $license_key,
261 'item_id' => self::ADDON_SLUGS_ID[ $options_slug ] ?? false,
262 'item_name' => rawurlencode( $plugin_name ),
263 ];
264 $response = wp_remote_get(
265 add_query_arg( $api_params, 'https://wpadvancedads.com/' ),
266 [
267 'timeout' => 15,
268 'sslverify' => false,
269 ]
270 );
271 if ( is_wp_error( $response ) ) {
272 return false;
273 }
274 $license_data = json_decode( wp_remote_retrieve_body( $response ) );
275
276 // if this license is still valid.
277 if ( 'valid' === $license_data->license ) {
278 update_option( $options_slug . '-license-expires', $license_data->expires, false );
279 update_option( $options_slug . '-license-status', $license_data->license, false );
280
281 return true;
282 }
283
284 return false;
285 }
286
287 /**
288 * Deactivate license key
289 *
290 * @param string $addon string with add-on identifier.
291 * @param string $plugin_name name of the add-on.
292 * @param string $options_slug slug of the option in the database.
293 *
294 * @return string
295 * @since 1.6.11
296 */
297 public function deactivate_license( $addon = '', $plugin_name = '', $options_slug = '' ) {
298 if ( '' === $addon || '' === $plugin_name || '' === $options_slug ) {
299 return __( 'Error while trying to disable the license. Please contact support.', 'advanced-ads' );
300 }
301
302 $licenses = $this->get_licenses();
303 $license_key = isset( $licenses[ $addon ] ) ? $licenses[ $addon ] : '';
304 $short_circuit = $this->shortcuit_deactivation( $addon, $options_slug );
305
306 if ( false !== $short_circuit ) {
307 return true;
308 }
309
310 if ( has_filter( 'advanced_ads_license_' . $options_slug ) ) {
311 return apply_filters( 'advanced_ads_license_' . $options_slug, false, __METHOD__, $plugin_name, $options_slug, $license_key );
312 }
313
314 $api_params = [
315 'edd_action' => 'deactivate_license',
316 'license' => $license_key,
317 'item_id' => self::ADDON_SLUGS_ID[ $options_slug ] ?? false,
318 'item_name' => rawurlencode( $plugin_name ),
319 ];
320
321 // Send the remote request.
322 $response = wp_remote_post(
323 self::API_ENDPOINT,
324 [
325 'body' => $api_params,
326 'timeout' => 15,
327 'sslverify' => false,
328 ]
329 );
330
331 // show license debug output if constant is set.
332 if ( defined( 'ADVANCED_ADS_SHOW_LICENSE_RESPONSE' ) ) {
333 return '<p><strong>' . esc_html__( 'The license status does not change as long as ADVANCED_ADS_SHOW_LICENSE_RESPONSE is enabled in wp-config.php.', 'advanced-ads' ) . '</strong></p>' .
334 '<pre>' . print_r( $response, true ) . '</pre>'; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
335 }
336
337 if ( is_wp_error( $response ) ) {
338 $body = wp_remote_retrieve_body( $response );
339 if ( $body ) {
340 return $body;
341 } else {
342 return __( 'License couldn’t be deactivated. Please try again later.', 'advanced-ads' );
343 }
344 }
345
346 $license_data = json_decode( wp_remote_retrieve_body( $response ) );
347
348 /**
349 * Send the user to our support when his request is blocked by our firewall
350 */
351 $error = $this->blocked_by_firewall( $response );
352 if ( $error ) {
353 return $error;
354 }
355
356 // remove data.
357 if ( 'deactivated' === $license_data->license ) {
358 delete_option( $options_slug . '-license-status' );
359 delete_option( $options_slug . '-license-expires' );
360 } elseif ( 'failed' === $license_data->license ) {
361 update_option( $options_slug . '-license-expires', $license_data->expires, false );
362 update_option( $options_slug . '-license-status', $license_data->license, false );
363
364 return 'ex';
365 } else {
366 return __( 'License couldn’t be deactivated. Please try again later.', 'advanced-ads' );
367 }
368
369 return 1;
370 }
371
372 /**
373 * Get license keys for all add-ons
374 *
375 * @return string[]
376 */
377 public function get_licenses() {
378 $licenses = get_option( ADVADS_SLUG . '-licenses', [] );
379 if ( empty( $licenses ) || ! is_array( $licenses ) ) {
380 $licenses = [];
381 }
382
383 return $licenses;
384 }
385
386 /**
387 * Save license keys for all add-ons
388 *
389 * @param array $licenses licenses.
390 */
391 public function save_licenses( $licenses = [] ) {
392 update_option( ADVADS_SLUG . '-licenses', $licenses );
393 }
394
395 /**
396 * Get license status of an add-on
397 *
398 * @param string $slug slug of the add-on.
399 *
400 * @return string|false license status, "valid", "invalid" or false if option doesn't exist.
401 */
402 public function get_license_status( $slug = '' ) {
403 return get_option( $slug . '-license-status', false );
404 }
405
406 /**
407 * If two or more add-ons use the same valid license this is probably an all-access customer
408 *
409 * @return bool
410 */
411 public function get_probably_all_access() {
412 $valid = array_filter(
413 $this->get_licenses(),
414 function ( $key ) {
415 return $this->get_license_status( ADVADS_SLUG . '-' . $key );
416 },
417 ARRAY_FILTER_USE_KEY
418 );
419
420 return [] !== $valid && max( array_count_values( $valid ) ) > 1;
421 }
422
423 /**
424 * Return the licence expiry time if it is equal for more than one add-on. That indicates it is likely an All Access license
425 *
426 * @return string|null
427 */
428 public function get_probably_all_access_expiry() {
429 /**
430 * Get expiry dates of all add-ons.
431 *
432 * @param string $key Add-on key.
433 *
434 * @return string|false the expiration date or false.
435 */
436 $expiry_counts = array_count_values(
437 array_map(
438 function ( $key ) {
439 return $this->get_license_expires( ADVADS_SLUG . '-' . $key );
440 },
441 array_keys( array_filter( $this->get_licenses() ) )
442 )
443 );
444
445 /**
446 * Remove all licenses that are used only once.
447 *
448 * @param int $count the count from array_count_values_above
449 *
450 * @return bool whether the count is greater 1
451 */
452 $all_access = array_filter(
453 $expiry_counts,
454 function ( $count ) {
455 return $count > 1;
456 }
457 );
458
459 // if there is an item in $all_access we can assume this is from All Access and return the expiry date.
460 return empty( $all_access ) ? null : key( $all_access );
461 }
462
463 /**
464 * Get license expired value of an add-on
465 *
466 * @param string $slug slug of the add-on.
467 *
468 * @return string $date expiry date of an add-on, empty string if no option exists
469 */
470 public function get_license_expires( $slug = '' ) {
471 return get_option( $slug . '-license-expires', '' );
472 }
473
474 /**
475 * Add custom messages to plugin updater
476 *
477 * @param bool $reply Whether to bail without returning the package. Default false.
478 * @param string $package The package file name.
479 * @param WP_Upgrader $updater The WP_Upgrader instance.
480 *
481 * @return string
482 *
483 * @todo check if this is still working.
484 */
485 public function addon_upgrade_filter( $reply, $package, $updater ) {
486 if ( isset( $updater->skin->plugin ) ) {
487 $plugin_file = $updater->skin->plugin;
488 } elseif ( isset( $updater->skin->plugin_info['Name'] ) ) {
489 $add_on = $this->get_installed_add_on_by_name( $updater->skin->plugin_info['Name'] );
490 // $add_on['path'] should always be set with out official plugins but might be missing for some local and custom made.
491 if ( isset( $add_on['path'] ) ) {
492 $plugin_file = plugin_basename( $add_on['path'] );
493 }
494 }
495
496 if ( isset( $plugin_file ) && $plugin_file ) {
497 // if AJAX; show direct update link as first possible solution.
498 if ( wp_doing_ajax() ) {
499 $update_link = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $plugin_file, 'upgrade-plugin_' . $plugin_file );
500 /* translators: %s plugin update link */
501 $updater->strings['download_failed'] = sprintf( __( 'Download failed. <a href="%s">Click here to try another method</a>.', 'advanced-ads' ), $update_link );
502 } else {
503 /* translators: %s download failed knowledgebase link */
504 $updater->strings['download_failed'] = sprintf( __( 'Download failed. <a href="%s" target="_blank">Click here to learn why</a>.', 'advanced-ads' ), 'https://wpadvancedads.com/manual/download-failed-updating-add-ons/#utm_source=advanced-ads&utm_medium=link&utm_campaign=download-failed' );
505 }
506 }
507
508 return $reply;
509 }
510
511 /**
512 * Search if a name is in the add-on array and return the add-on data of it
513 *
514 * @param string $name name of an add-on.
515 *
516 * @return array array with the add-on data
517 */
518 private function get_installed_add_on_by_name( $name = '' ) {
519 $add_ons = Data::get_addons();
520
521 if ( is_array( $add_ons ) ) {
522 foreach ( $add_ons as $key => $_add_on ) {
523 if ( $_add_on['name'] === $name ) {
524 return $_add_on;
525 }
526 }
527 }
528
529 return null;
530 }
531
532 /**
533 * Check if any license is valid
534 * can be used to display information for any Pro user only, like link to direct support
535 */
536 public static function any_license_valid() {
537 $add_ons = Data::get_addons();
538 if ( [] === $add_ons ) {
539 return false;
540 }
541
542 foreach ( $add_ons as $_add_on ) {
543 $status = self::get_instance()->get_license_status( $_add_on['options_slug'] );
544
545 // check expiry date.
546 $expiry_date = self::get_instance()->get_license_expires( $_add_on['options_slug'] );
547
548 if (
549 ( $expiry_date && strtotime( $expiry_date ) > time() )
550 || 'valid' === $status || 'lifetime' === $expiry_date
551 ) {
552 return true;
553 }
554 }
555
556 return false;
557 }
558
559 /**
560 * Update the license status based on information retrieved from the version info check
561 *
562 * @param array|WP_Error $response HTTP response or WP_Error object.
563 * @param string $context Context under which the hook is fired.
564 * @param string $http HTTP transport used.
565 * @param array $parsed_args HTTP request arguments.
566 * @param string $url The request URL.
567 * @return array|WP_Error
568 */
569 public function update_license_after_version_info( $response, $context, $http, $parsed_args, $url ) {
570 // Early bail!!
571 if (
572 self::API_ENDPOINT !== $url
573 || (
574 empty( $parsed_args['body']['edd_action'] )
575 || 'get_version' !== $parsed_args['body']['edd_action']
576 )
577 || is_wp_error( $response )
578 ) {
579 return $response;
580 }
581
582 $params = json_decode( wp_remote_retrieve_body( $response ) );
583 if ( empty( $params->name ) ) {
584 return $response;
585 }
586
587 $new_license_status = null;
588 $new_expiry_date = null;
589
590 // Some of the conditions could happen at the same time,
591 // though due to different conditions in EDD we are safer to have multiple checks.
592 if ( isset( $params->valid_until ) ) {
593 if ( 'invalid' === $params->valid_until ) {
594 $new_license_status = 'invalid';
595 }
596 if ( 'lifetime' === $params->valid_until ) {
597 $new_license_status = 'valid';
598 $new_expiry_date = 'lifetime';
599 }
600
601 if ( is_int( $params->valid_until ) ) {
602 $new_expiry_date = (int) $params->valid_until;
603 if ( time() < $params->valid_until ) {
604 $new_license_status = 'valid';
605 }
606 }
607 } elseif ( empty( $params->download_link ) || empty( $params->package ) || isset( $params->msg ) ) {
608 // If either of these two parameters is missing then the user does not have a valid license according to our store
609 // If there is a "msg" parameter then the license did also not work for another reason.
610 $new_license_status = 'invalid';
611 }
612
613 if ( ! $new_license_status && ! $new_expiry_date ) {
614 return $response;
615 }
616
617 $add_ons = Data::get_addons();
618
619 // Look for the add-on with the appropriate license key.
620 foreach ( $add_ons as $_add_on ) {
621 if ( ! isset( $_add_on['name'] ) || $params->name !== $_add_on['name'] ) {
622 continue;
623 }
624
625 $options_slug = $_add_on['options_slug'];
626
627 if ( $new_license_status ) {
628 update_option( $options_slug . '-license-status', $new_license_status, false );
629 }
630
631 if ( $new_expiry_date ) {
632 if ( 'lifetime' !== $new_expiry_date ) {
633 $new_expiry_date = gmdate( 'Y-m-d 23:59:49', $new_expiry_date );
634 }
635 update_option( $options_slug . '-license-expires', $new_expiry_date, false );
636 }
637
638 // Return with the first match since there should only be one plugin per name.
639 return $response;
640 }
641
642 return $response;
643 }
644
645 /**
646 * Shortcuit deactivation
647 *
648 * @param string $addon string with add-on identifier.
649 * @param string $options_slug slug of the option in the database.
650 *
651 * @return false
652 */
653 private function shortcuit_deactivation( $addon, $options_slug ) {
654 $licenses = $this->get_filtered_licenses();
655 $license_key = isset( $licenses[ $addon ] ) ? $licenses[ $addon ] : '';
656 $counts = array_count_values( $licenses );
657
658 if ( $counts[ $license_key ] > 1 ) {
659 delete_option( $options_slug . '-license-status' );
660 delete_option( $options_slug . '-license-expires' );
661 return __( 'License deactivated. Please try again later.', 'advanced-ads' );
662 }
663
664 return false;
665 }
666
667 /**
668 * If two or more add-ons use the same valid license this is probably an all-access customer
669 *
670 * @return array
671 */
672 private function get_filtered_licenses() {
673 $filtered = array_filter(
674 $this->get_licenses(),
675 function ( $key ) {
676 return $this->get_license_status( ADVADS_SLUG . '-' . $key );
677 },
678 ARRAY_FILTER_USE_KEY
679 );
680
681 return ! is_array( $filtered ) ? [] : $filtered;
682 }
683
684 /**
685 * Clear the license cache
686 *
687 * @param string $slug slug of the add-on.
688 * @param string $license_key license key.
689 */
690 private function clear_license_cache() {
691 global $wpdb;
692
693 $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'advads_edd_sl_%'" );
694 }
695 }
696