🏠 Root
/
home
/
artorgp
/
www
/
wp-content
/
plugins
/
wordpress-seo
/
src
/
myyoast-client
/
domain
/
Editing: token-set.php
<?php namespace Yoast\WP\SEO\MyYoast_Client\Domain; use InvalidArgumentException; use SensitiveParameter; /** * Immutable value object representing a set of OAuth tokens. * * Can represent both user-level tokens (from authorization code flow, with * refresh_token and id_token) and site-level tokens (from client_credentials, * access_token only). */ class Token_Set { /** * Seconds before actual expiry to consider the token expired. * Accounts for request latency and minor clock differences. */ private const EXPIRY_BUFFER_SECONDS = 60; /** * The access token (opaque string — do not parse). * * @var string */ private $access_token; /** * The Unix timestamp at which the access token expires. * * @var int */ private $expires_at; /** * The refresh token, if available (user-level tokens only). * * @var string|null */ private $refresh_token; /** * The OIDC ID token, if available (user-level tokens only). * * @var string|null */ private $id_token; /** * The granted scope string. * * @var string|null */ private $scope; /** * The token type (an Auth_Token_Type constant). * * @var string */ private $token_type; /** * The number of consecutive refresh errors. * * @var int */ private $error_count; /** * Token_Set constructor. * * @param string $access_token The access token. * @param int $expires_at Unix timestamp of token expiry. * @param string $token_type An Auth_Token_Type constant. * @param string|null $refresh_token The refresh token. * @param string|null $id_token The OIDC ID token. * @param string|null $scope The granted scope. * @param int $error_count The number of consecutive refresh errors. * * @throws InvalidArgumentException If required fields are empty or invalid. */ public function __construct( // phpcs:ignore PHPCompatibility.Attributes.NewAttributes.PHPNativeAttributeFound -- No-op on PHP < 8.2; redacts parameter from stack traces on PHP 8.2+. #[SensitiveParameter] string $access_token, int $expires_at, string $token_type = Auth_Token_Type::DPOP, // phpcs:ignore PHPCompatibility.Attributes.NewAttributes.PHPNativeAttributeFound -- No-op on PHP < 8.2; redacts parameter from stack traces on PHP 8.2+. #[SensitiveParameter] ?string $refresh_token = null, ?string $id_token = null, ?string $scope = null, int $error_count = 0 ) { if ( $access_token === '' ) { throw new InvalidArgumentException( 'Token_Set requires a non-empty access_token.' ); } if ( $expires_at <= 0 ) { throw new InvalidArgumentException( 'Token_Set requires a positive expires_at timestamp.' ); } if ( $token_type === '' ) { throw new InvalidArgumentException( 'Token_Set requires a non-empty token_type.' ); } $this->access_token = $access_token; $this->expires_at = $expires_at; $this->token_type = $token_type; $this->refresh_token = $refresh_token; $this->id_token = $id_token; $this->scope = $scope; $this->error_count = $error_count; } /** * Returns the access token. * * @return string */ public function get_access_token(): string { return $this->access_token; } /** * Returns the Unix timestamp at which the access token expires. * * @return int */ public function get_expires_at(): int { return $this->expires_at; } /** * Returns the token type. * * @return string */ public function get_token_type(): string { return $this->token_type; } /** * Returns the refresh token, or null if not available. * * @return string|null */ public function get_refresh_token(): ?string { return $this->refresh_token; } /** * Returns the OIDC ID token, or null if not available. * * @return string|null */ public function get_id_token(): ?string { return $this->id_token; } /** * Returns the granted scope string, or null if not available. * * @return string|null */ public function get_scope(): ?string { return $this->scope; } /** * Checks if the token set has the required scope(s). * Returns true if AT LEAST all required scopes are granted, false otherwise. * * @param string[] $required_scopes The required scopes as an array of strings. * * @return bool True if all required scopes are granted, false otherwise. */ public function has_scopes( array $required_scopes ): bool { if ( $this->scope === null ) { return \count( $required_scopes ) === 0; } $granted_scopes = \explode( ' ', $this->scope ); return \count( \array_diff( $required_scopes, $granted_scopes ) ) === 0; } /** * Returns the number of consecutive refresh errors. * * @return int */ public function get_error_count(): int { return $this->error_count; } /** * Returns a new Token_Set with an incremented error count. * * @return self */ public function with_incremented_error_count(): self { return new self( $this->access_token, $this->expires_at, $this->token_type, $this->refresh_token, $this->id_token, $this->scope, $this->error_count + 1, ); } /** * Whether the access token has expired. * * Uses a 60-second buffer to allow for request latency. * * @return bool */ public function is_expired(): bool { return \time() >= ( $this->expires_at - self::EXPIRY_BUFFER_SECONDS ); } /** * Converts the token set to an associative array for storage. * * @return array<string, string|int|null> The token set as an array. */ public function to_array(): array { return [ 'access_token' => $this->access_token, 'expires_at' => $this->expires_at, 'token_type' => $this->token_type, 'refresh_token' => $this->refresh_token, 'id_token' => $this->id_token, 'scope' => $this->scope, 'error_count' => $this->error_count, ]; } /** * Creates a Token_Set from a stored array. * * @param array<string, string|int|null> $data The stored array data. * * @return self */ public static function from_array( array $data ): self { return new self( (string) ( $data['access_token'] ?? '' ), (int) ( $data['expires_at'] ?? 0 ), ( $data['token_type'] ?? Auth_Token_Type::DPOP ), ( $data['refresh_token'] ?? null ), ( $data['id_token'] ?? null ), ( $data['scope'] ?? null ), (int) ( $data['error_count'] ?? 0 ), ); } /** * Creates a Token_Set from a token endpoint response. * * @param array<string, string|int|null> $response The parsed JSON response from the token endpoint. * * @return self * * @throws InvalidArgumentException If the response is missing a valid access_token. */ public static function from_response( array $response ): self { if ( empty( $response['access_token'] ) || ! \is_string( $response['access_token'] ) ) { throw new InvalidArgumentException( 'Token response is missing a valid access_token.' ); } $expires_in = (int) ( $response['expires_in'] ?? 900 ); return new self( $response['access_token'], ( \time() + $expires_in ), ( $response['token_type'] ?? Auth_Token_Type::DPOP ), ( $response['refresh_token'] ?? null ), ( $response['id_token'] ?? null ), ( $response['scope'] ?? null ), ); } }
Save
Cancel