PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / trunk
Yoast SEO – Advanced SEO with real-time guidance and built-in AI vtrunk
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
← All changes | src/ai/generator/application/suggestions-provider.php +33 -81 27.9 → trunk View file →
@@ -5,15 +5,16 @@
5 5 namespace Yoast\WP\SEO\AI\Generator\Application;
6 6
7 7 use RuntimeException;
8 8 use WP_User;
9 -use Yoast\WP\SEO\AI\Authorization\Application\Token_Manager;
9 +use Yoast\WP\SEO\AI\Authentication\Application\AI_Request_Sender_Factory;
10 10 use Yoast\WP\SEO\AI\Consent\Application\Consent_Handler;
11 11 use Yoast\WP\SEO\AI\Generator\Domain\Suggestion;
12 12 use Yoast\WP\SEO\AI\Generator\Domain\Suggestions_Bucket;
13 -use Yoast\WP\SEO\AI\HTTP_Request\Application\Request_Handler;
13 +use Yoast\WP\SEO\AI\Generator\Domain\Suggestions_Parameters;
14 14 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Bad_Request_Exception;
15 15 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Forbidden_Exception;
16 +use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Insufficient_Scope_Exception;
16 17 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Internal_Server_Error_Exception;
17 18 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Not_Found_Exception;
18 19 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Payment_Required_Exception;
19 20 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Request_Timeout_Exception;
@@ -19,11 +20,9 @@
19 20 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Request_Timeout_Exception;
20 21 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Service_Unavailable_Exception;
21 22 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Too_Many_Requests_Exception;
22 23 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Unauthorized_Exception;
23 -use Yoast\WP\SEO\AI\HTTP_Request\Domain\Request;
24 24 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Response;
25 -use Yoast\WP\SEO\Helpers\User_Helper;
26 25
27 26 /**
28 27 * The class that handles the suggestions from the AI API.
29 28 */
@@ -36,46 +35,26 @@
36 35 */
37 36 private $consent_handler;
38 37
39 38 /**
40 - * The request handler instance.
39 + * The auth strategy factory.
41 40 *
42 - * @var Request_Handler
41 + * @var AI_Request_Sender_Factory
43 42 */
44 - private $request_handler;
43 + private $ai_request_sender_factory;
45 44
46 45 /**
47 - * The token manager instance.
48 - *
49 - * @var Token_Manager
50 - */
51 - private $token_manager;
52 -
53 - /**
54 - * The user helper instance.
55 - *
56 - * @var User_Helper
57 - */
58 - private $user_helper;
59 -
60 - /**
61 46 * Class constructor.
62 47 *
63 - * @param Consent_Handler $consent_handler The consent handler instance.
64 - * @param Request_Handler $request_handler The request handler instance.
65 - * @param Token_Manager $token_manager The token manager instance.
66 - * @param User_Helper $user_helper The user helper instance.
48 + * @param Consent_Handler $consent_handler The consent handler instance.
49 + * @param AI_Request_Sender_Factory $ai_request_sender_factory The auth strategy factory.
67 50 */
68 51 public function __construct(
69 52 Consent_Handler $consent_handler,
70 - Request_Handler $request_handler,
71 - Token_Manager $token_manager,
72 - User_Helper $user_helper
53 + AI_Request_Sender_Factory $ai_request_sender_factory
73 54 ) {
74 - $this->consent_handler = $consent_handler;
75 - $this->request_handler = $request_handler;
76 - $this->token_manager = $token_manager;
77 - $this->user_helper = $user_helper;
55 + $this->consent_handler = $consent_handler;
56 + $this->ai_request_sender_factory = $ai_request_sender_factory;
78 57 }
79 58
80 59 // phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber -- PHPCS doesn't take into account exceptions thrown in called methods.
81 60
@@ -81,16 +60,15 @@
81 60
82 61 /**
83 62 * Method used to generate suggestions through AI.
84 63 *
85 - * @param WP_User $user The WP user.
86 - * @param string $suggestion_type The type of the requested suggestion.
87 - * @param string $prompt_content The excerpt taken from the post.
88 - * @param string $focus_keyphrase The focus keyphrase associated to the post.
89 - * @param string $language The language of the post.
90 - * @param string $platform The platform the post is intended for.
91 - * @param string $editor The current editor.
92 - * @param bool $retry_on_unauthorized Whether to retry when unauthorized (mechanism to retry once).
64 + * @param WP_User $user The WP user.
65 + * @param string $suggestion_type The type of the requested suggestion.
66 + * @param string $prompt_content The excerpt taken from the post.
67 + * @param string $focus_keyphrase The focus keyphrase associated to the post.
68 + * @param string $language The language of the post.
69 + * @param string $platform The platform the post is intended for.
70 + * @param string $editor The current editor.
93 71 *
94 72 * @throws Bad_Request_Exception Bad_Request_Exception.
95 73 * @throws Forbidden_Exception Forbidden_Exception.
96 74 * @throws Internal_Server_Error_Exception Internal_Server_Error_Exception.
@@ -109,55 +87,29 @@
109 87 string $prompt_content,
110 88 string $focus_keyphrase,
111 89 string $language,
112 90 string $platform,
113 - string $editor,
114 - bool $retry_on_unauthorized = true
91 + string $editor
115 92 ): array {
116 - try {
117 - $token = $this->token_manager->get_or_request_access_token( $user );
118 - } catch ( Forbidden_Exception $exception ) {
119 - // Follow the API in the consent being revoked (Use case: user sent an e-mail to revoke?).
120 - // phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped -- false positive.
121 - $this->consent_handler->revoke_consent( $user->ID );
122 - throw new Forbidden_Exception( 'CONSENT_REVOKED', $exception->getCode() );
123 - // phpcs:enable WordPress.Security.EscapeOutput.ExceptionNotEscaped
124 - }
93 + $parameters = new Suggestions_Parameters(
94 + $user,
95 + $suggestion_type,
96 + $prompt_content,
97 + $focus_keyphrase,
98 + $language,
99 + $platform,
100 + $editor,
101 + );
125 102
126 - $request_body = [
127 - 'service' => 'openai',
128 - 'user_id' => (string) $user->ID,
129 - 'subject' => [
130 - 'content' => $prompt_content,
131 - 'focus_keyphrase' => $focus_keyphrase,
132 - 'language' => $language,
133 - 'platform' => $platform,
134 - ],
135 - ];
136 - $request_headers = [
137 - 'Authorization' => "Bearer $token",
138 - 'X-Yst-Cohort' => $editor,
139 - ];
140 -
141 103 try {
142 - $response = $this->request_handler->handle( new Request( "/openai/suggestions/$suggestion_type", $request_body, $request_headers ) );
143 - } catch ( Unauthorized_Exception $exception ) {
144 - // Delete the stored JWT tokens, as they appear to be no longer valid.
145 - $this->user_helper->delete_meta( $user->ID, '_yoast_wpseo_ai_generator_access_jwt' );
146 - $this->user_helper->delete_meta( $user->ID, '_yoast_wpseo_ai_generator_refresh_jwt' );
147 -
148 - if ( ! $retry_on_unauthorized ) {
149 - throw $exception;
150 - }
151 -
152 - // Try again once more by fetching a new set of tokens and trying the suggestions endpoint again.
153 - return $this->get_suggestions( $user, $suggestion_type, $prompt_content, $focus_keyphrase, $language, $platform, $editor, false );
104 + $sender = $this->ai_request_sender_factory->create( $user );
105 + $response = $sender->get_suggestions( $parameters );
106 + } catch ( Insufficient_Scope_Exception $exception ) {
107 + throw $exception;
154 108 } catch ( Forbidden_Exception $exception ) {
155 - // Follow the API in the consent being revoked (Use case: user sent an e-mail to revoke?).
156 - // phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped -- false positive.
157 109 $this->consent_handler->revoke_consent( $user->ID );
110 + // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
158 111 throw new Forbidden_Exception( 'CONSENT_REVOKED', $exception->getCode() );
159 - // phpcs:enable WordPress.Security.EscapeOutput.ExceptionNotEscaped
160 112 }
161 113
162 114 return $this->build_suggestions_array( $response )->to_array();
163 115 }