PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.2
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.2
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
wordpress-seo / src / ai / generator / application / suggestions-provider.php

suggestions-provider.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.2, at src/ai/generator/application/suggestions-provider.php

139 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
4
5 namespace Yoast\WP\SEO\AI\Generator\Application;
6
7 use RuntimeException;
8 use WP_User;
9 use Yoast\WP\SEO\AI\Authentication\Application\AI_Request_Sender_Factory;
10 use Yoast\WP\SEO\AI\Consent\Application\Consent_Handler;
11 use Yoast\WP\SEO\AI\Generator\Domain\Suggestion;
12 use Yoast\WP\SEO\AI\Generator\Domain\Suggestions_Bucket;
13 use Yoast\WP\SEO\AI\Generator\Domain\Suggestions_Parameters;
14 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Bad_Request_Exception;
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;
17 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Internal_Server_Error_Exception;
18 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Not_Found_Exception;
19 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Payment_Required_Exception;
20 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Request_Timeout_Exception;
21 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Service_Unavailable_Exception;
22 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Too_Many_Requests_Exception;
23 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Exceptions\Unauthorized_Exception;
24 use Yoast\WP\SEO\AI\HTTP_Request\Domain\Response;
25
26 /**
27 * The class that handles the suggestions from the AI API.
28 */
29 class Suggestions_Provider {
30
31 /**
32 * The consent handler instance.
33 *
34 * @var Consent_Handler
35 */
36 private $consent_handler;
37
38 /**
39 * The auth strategy factory.
40 *
41 * @var AI_Request_Sender_Factory
42 */
43 private $ai_request_sender_factory;
44
45 /**
46 * Class constructor.
47 *
48 * @param Consent_Handler $consent_handler The consent handler instance.
49 * @param AI_Request_Sender_Factory $ai_request_sender_factory The auth strategy factory.
50 */
51 public function __construct(
52 Consent_Handler $consent_handler,
53 AI_Request_Sender_Factory $ai_request_sender_factory
54 ) {
55 $this->consent_handler = $consent_handler;
56 $this->ai_request_sender_factory = $ai_request_sender_factory;
57 }
58
59 // phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber -- PHPCS doesn't take into account exceptions thrown in called methods.
60
61 /**
62 * Method used to generate suggestions through AI.
63 *
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.
71 *
72 * @throws Bad_Request_Exception Bad_Request_Exception.
73 * @throws Forbidden_Exception Forbidden_Exception.
74 * @throws Internal_Server_Error_Exception Internal_Server_Error_Exception.
75 * @throws Not_Found_Exception Not_Found_Exception.
76 * @throws Payment_Required_Exception Payment_Required_Exception.
77 * @throws Request_Timeout_Exception Request_Timeout_Exception.
78 * @throws Service_Unavailable_Exception Service_Unavailable_Exception.
79 * @throws Too_Many_Requests_Exception Too_Many_Requests_Exception.
80 * @throws Unauthorized_Exception Unauthorized_Exception.
81 * @throws RuntimeException Unable to retrieve the access token.
82 * @return string[] The suggestions.
83 */
84 public function get_suggestions(
85 WP_User $user,
86 string $suggestion_type,
87 string $prompt_content,
88 string $focus_keyphrase,
89 string $language,
90 string $platform,
91 string $editor
92 ): array {
93 $parameters = new Suggestions_Parameters(
94 $user,
95 $suggestion_type,
96 $prompt_content,
97 $focus_keyphrase,
98 $language,
99 $platform,
100 $editor,
101 );
102
103 try {
104 $sender = $this->ai_request_sender_factory->create( $user );
105 $response = $sender->get_suggestions( $parameters );
106 } catch ( Insufficient_Scope_Exception $exception ) {
107 throw $exception;
108 } catch ( Forbidden_Exception $exception ) {
109 $this->consent_handler->revoke_consent( $user->ID );
110 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
111 throw new Forbidden_Exception( 'CONSENT_REVOKED', $exception->getCode() );
112 }
113
114 return $this->build_suggestions_array( $response )->to_array();
115 }
116
117 // phpcs:enable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
118
119 /**
120 * Generates the list of 5 suggestions to return.
121 *
122 * @param Response $response The response from the API.
123 *
124 * @return Suggestions_Bucket The array of suggestions.
125 */
126 public function build_suggestions_array( Response $response ): Suggestions_Bucket {
127 $suggestions_bucket = new Suggestions_Bucket();
128 $json = \json_decode( $response->get_body() );
129 if ( $json === null || ! isset( $json->choices ) ) {
130 return $suggestions_bucket;
131 }
132 foreach ( $json->choices as $suggestion ) {
133 $suggestions_bucket->add_suggestion( new Suggestion( $suggestion->text ) );
134 }
135
136 return $suggestions_bucket;
137 }
138 }
139