<?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
namespace Yoast\WP\SEO\MyYoast_Client\Application\Exceptions;
use RuntimeException;
use Throwable;
/**
* Exception thrown when a token endpoint request fails.
*
* Wraps OAuth error codes like `invalid_grant`, `invalid_client`,
* `invalid_dpop_proof`, etc.
*/
class Token_Request_Failed_Exception extends RuntimeException {
/**
* The OAuth error code from the token endpoint response.
*
* @var string
*/
private $error_code;
/**
* Token_Request_Failed_Exception constructor.
*
* @param string $error_code The OAuth error code.
* @param string $error_description A human-readable description.
* @param int $code The HTTP status code.
* @param Throwable|null $previous The previous exception.
*/
public function __construct( string $error_code, string $error_description = '', int $code = 0, ?Throwable $previous = null ) {
$this->error_code = $error_code;
$message = $error_code;
if ( $error_description !== '' ) {
$message .= ': ' . $error_description;
}
parent::__construct( $message, $code, $previous );
}
/**
* Returns the OAuth error code.
*
* @return string
*/
public function get_error_code(): string {
return $this->error_code;
}
/**
* Creates an exception from a token endpoint response body.
*
* @param array<string, string> $response_body The parsed JSON response.
* @param int $status_code The HTTP status code.
*
* @return self
*/
public static function from_response( array $response_body, int $status_code = 0 ): self {
return new self(
( $response_body['error'] ?? 'unknown_error' ),
( $response_body['error_description'] ?? '' ),
$status_code,
);
}
}