Yoast\WP\SEO\AI\Consent\Application
Consent_Handler{} │ Yoast 1.0└─ Consent_Handler_Interface
Class Consent_Handler Handles the consent given or revoked by the user, both locally (user meta) and remotely (Yoast AI service).
Хуков нет.
Использование
$Consent_Handler = new Consent_Handler(); // use class methods
Методы
- public __construct(
- public grant_consent( int $user_id )
- public revoke_consent( int $user_id )
- ERROR: no method name found on line `* @param AI_Request_Sender_Factory $ai_request_sender_factory The AI request sender factory.`
- ERROR: no method name found on line `* @throws Too_Many_Requests_Exception When the AI service responds with 429.`
Код Consent_Handler{} Consent Handler{} Yoast 28.3
class Consent_Handler implements Consent_Handler_Interface {
/**
* Holds the user helper instance.
*
* @var User_Helper
*/
private $user_helper;
/**
* The AI request sender factory, used to dispatch the consent calls through the active auth strategy.
*
* @var AI_Request_Sender_Factory
*/
private $ai_request_sender_factory;
/**
* The token manager, used to invalidate leftover legacy JWTs when consent is revoked.
*
* @var Token_Manager
*/
private $token_manager;
/**
* Class constructor.
*
* @param User_Helper $user_helper The user helper.
* @param AI_Request_Sender_Factory $ai_request_sender_factory The AI request sender factory.
* @param Token_Manager $token_manager The token manager.
*/
public function __construct(
User_Helper $user_helper,
AI_Request_Sender_Factory $ai_request_sender_factory,
Token_Manager $token_manager
) {
$this->user_helper = $user_helper;
$this->ai_request_sender_factory = $ai_request_sender_factory;
$this->token_manager = $token_manager;
}
// phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber -- PHPCS doesn't take into account exceptions thrown in called methods.
/**
* Records the user's consent on the Yoast AI service and, on success, in the local user meta.
*
* Transactional: any HTTP-layer exception is propagated and the local meta is left untouched, so
* the local and server state stay in sync.
*
* @param int $user_id The user ID.
*
* @return void
*
* @throws Bad_Request_Exception When the AI service responds with 400.
* @throws Consent_Required_Exception When the AI service responds with a 403 indicating consent is required.
* @throws Insufficient_Scope_Exception When the AI service responds with a 403 insufficient_scope.
* @throws Forbidden_Exception When the AI service responds with any other 403.
* @throws Internal_Server_Error_Exception When the AI service responds with 500.
* @throws Not_Found_Exception When the AI service responds with 404.
* @throws Payment_Required_Exception When the AI service responds with 402.
* @throws Request_Timeout_Exception When the AI service responds with 408.
* @throws Service_Unavailable_Exception When the AI service responds with 503.
* @throws Too_Many_Requests_Exception When the AI service responds with 429.
* @throws Unauthorized_Exception When the AI service responds with 401.
* @throws WP_Request_Exception When the underlying WordPress HTTP call fails.
* @throws RuntimeException When the user is not found.
*/
public function grant_consent( int $user_id ) {
$user = \get_user_by( 'id', $user_id );
if ( ! $user instanceof WP_User ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- false positive.
throw new RuntimeException( "User not found: $user_id" );
}
$this->ai_request_sender_factory->create( $user )->grant_consent( $user );
$this->user_helper->update_meta( $user_id, '_yoast_wpseo_ai_consent', true );
}
/**
* Revokes the user's consent on the Yoast AI service and clears the local user meta.
*
* Security-first: the local meta is always cleared before the remote call, so consent is
* revoked locally even if the remote `DELETE /user/consent` fails. Any locally stored legacy
* JWTs are then invalidated regardless of the remote outcome — credentials must not outlive
* consent. The invalidation runs after the DELETE on purpose: the legacy Token path may mint
* a fresh JWT to authenticate the DELETE, and invalidating afterwards catches that token too.
* Any HTTP-layer exception is propagated and its management is deferred to the caller.
*
* @param int $user_id The user ID.
*
* @return void
*
* @throws Bad_Request_Exception When the AI service responds with 400.
* @throws Consent_Required_Exception When the AI service responds with a 403 indicating consent is required.
* @throws Insufficient_Scope_Exception When the AI service responds with a 403 insufficient_scope.
* @throws Forbidden_Exception When the AI service responds with any other 403.
* @throws Internal_Server_Error_Exception When the AI service responds with 500.
* @throws Not_Found_Exception When the AI service responds with 404.
* @throws Payment_Required_Exception When the AI service responds with 402.
* @throws Request_Timeout_Exception When the AI service responds with 408.
* @throws Service_Unavailable_Exception When the AI service responds with 503.
* @throws Too_Many_Requests_Exception When the AI service responds with 429.
* @throws Unauthorized_Exception When the AI service responds with 401.
* @throws WP_Request_Exception When the underlying WordPress HTTP call fails.
* @throws RuntimeException When the user is not found.
*/
public function revoke_consent( int $user_id ) {
$user = \get_user_by( 'id', $user_id );
if ( ! $user instanceof WP_User ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- false positive.
throw new RuntimeException( "User not found: $user_id" );
}
// Local consent is always revoked regardless of remote failures.
$this->user_helper->delete_meta( $user_id, '_yoast_wpseo_ai_consent' );
try {
$this->ai_request_sender_factory->create( $user )->revoke_consent( $user );
} finally {
// Invalidate the legacy JWTs — including ones minted to authenticate the DELETE above —
// so credentials never outlive consent. Skipped when no local JWTs exist (the OAuth path
// without a leftover pre-OAuth grant).
if ( $this->token_manager->has_local_tokens( $user_id ) ) {
$this->token_manager->token_invalidate( $user_id );
}
}
}
// phpcs:enable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
}