PluginProbe ʕ •ᴥ•ʔ
Cookiebot by Usercentrics – Automatic Cookie Banner for GDPR/CCPA & Google Consent Mode / 4.6.2
Cookiebot by Usercentrics – Automatic Cookie Banner for GDPR/CCPA & Google Consent Mode v4.6.2
4.7.2 4.7.1 trunk 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 3.0.0 3.0.1 3.1.0 3.10.0 3.10.1 3.11.1 3.11.2 3.11.3 3.2.0 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.5 3.6.6 3.7.0 3.7.1 3.8.0 3.9.0 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.2.0 4.2.1 4.2.10 4.2.11 4.2.12 4.2.13 4.2.14 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.3.10 4.3.11 4.3.12 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.7.1 4.3.8 4.3.9 4.3.9.1 4.4.0 4.4.1 4.4.2 4.5.0 4.5.1 4.5.10 4.5.11 4.5.2 4.5.3 4.5.4 4.5.5 4.5.6 4.5.7 4.5.8 4.5.9 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.6.6 4.6.7 4.7.0
cookiebot / src / lib / Cookiebot_WP.php
cookiebot / src / lib Last commit date
buffer 1 year ago script_loader_tag 1 year ago traits 1 year ago Account_Service.php 10 months ago Consent_API_Helper.php 1 year ago Cookie_Consent.php 1 year ago Cookie_Consent_Interface.php 1 year ago Cookiebot_Activated.php 10 months ago Cookiebot_Admin_Links.php 1 year ago Cookiebot_Automatic_Updates.php 1 year ago Cookiebot_Deactivated.php 1 year ago Cookiebot_Frame.php 1 year ago Cookiebot_Javascript_Helper.php 7 months ago Cookiebot_Review.php 6 months ago Cookiebot_WP.php 6 months ago Dependency_Container.php 1 year ago Settings_Page_Tab.php 1 year ago Settings_Service.php 1 year ago Settings_Service_Interface.php 1 year ago Supported_Languages.php 1 year ago Supported_Regions.php 1 year ago WP_Rocket_Helper.php 1 year ago Widgets.php 1 year ago global-deprecations.php 1 year ago helper.php 6 months ago
Cookiebot_WP.php
778 lines
1 <?php
2
3
4 namespace cybot\cookiebot\lib;
5
6 use cybot\cookiebot\addons\Cookiebot_Addons;
7 use cybot\cookiebot\admin_notices\Cookiebot_Notices;
8 use cybot\cookiebot\gutenberg\Cookiebot_Gutenberg_Declaration_Block;
9 use cybot\cookiebot\settings\Menu_Settings;
10 use cybot\cookiebot\settings\Network_Menu_Settings;
11 use cybot\cookiebot\shortcode\Cookiebot_Embedding_Shortcode;
12 use cybot\cookiebot\widgets\Dashboard_Widget_Cookiebot_Status;
13 use cybot\cookiebot\lib\Account_Service;
14 use DomainException;
15 use RuntimeException;
16
17 if ( ! defined( 'CYBOT_COOKIEBOT_VERSION' ) ) {
18 define( 'CYBOT_COOKIEBOT_VERSION', '1.0.0' );
19 }
20
21 class Cookiebot_WP {
22
23 public static function debug_log( $message ) {
24 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
25 // phpcs:ignore
26 error_log( '[Cookiebot] ' . $message );
27 }
28 }
29
30 const COOKIEBOT_PLUGIN_VERSION = '4.6.2';
31 const COOKIEBOT_MIN_PHP_VERSION = '5.6.0';
32
33 /**
34 * @var Cookiebot_WP The single instance of the class
35 * @since 1.0.0
36 */
37 private static $instance = null;
38
39 private $account_service;
40
41 /**
42 * Main Cookiebot_WP Instance
43 *
44 * Ensures only one instance of Cookiebot_WP is loaded or can be loaded.
45 *
46 * @return Cookiebot_WP - Main instance
47 * @throws RuntimeException
48 * @version 1.0.0
49 * @since 1.0.0
50 * @static
51 */
52 public static function instance() {
53 if ( is_null( self::$instance ) ) {
54 self::$instance = new self();
55 }
56
57 return self::$instance;
58 }
59
60 /**
61 * Cookiebot_WP Constructor.
62 *
63 * @throws RuntimeException
64 * @since 1.0.0
65 * @access public
66 * @version 2.1.4
67 */
68 public function __construct() {
69 $this->throw_exception_if_php_version_is_incompatible();
70 $this->cookiebot_init();
71 register_activation_hook( CYBOT_COOKIEBOT_PLUGIN_DIR . 'cookiebot.php', array( new Cookiebot_Activated(), 'run' ) );
72 register_deactivation_hook( CYBOT_COOKIEBOT_PLUGIN_DIR . 'cookiebot.php', array( new Cookiebot_Deactivated(), 'run' ) );
73
74 // Initialize services
75 $this->account_service = new Account_Service();
76 }
77
78 /**
79 * @throws RuntimeException
80 */
81 private function throw_exception_if_php_version_is_incompatible() {
82 if ( version_compare( PHP_VERSION, self::COOKIEBOT_MIN_PHP_VERSION, '<' ) ) {
83 $message = sprintf(
84 // translators: The placeholder is for the COOKIEBOT_MIN_PHP_VERSION constant
85 __( 'The Cookiebot plugin requires PHP version %s or greater.', 'cookiebot' ),
86 self::COOKIEBOT_MIN_PHP_VERSION
87 );
88 throw new DomainException( $message );
89 }
90 }
91
92 public function cookiebot_init() {
93 Cookiebot_Addons::instance();
94 add_action( 'init', array( $this, 'cookiebot_load_textdomain' ) );
95
96 if ( is_admin() ) {
97 ( new Menu_Settings() )->add_menu();
98 if ( is_multisite() && is_plugin_active_for_network( 'cookiebot/cookiebot.php' ) ) {
99 ( new Network_Menu_Settings() )->add_menu();
100 }
101 ( new Dashboard_Widget_Cookiebot_Status() )->register_hooks();
102 ( new Cookiebot_Notices() )->register_hooks();
103 ( new Cookiebot_Review() )->register_hooks();
104 }
105
106 ( new Consent_API_Helper() )->register_hooks();
107 ( new Cookiebot_Javascript_Helper() )->register_hooks();
108 ( new Cookiebot_Embedding_Shortcode() )->register_hooks();
109 ( new Cookiebot_Automatic_Updates() )->register_hooks();
110 ( new Widgets() )->register_hooks();
111 ( new Cookiebot_Gutenberg_Declaration_Block() )->register_hooks();
112 ( new WP_Rocket_Helper() )->register_hooks();
113
114 $this->set_default_options();
115 ( new Cookiebot_Admin_Links() )->register_hooks();
116 }
117
118 /**
119 * Returns true if an user is logged in and has an edit_themes capability
120 *
121 * @return bool
122 *
123 * @since 3.3.1
124 * @version 3.4.1
125 */
126 public static function can_current_user_edit_theme() {
127 if ( is_user_logged_in() &&
128 (
129 current_user_can( 'edit_themes' ) ||
130 current_user_can( 'edit_pages' ) ||
131 current_user_can( 'edit_posts' )
132 )
133 ) {
134 return true;
135 }
136
137 return false;
138 }
139
140 /**
141 * Loads translations textdomain
142 *
143 * @return void
144 */
145 public function cookiebot_load_textdomain() {
146 load_textdomain(
147 'cookiebot',
148 CYBOT_COOKIEBOT_PLUGIN_DIR . 'langs/cookiebot-' . get_locale() . '.mo'
149 );
150 load_plugin_textdomain( 'cookiebot', false, dirname( plugin_basename( __FILE__ ) ) . '/langs' );
151 }
152
153 /**
154 * @return string
155 */
156 public static function get_cbid() {
157 $network_setting = (string) get_site_option( 'cookiebot-cbid', '' );
158 $setting = (string) get_option( 'cookiebot-cbid', $network_setting );
159
160 return empty( $setting ) ? $network_setting : $setting;
161 }
162
163 public static function get_auth_token() {
164 $token = (string) get_option( 'cookiebot-auth-token' );
165 return $token;
166 }
167
168 public static function get_user_data() {
169 $user_data = get_option( 'cookiebot-user-data', '' );
170 return empty( $user_data ) ? '' : $user_data;
171 }
172
173 /**
174 * Check if the user was onboarded via signup
175 *
176 * @return bool
177 */
178 public static function was_onboarded_via_signup() {
179 return (bool) get_option( 'cookiebot-uc-onboarded-via-signup', false );
180 }
181
182 public static function get_scan_status() {
183 $scan_status = get_option( 'cookiebot-scan-status', '' );
184 return empty( $scan_status ) ? '' : $scan_status;
185 }
186
187 /**
188 * @return string
189 */
190 public static function get_network_cbid() {
191 return get_site_option( 'cookiebot-cbid', '' );
192 }
193
194 /**
195 * @return string
196 */
197 public static function get_banner_enabled() {
198 $enabled = get_option( 'cookiebot-banner-enabled', 'default' );
199 if ( $enabled === 'default' ) {
200 $enabled = '1';
201 update_option( 'cookiebot-banner-enabled', $enabled );
202 }
203 return $enabled;
204 }
205
206 public static function get_auto_blocking_mode() {
207 $enabled = get_option( 'cookiebot-uc-auto-blocking-mode', 'default' );
208 if ( $enabled === 'default' ) {
209 $enabled = '1';
210 update_option( 'cookiebot-uc-auto-blocking-mode', $enabled );
211 }
212 return $enabled;
213 }
214
215 /**
216 * @return string
217 */
218 public static function get_gcm_enabled() {
219 $enabled = get_option( 'cookiebot-gcm', 'default' );
220 if ( $enabled === 'default' ) {
221 $enabled = '1';
222 update_option( 'cookiebot-gcm', $enabled );
223 }
224 return $enabled;
225 }
226
227 /**
228 * @return string
229 */
230 public static function get_preview_link() {
231 $url = get_site_option( 'siteurl', '#' );
232 return $url;
233 }
234
235 /**
236 * @return string
237 */
238 public static function get_subscription_type() {
239 $raw_data = get_option( 'cookiebot-user-data', '' );
240
241 if ( empty( $raw_data ) ) {
242 self::debug_log( 'Raw data is empty' );
243 return '';
244 }
245
246 // Use the data directly if it's already an array
247 $data = is_array( $raw_data ) ? $raw_data : json_decode( $raw_data, true );
248
249 // Check if we have the new subscription structure
250 if ( ! isset( $data['subscriptions']['active'] ) ) {
251 self::debug_log( 'No active subscription found' );
252 return '';
253 }
254
255 $subscription = $data['subscriptions']['active'];
256 $status = isset( $subscription['subscription_status'] ) ? $subscription['subscription_status'] : '';
257 $price_plan = isset( $subscription['price_plan'] ) ? $subscription['price_plan'] : 'free';
258
259 self::debug_log( 'Subscription details:' );
260 self::debug_log( 'Status: ' . $status );
261 self::debug_log( 'Price Plan: ' . $price_plan );
262
263 // Check for trial status first
264 if ( in_array( $status, array( 'trial_will_be_billed', 'trial_missing_payment' ), true ) ) {
265 self::debug_log( 'Trial status detected, returning Premium trial' );
266 return 'Premium Trial';
267 }
268
269 // If not in trial, check active subscriptions
270 if ( in_array( $status, array( 'active_auto_renew', 'active_no_renew' ), true ) ) {
271 // Map extended plan names to their base names
272 $plan_mapping = array(
273 'FreeExtended' => 'Free',
274 'EssentialExtended' => 'Essential',
275 'PlusExtended' => 'Plus',
276 'ProExtended' => 'Pro',
277 'BusinessExtended' => 'Business',
278 );
279
280 $result = isset( $plan_mapping[ $price_plan ] ) ? $plan_mapping[ $price_plan ] : ucfirst( $price_plan );
281 self::debug_log( 'Active subscription, returning: ' . $result );
282 return $result;
283 }
284
285 self::debug_log( 'No conditions met, returning Free' );
286 return '';
287 }
288
289 /**
290 * @return string
291 */
292 public static function get_legal_framwework() {
293 $configuration = get_option( 'cookiebot-configuration', array() );
294 return isset( $configuration['legal_framework_template'] ) ? strtoupper( $configuration['legal_framework_template'] ) : 'GDPR';
295 }
296
297 /**
298 * @return string
299 */
300 public static function get_cookie_blocking_mode() {
301 $allowed_modes = array( 'auto', 'manual' );
302 $network_setting = (string) get_site_option( 'cookiebot-cookie-blocking-mode', 'manual' );
303 $setting = $network_setting === 'manual' ?
304 (string) get_option( 'cookiebot-cookie-blocking-mode', $network_setting ) :
305 $network_setting;
306
307 return in_array( $setting, $allowed_modes, true ) ? $setting : 'auto';
308 }
309
310 /**
311 * @return bool
312 */
313 public static function check_network_auto_blocking_mode() {
314 $network_setting = (string) get_site_option( 'cookiebot-cookie-blocking-mode' );
315
316 return $network_setting === 'auto' ? true : false;
317 }
318
319 /**
320 * @return string
321 */
322 public static function get_cookie_categories_status() {
323 return self::get_cookie_blocking_mode() === 'auto' ? 'disabled' : '';
324 }
325
326 /**
327 * @return bool
328 */
329 public static function is_cookie_category_selected( $option, $category ) {
330 $categories = get_option( $option );
331 if ( ! $categories || ! is_array( $categories ) ) {
332 return false;
333 }
334
335 return in_array( $category, $categories, true );
336 }
337
338 /**
339 * Cookiebot_WP Check if Cookiebot is active in admin
340 *
341 * @version 4.2.8
342 * @since 3.1.0
343 */
344 public static function cookiebot_disabled_in_admin() {
345 if ( ( is_network_admin() && get_site_option( 'cookiebot-nooutput-admin', false ) ) ||
346 ( ! is_network_admin() && get_site_option( 'cookiebot-nooutput-admin', false ) ) ||
347 ( ! is_network_admin() && get_option( 'cookiebot-nooutput-admin', false ) ) ) {
348 return true;
349 }
350
351 return false;
352 }
353
354 /**
355 * Cookiebot_WP Set default options
356 *
357 * @version 4.2.5
358 * @since 4.2.5
359 */
360 private function set_default_options() {
361 $options = array(
362 'cookiebot-nooutput-admin' => '1',
363 'cookiebot-gcm' => '1',
364 'cookiebot-banner-enabled' => '1',
365 'cookiebot-cookie-blocking-mode' => 'auto',
366 );
367
368 foreach ( $options as $option => $default ) {
369 if ( get_option( $option ) === false && ! get_option( $option . self::OPTION_FIRST_RUN_SUFFIX ) ) {
370 update_option( $option, $default );
371 }
372
373 if ( ( get_option( $option ) || get_option( $option ) !== false ) && ! get_option( $option . self::OPTION_FIRST_RUN_SUFFIX ) ) {
374 update_option( $option . self::OPTION_FIRST_RUN_SUFFIX, '1' );
375 }
376 }
377
378 // Safeguard to always garantee the blocking mode has a value.
379 // There is one situation in which this value is cleared after disconnecting an onboarded user account
380 if ( empty( get_option( 'cookiebot-cookie-blocking-mode' ) ) ) {
381 update_option( 'cookiebot-cookie-blocking-mode', 'auto' );
382 }
383
384 self::set_tcf_version();
385 }
386
387 private static function set_tcf_version() {
388 $iab_version = get_option( 'cookiebot-tcf-version' );
389 if ( empty( $iab_version ) || $iab_version === 'IAB' ) {
390 update_option( 'cookiebot-tcf-version', 'TCFv2.2' );
391 }
392 }
393
394 public function set_settings_action_link( $actions ) {
395 $cblinks = array(
396 '<a href="' . esc_url( add_query_arg( 'page', 'cookiebot', admin_url( 'admin.php' ) ) ) . '">' . esc_html__( 'Dashboard', 'cookiebot' ) . '</a>',
397 );
398 $actions = array_merge( $actions, $cblinks );
399 return $actions;
400 }
401
402 /**
403 * @return string
404 */
405 public static function get_manager_language() {
406 $locale = get_locale();
407 $supported_langs = array(
408 'de_DE' => 'de',
409 'da_DK' => 'da',
410 'fr_FR' => 'fr',
411 'it_IT' => 'it',
412 'es_ES' => 'es',
413 );
414
415 return array_key_exists( $locale, $supported_langs ) ? $supported_langs[ $locale ] : esc_html( 'en' );
416 }
417
418 const OPTION_FIRST_RUN_SUFFIX = '-first-run';
419
420 public function get_usercentrics_script() {
421 $final_script = '';
422
423 // Enqueue Usercentrics scripts
424 wp_enqueue_script(
425 'usercentrics-tcf-stub',
426 'https://web.cmp.usercentrics.eu/tcf/stub.js',
427 array(),
428 CYBOT_COOKIEBOT_VERSION,
429 true
430 );
431
432 wp_enqueue_script(
433 'usercentrics-autoblocker',
434 'https://web.cmp.usercentrics.eu/modules/autoblocker.js',
435 array(),
436 CYBOT_COOKIEBOT_VERSION,
437 true
438 );
439
440 wp_enqueue_script(
441 'usercentrics-cmp',
442 'https://web.cmp.usercentrics.eu/ui/loader.js',
443 array(),
444 CYBOT_COOKIEBOT_VERSION,
445 true
446 );
447
448 // Add data attributes to the CMP script
449 wp_script_add_data(
450 'usercentrics-cmp',
451 'data-usercentrics',
452 'Usercentrics Consent Management Platform'
453 );
454 wp_script_add_data(
455 'usercentrics-cmp',
456 'data-settings-id',
457 '%s'
458 );
459 wp_script_add_data(
460 'usercentrics-cmp',
461 'async',
462 true
463 );
464
465 return $final_script;
466 }
467
468 public function enqueue_scripts() {
469 wp_enqueue_script(
470 'cookiebot',
471 'https://consent.cookiebot.com/uc.js',
472 array(),
473 CYBOT_COOKIEBOT_VERSION,
474 true
475 );
476
477 wp_enqueue_script(
478 'cookiebot-helper',
479 plugins_url( 'js/cookiebot-helper.js', dirname( __FILE__ ) ),
480 array( 'jquery' ),
481 CYBOT_COOKIEBOT_VERSION,
482 true
483 );
484
485 wp_enqueue_script(
486 'cookiebot-admin',
487 plugins_url( 'js/cookiebot-admin.js', dirname( __FILE__ ) ),
488 array( 'jquery' ),
489 CYBOT_COOKIEBOT_VERSION,
490 true
491 );
492 }
493
494 /**
495 * Clone object and return it
496 *
497 * @return object
498 *
499 * @since 1.0.0
500 */
501 public function get_cloned_object() {
502 $temp = clone $this;
503 return $temp;
504 }
505
506 /**
507 * Get the banner script HTML
508 *
509 * @return string
510 *
511 * @phpcs:disable WordPress.WP.EnqueuedResources.NonEnqueuedScript
512 */
513 public static function get_banner_script() {
514 $cbid = self::get_cbid();
515 self::debug_log( '=== get_banner_script: Starting ===' );
516 self::debug_log( 'CBID: ' . $cbid );
517
518 // Basic validation checks
519 if ( empty( $cbid ) || defined( 'COOKIEBOT_DISABLE_ON_PAGE' ) ) {
520 self::debug_log( 'get_banner_script: Basic validation failed - CBID empty or disabled' );
521 return '';
522 }
523
524 // Banner enabled check
525 $banner_enabled = get_option( 'cookiebot-banner-enabled', '1' );
526 self::debug_log( 'Banner enabled setting: ' . $banner_enabled );
527 if ( $banner_enabled !== '1' ) {
528 self::debug_log( 'get_banner_script: Banner disabled in settings' );
529 return '';
530 }
531
532 // User verification and trial checks
533 $user_data = self::get_user_data();
534
535 if ( ! empty( $user_data ) && self::is_trial_expired() ) {
536 self::debug_log( 'get_banner_script: Trial expired' );
537 return '';
538 }
539
540 // Output conditions check
541 self::debug_log( 'get_banner_script: Generating dynamic script' );
542
543 // Build the script HTML
544 $script_html = '';
545
546 // Add TCF stub if IAB is enabled
547 $iab_enabled = ! empty( get_option( 'cookiebot-iab' ) );
548 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
549 self::debug_log( 'IAB enabled: ' . ( $iab_enabled ? 'yes' : 'no' ) );
550 if ( $iab_enabled ) {
551 // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
552 $script_html .= sprintf(
553 '<script src="%s"></script>',
554 esc_url( 'https://web.cmp.usercentrics.eu/tcf/stub.js' )
555 );
556 }
557
558 // Add autoblocker if auto mode is enabled
559 $blocking_mode = get_option( 'cookiebot-uc-auto-blocking-mode', '1' );
560 $blocking_mode_cookiebot = get_option( 'cookiebot-cookie-blocking-mode', 'auto' );
561
562 if ( $blocking_mode === '0' || $blocking_mode_cookiebot === 'manual' ) {
563 $blocking_mode = '0';
564 }
565
566 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
567 self::debug_log( 'Blocking mode: ' . $blocking_mode );
568 if ( $blocking_mode === '1' ) {
569 // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
570 $script_html .= sprintf(
571 '<script src="%s"></script>',
572 esc_url( 'https://web.cmp.usercentrics.eu/modules/autoblocker.js' )
573 );
574 }
575
576 $data_label = ! empty( get_option( 'cookiebot-ruleset-id' ) ) ? get_option( 'cookiebot-ruleset-id' ) : 'settings';
577 // Add main banner script
578 // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
579 $script_html .= sprintf(
580 '<script id="usercentrics-cmp" data-%s-id="%s" data-usercentrics="%s" src="%s" async></script>',
581 esc_attr( $data_label ),
582 esc_attr( $cbid ),
583 esc_attr( 'Usercentrics Consent Management Platform' ),
584 esc_url( 'https://web.cmp.usercentrics.eu/ui/loader.js' )
585 );
586
587 self::debug_log( 'Final script HTML: ' . $script_html );
588 return $script_html;
589 }
590
591 /**
592 * Check if the trial has expired by checking various conditions
593 *
594 * @return bool True if trial has expired, false otherwise
595 */
596 public static function is_trial_expired() {
597 $user_data = self::get_user_data();
598
599 if ( empty( $user_data ) ) {
600 self::debug_log( 'is_trial_expired: No user data found' );
601 return false;
602 }
603
604 // Check if there's an active subscription
605 if ( isset( $user_data['subscriptions']['active'] ) ) {
606 $active_subscription = $user_data['subscriptions']['active'];
607
608 // Check subscription status
609 if ( isset( $active_subscription['subscription_status'] ) ) {
610 $status = $active_subscription['subscription_status'];
611 self::debug_log( 'is_trial_expired: Subscription status: ' . $status );
612
613 // For trial statuses, check the trial period
614 if ( in_array( $status, array( 'trial_will_be_billed', 'trial_missing_payment' ), true ) ) {
615 if ( isset( $active_subscription['trial_end_date'] ) && ! empty( $active_subscription['trial_end_date'] ) ) {
616 $trial_end = \DateTime::createFromFormat( 'Y-m-d\TH:i:s.000\Z', $active_subscription['trial_end_date'] );
617
618 if ( $trial_end === false ) {
619 self::debug_log( 'is_trial_expired: Failed to parse trial end date' );
620 return false;
621 }
622
623 $now = new \DateTime();
624 $interval = $now->diff( $trial_end );
625
626 // If the interval is negative (past the end date) or zero, the trial has expired
627 $is_expired = $interval->invert || $interval->days === 0;
628 self::debug_log( 'is_trial_expired: Is expired? ' . ( $is_expired ? 'yes' : 'no' ) );
629 return $is_expired;
630 }
631 }
632
633 // For active subscriptions, check if it's a trial plan
634 if ( in_array( $status, array( 'active_auto_renew', 'active_no_renew' ), true ) ) {
635 // Not a trial subscription
636 self::debug_log( 'is_trial_expired: Active subscription - not a trial' );
637 return false;
638 }
639
640 // Cancelled subscriptions are considered expired
641 if ( $status === 'cancelled' ) {
642 self::debug_log( 'is_trial_expired: Cancelled subscription - expired' );
643 return true;
644 }
645 }
646 }
647
648 // If we get here and subscription type is Free, consider trial as expired
649 $subscription_type = self::get_subscription_type();
650 if ( $subscription_type === 'Free' ) {
651 self::debug_log( 'is_trial_expired: Free subscription - considered expired' );
652 return true;
653 }
654
655 self::debug_log( 'is_trial_expired: Default case - not expired' );
656 return false;
657 }
658
659 /**
660 * Check if the user has upgraded from the free plan
661 *
662 * @return bool
663 */
664 public static function has_upgraded() {
665 $user_data = get_option( 'cookiebot-user-data' );
666
667 if ( ! isset( $user_data['subscriptions']['active'] ) ) {
668 return false;
669 }
670
671 $active_subscription = $user_data['subscriptions']['active'];
672 $status = isset( $active_subscription['subscription_status'] ) ? $active_subscription['subscription_status'] : '';
673 $price_plan = isset( $active_subscription['price_plan'] ) ? $active_subscription['price_plan'] : '';
674
675 if ( empty( $price_plan ) ) {
676 return false;
677 }
678
679 // Check if the subscription is active (not trial or cancelled)
680 if ( in_array( $status, array( 'active_auto_renew', 'active_no_renew' ), true ) ) {
681 // Map extended plan names to their base names
682 $plan_mapping = array(
683 'FreeExtended' => 'Free',
684 'EssentialExtended' => 'Essential',
685 'PlusExtended' => 'Plus',
686 'ProExtended' => 'Pro',
687 'BusinessExtended' => 'Business',
688 );
689
690 $base_plan = isset( $plan_mapping[ $price_plan ] ) ? $plan_mapping[ $price_plan ] : $price_plan;
691 return true;
692 }
693
694 return false;
695 }
696
697 /**
698 * Get the number of days left in the trial period
699 *
700 * @return int Number of days left in the trial, or 0 if trial has expired or no trial exists
701 */
702 public static function get_trial_days_left() {
703 $user_data = self::get_user_data();
704
705 if ( empty( $user_data ) ) {
706 self::debug_log( 'get_trial_days_left: No user data found' );
707 return 0;
708 }
709
710 // Check if there's an active subscription
711 if ( isset( $user_data['subscriptions']['active'] ) ) {
712 $active_subscription = $user_data['subscriptions']['active'];
713
714 // Check subscription status
715 if ( isset( $active_subscription['subscription_status'] ) ) {
716 $status = $active_subscription['subscription_status'];
717 self::debug_log( 'get_trial_days_left: Subscription status: ' . $status );
718
719 // For trial statuses, calculate days left until trial_end_date
720 if ( in_array( $status, array( 'trial_will_be_billed', 'trial_missing_payment' ), true ) ) {
721 if ( isset( $active_subscription['trial_end_date'] ) && ! empty( $active_subscription['trial_end_date'] ) ) {
722 $trial_end = \DateTime::createFromFormat( 'Y-m-d\TH:i:s.000\Z', $active_subscription['trial_end_date'] );
723
724 if ( $trial_end === false ) {
725 self::debug_log( 'get_trial_days_left: Failed to parse trial end date' );
726 return 0;
727 }
728
729 $now = new \DateTime();
730 $interval = $now->diff( $trial_end );
731
732 // If the interval is negative (past the end date), return 0
733 if ( $interval->invert ) {
734 self::debug_log( 'get_trial_days_left: Trial has already ended' );
735 return 0;
736 }
737
738 // Add 1 to include the current day
739 $days_left = $interval->days + 1;
740 self::debug_log( 'get_trial_days_left: Days left: ' . $days_left );
741 return $days_left;
742 }
743 }
744
745 // For active subscriptions, no trial days left
746 if ( in_array( $status, array( 'active_auto_renew', 'active_no_renew' ), true ) ) {
747 self::debug_log( 'get_trial_days_left: Active subscription - no trial days' );
748 return 0;
749 }
750 }
751 }
752
753 return 0;
754 }
755
756 /**
757 * Check if the subscription is in trial status
758 *
759 * @return bool True if subscription is in trial status, false otherwise
760 */
761 public static function is_in_trial() {
762 $user_data = self::get_user_data();
763
764 if ( empty( $user_data ) || ! isset( $user_data['subscriptions']['active']['subscription_status'] ) ) {
765 self::debug_log( 'is_in_trial: No user data or subscription status found' );
766 return false;
767 }
768
769 $status = $user_data['subscriptions']['active']['subscription_status'];
770 $is_trial = in_array( $status, array( 'trial_will_be_billed', 'trial_missing_payment' ), true );
771
772 self::debug_log( 'is_in_trial: Subscription status: ' . $status );
773 self::debug_log( 'is_in_trial: Is trial? ' . ( $is_trial ? 'yes' : 'no' ) );
774
775 return $is_trial;
776 }
777 }
778