PluginProbe
Analytify – Google Analytics Dashboard For WordPress (GA4 analytics tracking) / trunk
Analytify – Google Analytics Dashboard For WordPress (GA4 analytics tracking) vtrunk
9.1.2 9.1.1 9.1.0 9.0.2 9.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.1.0 1.1.1 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 All 153 releases
wp-analytify / inc / analytify-authentication.php

analytify-authentication.php in Analytify – Google Analytics Dashboard For WordPress (GA4 analytics tracking) trunk, at inc/analytify-authentication.php

680 lines 22.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Authentication File for Analytify Plugin
4 *
5 * This file contains all authentication-related functionality including
6 * OAuth connection, token management, refresh tokens, and Google API
7 * authentication methods.
8 *
9 * @package WP_Analytify
10 * @since 8.0.0
11 */
12
13 // Prevent direct access.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 require_once __DIR__ . '/analytify-google-oauth-email-helpers.php';
19
20 /**
21 * Authentication Methods for Analytify_General Class
22 * since 8.0
23 */
24 trait Analytify_Authentication {
25
26 /**
27 * Update authentication date with current timestamp.
28 *
29 * @since 7.0.0
30 * @return void
31 */
32 private function analytify_update_authentication_date() {
33 $this->auth_date_format = gmdate( 'l jS F Y h:i:s A' ) . ' ' . date_default_timezone_get();
34 update_option( 'analytify_authentication_date', $this->auth_date_format );
35 }
36
37 /**
38 * Get Google token data from options.
39 *
40 * @since 7.0.0
41 * @return array|false Token data or false if not found
42 */
43 public function analytify_get_google_token() {
44 if ( empty( $this->google_token ) ) {
45 $this->google_token = get_option( 'pa_google_token' );
46 }
47 return $this->google_token;
48 }
49
50 /**
51 * Update Google token data in options and class variable.
52 *
53 * @since 7.0.0
54 * @param array $token_data Token data to save.
55 * @return void
56 */
57 private function analytify_update_google_token( $token_data ) {
58 $this->google_token = $token_data;
59 update_option( 'pa_google_token', $token_data );
60 }
61
62 /**
63 * Google OAuth email stored under wp-analytify-authentication (same option as manual GA code).
64 *
65 * @since 9.1.0
66 * @return string
67 */
68 protected function analytify_auth_settings_get_google_oauth_email() {
69 if ( ! defined( 'ANALYTIFY_AUTHENTICATION_OPTION_NAME' ) || ! defined( 'ANALYTIFY_GOOGLE_OAUTH_EMAIL_KEY' ) ) {
70 return '';
71 }
72 $opts = get_option( ANALYTIFY_AUTHENTICATION_OPTION_NAME, array() );
73 if ( ! is_array( $opts ) || empty( $opts[ ANALYTIFY_GOOGLE_OAUTH_EMAIL_KEY ] )
74 || ! is_string( $opts[ ANALYTIFY_GOOGLE_OAUTH_EMAIL_KEY ] ) ) {
75 return '';
76 }
77 $email = sanitize_email( $opts[ ANALYTIFY_GOOGLE_OAUTH_EMAIL_KEY ] );
78 return is_email( $email ) ? $email : '';
79 }
80
81 /**
82 * Persist Google OAuth email into wp-analytify-authentication.
83 *
84 * @since 9.1.0
85 * @param string $email Email address.
86 * @return void
87 */
88 protected function analytify_auth_settings_set_google_oauth_email( $email ) {
89 if ( ! defined( 'ANALYTIFY_AUTHENTICATION_OPTION_NAME' ) || ! defined( 'ANALYTIFY_GOOGLE_OAUTH_EMAIL_KEY' ) ) {
90 return;
91 }
92 if ( ! is_string( $email ) || '' === $email ) {
93 return;
94 }
95 $email = sanitize_email( $email );
96 if ( ! is_email( $email ) ) {
97 return;
98 }
99 $opts = get_option( ANALYTIFY_AUTHENTICATION_OPTION_NAME, array() );
100 if ( ! is_array( $opts ) ) {
101 $opts = array();
102 }
103 $opts[ ANALYTIFY_GOOGLE_OAUTH_EMAIL_KEY ] = $email;
104 update_option( ANALYTIFY_AUTHENTICATION_OPTION_NAME, $opts );
105 }
106
107 /**
108 * Remove stored Google OAuth email (e.g. on logout).
109 *
110 * @since 9.1.0
111 * @return void
112 */
113 protected function analytify_auth_settings_clear_google_oauth_email() {
114 if ( ! defined( 'ANALYTIFY_AUTHENTICATION_OPTION_NAME' ) || ! defined( 'ANALYTIFY_GOOGLE_OAUTH_EMAIL_KEY' ) ) {
115 return;
116 }
117 $opts = get_option( ANALYTIFY_AUTHENTICATION_OPTION_NAME, array() );
118 if ( ! is_array( $opts ) || ! array_key_exists( ANALYTIFY_GOOGLE_OAUTH_EMAIL_KEY, $opts ) ) {
119 return;
120 }
121 unset( $opts[ ANALYTIFY_GOOGLE_OAUTH_EMAIL_KEY ] );
122 update_option( ANALYTIFY_AUTHENTICATION_OPTION_NAME, $opts );
123 }
124
125 /**
126 * Resolve Google account email from id_token / userinfo and store in wp-analytify-authentication.
127 * Does not store email inside pa_google_token (OAuth blob stays API fields only).
128 *
129 * @since 9.1.0
130 * @param array<string, mixed> $token_data Token row (modified in place: legacy email key removed).
131 * @return void
132 */
133 private function analytify_capture_google_oauth_email( array &$token_data ) {
134 if ( $this->analytify_auth_settings_get_google_oauth_email() ) {
135 unset( $token_data['analytify_google_user_email'] );
136 return;
137 }
138
139 $email = '';
140 if ( ! empty( $token_data['id_token'] ) && is_string( $token_data['id_token'] ) ) {
141 $email = analytify_parse_google_email_from_id_token( $token_data['id_token'] );
142 }
143
144 if ( ! $email && ! empty( $token_data['access_token'] ) && is_string( $token_data['access_token'] ) ) {
145 $email = analytify_fetch_google_email_from_userinfo( $token_data['access_token'] );
146 }
147
148 if ( $email ) {
149 $this->analytify_auth_settings_set_google_oauth_email( $email );
150 delete_transient( 'analytify_google_userinfo_probe_skip' );
151 }
152
153 unset( $token_data['analytify_google_user_email'] );
154 }
155
156 /**
157 * Resolve email for display: auth settings, legacy token key migration, then JWT on token row.
158 *
159 * @since 9.1.0
160 * @param array<string, mixed> $token Token row (by ref; legacy keys stripped).
161 * @return string
162 */
163 private function analytify_resolve_google_oauth_email( array &$token ) {
164 $stored = $this->analytify_auth_settings_get_google_oauth_email();
165 if ( $stored ) {
166 if ( isset( $token['analytify_google_user_email'] ) ) {
167 unset( $token['analytify_google_user_email'] );
168 $this->google_token = $token;
169 update_option( 'pa_google_token', $token );
170 }
171 return $stored;
172 }
173
174 if ( ! empty( $token['analytify_google_user_email'] ) && is_string( $token['analytify_google_user_email'] ) ) {
175 $legacy_t = sanitize_email( $token['analytify_google_user_email'] );
176 if ( is_email( $legacy_t ) ) {
177 $this->analytify_auth_settings_set_google_oauth_email( $legacy_t );
178 unset( $token['analytify_google_user_email'] );
179 $this->google_token = $token;
180 update_option( 'pa_google_token', $token );
181 return $legacy_t;
182 }
183 }
184
185 if ( ! empty( $token['id_token'] ) && is_string( $token['id_token'] ) ) {
186 $from_jwt = analytify_parse_google_email_from_id_token( $token['id_token'] );
187 if ( $from_jwt ) {
188 $this->analytify_auth_settings_set_google_oauth_email( $from_jwt );
189 delete_transient( 'analytify_google_userinfo_probe_skip' );
190 return $from_jwt;
191 }
192 }
193
194 return '';
195 }
196
197 /**
198 * Google account email for the Authentication tab (wp-analytify-authentication option).
199 * Migrates legacy pa_google_token analytify_google_user_email key when present.
200 *
201 * @since 9.1.0
202 * @return string
203 */
204 public function analytify_get_connected_google_account_email() {
205 $stored = $this->analytify_auth_settings_get_google_oauth_email();
206 if ( $stored ) {
207 $tok_clean = get_option( 'pa_google_token' );
208 if ( is_array( $tok_clean ) && isset( $tok_clean['analytify_google_user_email'] ) ) {
209 unset( $tok_clean['analytify_google_user_email'] );
210 $this->google_token = $tok_clean;
211 update_option( 'pa_google_token', $tok_clean );
212 }
213 return $stored;
214 }
215
216 $token = get_option( 'pa_google_token' );
217 if ( ! is_array( $token ) ) {
218 return '';
219 }
220
221 $email = $this->analytify_resolve_google_oauth_email( $token );
222 if ( $email ) {
223 return $email;
224 }
225
226 if ( ! current_user_can( 'manage_options' ) ) {
227 return '';
228 }
229
230 if ( get_transient( 'analytify_google_userinfo_probe_skip' ) ) {
231 return '';
232 }
233
234 $access = $this->analytify_pa_connect_v2();
235 $token = get_option( 'pa_google_token' );
236 if ( is_array( $token ) ) {
237 $email = $this->analytify_resolve_google_oauth_email( $token );
238 if ( $email ) {
239 return $email;
240 }
241 }
242
243 if ( is_string( $access ) && '' !== $access ) {
244 $from_api = analytify_fetch_google_email_from_userinfo( $access );
245 if ( $from_api ) {
246 $this->analytify_auth_settings_set_google_oauth_email( $from_api );
247 delete_transient( 'analytify_google_userinfo_probe_skip' );
248 return $from_api;
249 }
250 set_transient( 'analytify_google_userinfo_probe_skip', 1, 6 * HOUR_IN_SECONDS );
251 }
252
253 return '';
254 }
255
256 /**
257 * Get GA4 streams data from options.
258 *
259 * @since 7.0.0
260 * @return array GA4 streams data
261 */
262 public function analytify_get_ga4_streams() {
263 if ( empty( $this->ga4_streams ) ) {
264 $this->ga4_streams = get_option( 'analytify-ga4-streams', array() );
265 }
266 return $this->ga4_streams;
267 }
268
269 /**
270 * Check the tracking method.
271 *
272 * @return void
273 */
274 public function analytify_set_tracking_mode() {
275 if ( ! defined( 'WP_ANALYTIFY_TRACKING_MODE' ) ) {
276 define( 'WP_ANALYTIFY_TRACKING_MODE', $this->settings->get_option( 'gtag_tracking_mode', 'wp-analytify-advanced', 'gtag' ) );
277 }
278 }
279
280 /**
281 * Connect with Google Analytics API and get authentication token and save it.
282 * Never logs response body (OAuth responses can contain tokens).
283 *
284 * @since 6.0.0
285 * @version 9.1.0
286 *
287 * @return string|false|null Access token, false on error, or null if no auth code.
288 */
289 public function analytify_pa_connect_v2() {
290 $logger = function_exists( 'analytify_get_logger' ) ? analytify_get_logger() : null;
291
292 // Retrieve stored token data.
293 $token_data = $this->analytify_get_google_token();
294 $auth_code = get_option( 'post_analytics_token' );
295 $refresh_token = ! empty( $token_data['refresh_token'] ) ? $token_data['refresh_token'] : null;
296 $expires_in = isset( $token_data['expires_in'] ) ? (int) $token_data['expires_in'] : 0;
297 $token_time = isset( $token_data['created_at'] ) ? (int) $token_data['created_at'] : 0;
298
299 // Return valid access token if available.
300 if ( ! empty( $token_data['access_token'] ) && ( 0 === $expires_in || ( time() - $token_time ) < $expires_in ) ) {
301 return $token_data['access_token'];
302 }
303
304 // Try refreshing using refresh token.
305 if ( ! empty( $refresh_token ) ) {
306 $access_token_data = $this->analytify_refresh_access_token( $refresh_token );
307 if ( $access_token_data && ! empty( $access_token_data['access_token'] ) ) {
308 $this->token = $access_token_data['access_token'];
309 return $access_token_data['access_token'];
310 }
311 return null;
312 }
313
314 // Fallback: use authorization code.
315 if ( empty( $auth_code ) ) {
316 return null;
317 }
318
319 try {
320 $token_uri = WP_ANALYTIFY_TOKEN_URL;
321 $token_request_data = array(
322 'client_id' => WP_ANALYTIFY_CLIENTID,
323 'client_secret' => WP_ANALYTIFY_CLIENTSECRET,
324 'code' => $auth_code,
325 'redirect_uri' => WP_ANALYTIFY_REDIRECT,
326 'grant_type' => 'authorization_code',
327 'access_type' => 'offline',
328 );
329
330 $response = wp_remote_post(
331 $token_uri,
332 array(
333 'body' => $token_request_data,
334 'headers' => array( 'Referer' => ANALYTIFY_VERSION ),
335 )
336 );
337
338 if ( is_wp_error( $response ) ) {
339 if ( ! get_transient( 'analytify_token_request_error_logged' ) ) {
340 if ( $logger && method_exists( $logger, 'warning' ) ) {
341 $logger->warning(
342 'Failed to send token request.',
343 array(
344 'source' => 'analytify_pa_connect_v2',
345 'error' => sanitize_text_field( $response->get_error_message() ),
346 'token_uri' => esc_url_raw( $token_uri ),
347 'has_auth_code' => ! empty( $auth_code ),
348 'request_grant_type' => sanitize_text_field( $token_request_data['grant_type'] ),
349 )
350 );
351 }
352 set_transient( 'analytify_token_request_error_logged', true, 24 * HOUR_IN_SECONDS );
353 }
354 return false;
355 }
356
357 $body = wp_remote_retrieve_body( $response );
358 $access_token_data = json_decode( $body, true );
359
360 if ( ! empty( $access_token_data['access_token'] ) ) {
361 $access_token_data['created_at'] = time();
362 $this->analytify_capture_google_oauth_email( $access_token_data );
363 $this->analytify_update_google_token( $access_token_data );
364 $this->analytify_update_authentication_date();
365 // Reset email notification flag on successful re-authentication.
366 delete_option( 'analytify_token_refresh_failed_email_sent' );
367 $this->token = $access_token_data['access_token'];
368 return $access_token_data['access_token'];
369 } else {
370 if ( ! get_transient( 'analytify_token_response_error_logged' ) ) {
371 // Do not log response_body (OAuth response can contain access/refresh tokens).
372 if ( $logger && method_exists( $logger, 'warning' ) ) {
373 $logger->warning(
374 'Access token not found in response.',
375 array(
376 'source' => 'analytify_pa_connect_v2',
377 'response_code' => absint( wp_remote_retrieve_response_code( $response ) ),
378 'has_auth_code' => ! empty( $auth_code ),
379 'has_refresh_token' => ! empty( $refresh_token ),
380 'token_uri' => esc_url_raw( $token_uri ),
381 'request_grant_type' => sanitize_text_field( $token_request_data['grant_type'] ),
382 )
383 );
384 }
385 set_transient( 'analytify_token_response_error_logged', true, 24 * HOUR_IN_SECONDS );
386 }
387 return false;
388 }
389 } catch ( Exception $e ) {
390 if ( ! get_transient( 'analytify_token_exception_error_logged' ) ) {
391 if ( $logger && method_exists( $logger, 'warning' ) ) {
392 $logger->warning(
393 'Exception during token request: ' . $e->getMessage(),
394 array(
395 'source' => 'analytify_pa_connect_v2',
396 'exception' => sanitize_text_field( $e->getMessage() ),
397 'token_uri' => esc_url_raw( $token_uri ),
398 'has_auth_code' => ! empty( $auth_code ),
399 'request_grant_type' => sanitize_text_field( $token_request_data['grant_type'] ),
400 'trace' => sanitize_textarea_field( $e->getTraceAsString() ),
401 )
402 );
403 }
404 set_transient( 'analytify_token_exception_error_logged', true, 24 * HOUR_IN_SECONDS );
405 }
406 return false;
407 }
408 }
409
410
411 /**
412 * Refreshes the access token using the provided refresh token.
413 *
414 * This function is responsible for obtaining a new access token
415 * by using the given refresh token. It is typically used when the
416 * current access token has expired and needs to be renewed.
417 * Never includes response body in logged error message (may contain tokens).
418 *
419 * @version 9.1.0
420 *
421 * @param string $refresh_token The refresh token used to obtain a new access token.
422 * @return mixed The new access token or an error response if the refresh fails.
423 */
424 public function analytify_refresh_access_token( $refresh_token ) {
425 $logger = function_exists( 'analytify_get_logger' ) ? analytify_get_logger() : null;
426
427 if ( empty( $refresh_token ) ) {
428 return false;
429 }
430
431 $token_uri = WP_ANALYTIFY_TOKEN_URL;
432 $request_data = array(
433 'client_id' => WP_ANALYTIFY_CLIENTID,
434 'client_secret' => WP_ANALYTIFY_CLIENTSECRET,
435 'refresh_token' => $refresh_token,
436 'grant_type' => 'refresh_token',
437 );
438
439 $response = wp_remote_post(
440 $token_uri,
441 array(
442 'body' => $request_data,
443 'headers' => array( 'Referer' => ANALYTIFY_VERSION ),
444 )
445 );
446
447 if ( is_wp_error( $response ) ) {
448 if ( ! get_transient( 'analytify_token_error_logged' ) ) {
449 if ( $logger && method_exists( $logger, 'warning' ) ) {
450 $logger->warning(
451 'Failed to refresh access token.',
452 array(
453 'source' => 'analytify_refresh_access_token',
454 'error' => sanitize_text_field( $response->get_error_message() ),
455 'refresh_token_provided' => ! empty( $refresh_token ),
456 )
457 );
458 }
459 set_transient( 'analytify_token_error_logged', true, HOUR_IN_SECONDS );
460 }
461 return false;
462 }
463
464 $response_code = wp_remote_retrieve_response_code( $response );
465 $body = wp_remote_retrieve_body( $response );
466 $access_token_data = json_decode( $body, true );
467
468 if ( 200 !== $response_code || empty( $access_token_data['access_token'] ) ) {
469 // Do not include response body in error message (may contain tokens).
470 $error_message = "HTTP {$response_code}: Failed to refresh access token.";
471
472 // Check if email notification is enabled in Advanced settings.
473 $advanced_settings = get_option( 'wp-analytify-advanced', array() );
474 $email_enabled = isset( $advanced_settings['enable_token_refresh_failure_email'] ) && 'on' === $advanced_settings['enable_token_refresh_failure_email'];
475
476 // Send one-time email notification if enabled and not already sent.
477 if ( $email_enabled ) {
478 $email_already_sent = get_option( 'analytify_token_refresh_failed_email_sent', false );
479
480 if ( ! $email_already_sent ) {
481 $site_name = get_bloginfo( 'name' );
482 $site_url = home_url();
483
484 // Default email arguments.
485 $default_mail_args = array(
486 'to' => get_option( 'admin_email' ),
487 'subject' => sprintf(
488 /* translators: %s: Site name */
489 __( '[%s] Analytify: Google Analytics Token Refresh Failed', 'wp-analytify' ),
490 $site_name
491 ),
492 'message' => sprintf(
493 /* translators: 1: Site name, 2: Site URL, 3: Error message, 4: Settings URL */
494 __(
495 'Hello,
496
497 Your Google Analytics token refresh has failed on %1$s (%2$s).
498
499 Error details: %3$s
500
501 Please re-authenticate your Google Analytics connection in the Analytify settings to restore functionality.
502
503 You can access the settings here: %4$s
504
505 This is an automated notification from Analytify.',
506 'wp-analytify'
507 ),
508 $site_name,
509 $site_url,
510 wp_kses( $error_message, array() ),
511 admin_url( 'admin.php?page=analytify-settings' )
512 ),
513 'headers' => array( 'Content-Type: text/plain; charset=UTF-8' ),
514 );
515
516 /**
517 * Filter email arguments for token refresh failure notification.
518 *
519 * @since 8.0.0
520 * @param array $mail_args Email arguments. Keys: to, subject, message, headers.
521 * @param string $error_message Error message describing the token refresh failure.
522 * @return array Filtered email arguments with keys: to, subject, message, headers.
523 */
524 $mail_args = apply_filters( 'analytify_token_refresh_failed_email_args', $default_mail_args, $error_message );
525
526 // Ensure filter result is an array.
527 if ( ! is_array( $mail_args ) ) {
528 $mail_args = $default_mail_args;
529 }
530
531 // Parse with defaults to ensure all required keys exist.
532 $mail_args = wp_parse_args( $mail_args, $default_mail_args );
533
534 // Validate and sanitize recipient(s).
535 $recipients = $mail_args['to'];
536 if ( is_string( $recipients ) ) {
537 // Handle comma-separated emails.
538 $recipients = array_map( 'trim', explode( ',', $recipients ) );
539 } elseif ( ! is_array( $recipients ) ) {
540 $recipients = array();
541 }
542
543 // Sanitize each email address and filter out empty/invalid ones.
544 $sanitized_recipients = array();
545 foreach ( $recipients as $recipient ) {
546 $sanitized = sanitize_email( $recipient );
547 if ( ! empty( $sanitized ) && is_email( $sanitized ) ) {
548 $sanitized_recipients[] = $sanitized;
549 }
550 }
551
552 // Defensive: Skip wp_mail if no valid recipients.
553 if ( empty( $sanitized_recipients ) ) {
554 if ( $logger && method_exists( $logger, 'warning' ) ) {
555 $logger->warning(
556 'Token refresh failure email skipped - no valid recipients.',
557 array(
558 'source' => 'analytify_refresh_access_token',
559 'original_recipients' => $recipients,
560 )
561 );
562 }
563 } else {
564 // Sanitize subject.
565 $subject = wp_strip_all_tags( $mail_args['subject'] );
566
567 // Validate and sanitize headers.
568 $headers = $mail_args['headers'];
569 if ( is_string( $headers ) ) {
570 $headers = array( $headers );
571 } elseif ( ! is_array( $headers ) ) {
572 $headers = array();
573 }
574
575 // Sanitize header strings.
576 $sanitized_headers = array();
577 foreach ( $headers as $header ) {
578 if ( is_string( $header ) && ! empty( trim( $header ) ) ) {
579 $sanitized_headers[] = sanitize_text_field( $header );
580 }
581 }
582
583 // Convert recipients array to comma-separated string for wp_mail.
584 $to = implode( ',', $sanitized_recipients );
585
586 // Send email.
587 $email_sent = wp_mail( $to, $subject, $mail_args['message'], $sanitized_headers );
588
589 if ( $email_sent ) {
590 // Store flag in separate option only if email succeeds.
591 update_option( 'analytify_token_refresh_failed_email_sent', true );
592 } elseif ( $logger && method_exists( $logger, 'warning' ) ) {
593 $logger->warning(
594 'Token refresh failure email failed to send via wp_mail.',
595 array(
596 'source' => 'analytify_refresh_access_token',
597 'recipients' => $sanitized_recipients,
598 'subject' => $subject,
599 )
600 );
601 }
602 }
603 }
604 }
605
606 if ( ! apply_filters( 'analytify_suppress_default_token_error_log', false, $error_message ) ) {
607 if ( ! get_transient( 'analytify_token_error_logged' ) ) {
608 if ( $logger && method_exists( $logger, 'warning' ) ) {
609 $logger->warning(
610 'Token refresh failed.',
611 array(
612 'source' => 'analytify_refresh_access_token',
613 'error_message' => sanitize_text_field( $error_message ),
614 'response_code' => absint( wp_remote_retrieve_response_code( $response ) ),
615 )
616 );
617 }
618 set_transient( 'analytify_token_error_logged', true, DAY_IN_SECONDS );
619 }
620 }
621
622 return false;
623 }
624
625 // Merge with existing token data and save.
626 $existing_token_data = $this->analytify_get_google_token();
627 if ( ! is_array( $existing_token_data ) ) {
628 $existing_token_data = array();
629 }
630 $updated_token_data = array_merge(
631 $existing_token_data,
632 array(
633 'access_token' => $access_token_data['access_token'],
634 'expires_in' => $access_token_data['expires_in'],
635 'created_at' => time(),
636 )
637 );
638
639 $this->analytify_capture_google_oauth_email( $updated_token_data );
640 $this->analytify_update_google_token( $updated_token_data );
641 $this->analytify_update_authentication_date();
642 // Reset email notification flag on successful token refresh.
643 delete_option( 'analytify_token_refresh_failed_email_sent' );
644
645 return $updated_token_data;
646 }
647
648 /**
649 * Get a fresh access token.
650 *
651 * @since 7.0.0
652 */
653 public function analytify_get_fresh_access_token() {
654 // Load the token from your storage.
655 $auth_token = $this->client->getAccessToken();
656
657 // Extract the created time and expires_in value.
658 $created_time = $auth_token['created'];
659 $expires_in = $auth_token['expires_in'];
660
661 // Get the current time.
662 $current_time = time();
663
664 // Check if the token has expired.
665 if ( ( $created_time + $expires_in ) < $current_time ) {
666 // Token has expired, refresh it.
667 if ( $this->client->isAccessTokenExpired() ) {
668 $this->client->fetchAccessTokenWithRefreshToken( $this->client->getRefreshToken() );
669
670 // Save the new token to your storage.
671 $new_token = $this->client->getAccessToken();
672 }
673 }
674
675 // Return the access token (fresh or existing).
676 $auth_token = $this->client->getAccessToken();
677 return $auth_token['access_token'];
678 }
679 }
680