22
33namespace Yoast \WP \SEO \AI_Consent \Application ;
44
5+ use Yoast \WP \SEO \AI_Authorization \Application \Token_Manager ;
6+ use Yoast \WP \SEO \AI_HTTP_Request \Application \Request_Handler ;
7+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \Bad_Request_Exception ;
8+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \Forbidden_Exception ;
9+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \Internal_Server_Error_Exception ;
10+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \Not_Found_Exception ;
11+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \Payment_Required_Exception ;
12+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \Remote_Request_Exception ;
13+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \Request_Timeout_Exception ;
14+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \Service_Unavailable_Exception ;
15+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \Too_Many_Requests_Exception ;
16+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \Unauthorized_Exception ;
17+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Exceptions \WP_Request_Exception ;
18+ use Yoast \WP \SEO \AI_HTTP_Request \Domain \Request ;
519use Yoast \WP \SEO \Helpers \User_Helper ;
20+ use Yoast \WP \SEO \Loggers \Logger ;
621
722/**
823 * Class Consent_Handler
9- * Handles the consent given or revoked by the user.
24+ * Handles the consent given or revoked by the user, both locally (user meta) and remotely (Yoast AI service) .
1025 *
1126 * @makePublic
1227 */
@@ -19,34 +34,112 @@ class Consent_Handler implements Consent_Handler_Interface {
1934 */
2035 private $ user_helper ;
2136
37+ /**
38+ * The token manager instance.
39+ *
40+ * @var Token_Manager
41+ */
42+ private $ token_manager ;
43+
44+ /**
45+ * The request handler instance.
46+ *
47+ * @var Request_Handler
48+ */
49+ private $ request_handler ;
50+
51+ /**
52+ * The logger instance.
53+ *
54+ * @var Logger
55+ */
56+ private $ logger ;
57+
2258 /**
2359 * Class constructor.
2460 *
25- * @param User_Helper $user_helper The user helper.
61+ * @param User_Helper $user_helper The user helper.
62+ * @param Token_Manager $token_manager The token manager, used to obtain a JWT for the consent endpoints.
63+ * @param Request_Handler $request_handler The request handler, used to call the AI service's consent endpoints.
64+ * @param Logger $logger The logger, used to record best-effort failures during revoke.
2665 */
27- public function __construct ( User_Helper $ user_helper ) {
28- $ this ->user_helper = $ user_helper ;
66+ public function __construct (
67+ User_Helper $ user_helper ,
68+ Token_Manager $ token_manager ,
69+ Request_Handler $ request_handler ,
70+ Logger $ logger
71+ ) {
72+ $ this ->user_helper = $ user_helper ;
73+ $ this ->token_manager = $ token_manager ;
74+ $ this ->request_handler = $ request_handler ;
75+ $ this ->logger = $ logger ;
2976 }
3077
78+ // phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber -- PHPCS doesn't take into account exceptions thrown in called methods.
79+
3180 /**
32- * Handles consent revoked by deleting the consent user metadata from the database.
81+ * Records the user's consent on the Yoast AI service and, on success, in the local user meta.
82+ *
83+ * Transactional: any HTTP-layer exception is propagated and the local meta is left untouched, so
84+ * the local and server state stay in sync.
3385 *
3486 * @param int $user_id The user ID.
3587 *
3688 * @return void
89+ *
90+ * @throws Bad_Request_Exception When the AI service responds with 400.
91+ * @throws Forbidden_Exception When the AI service responds with 403.
92+ * @throws Internal_Server_Error_Exception When the AI service responds with 500.
93+ * @throws Not_Found_Exception When the AI service responds with 404.
94+ * @throws Payment_Required_Exception When the AI service responds with 402.
95+ * @throws Request_Timeout_Exception When the AI service responds with 408.
96+ * @throws Service_Unavailable_Exception When the AI service responds with 503.
97+ * @throws Too_Many_Requests_Exception When the AI service responds with 429.
98+ * @throws Unauthorized_Exception When the AI service responds with 401.
99+ * @throws WP_Request_Exception When the underlying WordPress HTTP call fails.
37100 */
38- public function revoke_consent ( int $ user_id ) {
39- $ this ->user_helper ->delete_meta ( $ user_id , '_yoast_wpseo_ai_consent ' );
101+ public function grant_consent ( int $ user_id ) {
102+ $ user = \get_user_by ( 'id ' , $ user_id );
103+ $ jwt = $ this ->token_manager ->get_or_request_access_token ( $ user );
104+
105+ $ this ->request_handler ->handle (
106+ new Request ( '/user/consent ' , [], [ 'Authorization ' => "Bearer $ jwt " ], Request::METHOD_POST ),
107+ );
108+
109+ $ this ->user_helper ->update_meta ( $ user_id , '_yoast_wpseo_ai_consent ' , true );
40110 }
41111
42112 /**
43- * Handles consent granted by adding the consent user metadata to the database.
113+ * Revokes the user's consent on the Yoast AI service and clears the local user meta.
114+ *
115+ * Security-first: the local meta is always cleared, even if the remote DELETE fails. HTTP-layer
116+ * failures are logged as warnings and swallowed; programmer errors (non-`Remote_Request_Exception`
117+ * / non-`WP_Request_Exception`) are not caught and will propagate.
44118 *
45119 * @param int $user_id The user ID.
46120 *
47121 * @return void
48122 */
49- public function grant_consent ( int $ user_id ) {
50- $ this ->user_helper ->update_meta ( $ user_id , '_yoast_wpseo_ai_consent ' , true );
123+ public function revoke_consent ( int $ user_id ) {
124+ try {
125+ $ user = \get_user_by ( 'id ' , $ user_id );
126+ $ jwt = $ this ->token_manager ->get_or_request_access_token ( $ user );
127+
128+ $ this ->request_handler ->handle (
129+ new Request ( '/user/consent ' , [], [ 'Authorization ' => "Bearer $ jwt " ], Request::METHOD_DELETE ),
130+ );
131+ } catch ( Remote_Request_Exception | WP_Request_Exception $ e ) {
132+ $ this ->logger ->warning (
133+ 'Failed to revoke consent on the Yoast AI service; clearing local consent anyway. ' ,
134+ [
135+ 'user_id ' => $ user_id ,
136+ 'exception ' => $ e ->getMessage (),
137+ ],
138+ );
139+ }
140+
141+ $ this ->user_helper ->delete_meta ( $ user_id , '_yoast_wpseo_ai_consent ' );
51142 }
143+
144+ // phpcs:enable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
52145}
0 commit comments