PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 19.0
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v19.0
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 / config / oauth-client.php

oauth-client.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 19.0, at src/config/oauth-client.php

261 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yoast\WP\SEO\Config;
4
5 use Exception;
6 use Yoast\WP\SEO\Exceptions\OAuth\Authentication_Failed_Exception;
7 use Yoast\WP\SEO\Exceptions\OAuth\Tokens\Empty_Property_Exception;
8 use Yoast\WP\SEO\Exceptions\OAuth\Tokens\Empty_Token_Exception;
9 use Yoast\WP\SEO\Exceptions\OAuth\Tokens\Failed_Storage_Exception;
10 use Yoast\WP\SEO\Helpers\Options_Helper;
11 use Yoast\WP\SEO\Values\OAuth\OAuth_Token;
12 use YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException;
13 use YoastSEO_Vendor\League\OAuth2\Client\Provider\GenericProvider;
14
15 /**
16 * Class OAuth_Client
17 */
18 abstract class OAuth_Client {
19
20 /**
21 * The option's key.
22 *
23 * @var string
24 */
25 protected $token_option = null;
26
27 /**
28 * The provider.
29 *
30 * @var Wincher_PKCE_Provider|GenericProvider
31 */
32 protected $provider;
33
34 /**
35 * The options helper.
36 *
37 * @var Options_Helper
38 */
39 protected $options_helper;
40
41 /**
42 * The token.
43 *
44 * @var OAuth_Token|null
45 */
46 protected $token = null;
47
48 /**
49 * OAuth_Client constructor.
50 *
51 * @param string $token_option The option's name to save the token as.
52 * @param Wincher_PKCE_Provider|GenericProvider $provider The provider.
53 * @param Options_Helper $options_helper The Options_Helper instance.
54 *
55 * @throws Empty_Property_Exception Exception thrown if a token property is empty.
56 */
57 public function __construct(
58 $token_option,
59 $provider,
60 Options_Helper $options_helper
61 ) {
62 $this->provider = $provider;
63 $this->token_option = $token_option;
64 $this->options_helper = $options_helper;
65
66 $tokens = $this->options_helper->get( $this->token_option );
67
68 if ( ! empty( $tokens ) ) {
69 $this->token = new OAuth_Token(
70 $tokens['access_token'],
71 $tokens['refresh_token'],
72 $tokens['expires'],
73 $tokens['has_expired'],
74 $tokens['created_at']
75 );
76 }
77 }
78
79 /**
80 * Requests the access token and refresh token based on the passed code.
81 *
82 * @param string $code The code to send.
83 *
84 * @return OAuth_Token The requested tokens.
85 *
86 * @throws Authentication_Failed_Exception Exception thrown if authentication has failed.
87 */
88 public function request_tokens( $code ) {
89 try {
90 $response = $this->provider
91 ->getAccessToken(
92 'authorization_code',
93 [
94 'code' => $code,
95 ]
96 );
97
98 $token = OAuth_Token::from_response( $response );
99
100 return $this->store_token( $token );
101 } catch ( Exception $exception ) {
102 throw new Authentication_Failed_Exception( $exception );
103 }
104 }
105
106 /**
107 * Performs an authenticated GET request to the desired URL.
108 *
109 * @param string $url The URL to send the request to.
110 * @param array $options The options to pass along to the request.
111 *
112 * @return mixed The parsed API response.
113 *
114 * @throws IdentityProviderException Exception thrown if there's something wrong with the identifying data.
115 * @throws Authentication_Failed_Exception Exception thrown if authentication has failed.
116 * @throws Empty_Token_Exception Exception thrown if the token is empty.
117 */
118 public function get( $url, $options = [] ) {
119 return $this->do_request( 'GET', $url, $options );
120 }
121
122 /**
123 * Performs an authenticated POST request to the desired URL.
124 *
125 * @param string $url The URL to send the request to.
126 * @param mixed $body The data to send along in the request's body.
127 * @param array $options The options to pass along to the request.
128 *
129 * @return mixed The parsed API response.
130 *
131 * @throws IdentityProviderException Exception thrown if there's something wrong with the identifying data.
132 * @throws Authentication_Failed_Exception Exception thrown if authentication has failed.
133 * @throws Empty_Token_Exception Exception thrown if the token is empty.
134 */
135 public function post( $url, $body, $options = [] ) {
136 $options['body'] = $body;
137
138 return $this->do_request( 'POST', $url, $options );
139 }
140
141 /**
142 * Performs an authenticated DELETE request to the desired URL.
143 *
144 * @param string $url The URL to send the request to.
145 * @param array $options The options to pass along to the request.
146 *
147 * @return mixed The parsed API response.
148 *
149 * @throws IdentityProviderException Exception thrown if there's something wrong with the identifying data.
150 * @throws Authentication_Failed_Exception Exception thrown if authentication has failed.
151 * @throws Empty_Token_Exception Exception thrown if the token is empty.
152 */
153 public function delete( $url, $options = [] ) {
154 return $this->do_request( 'DELETE', $url, $options );
155 }
156
157 /**
158 * Determines whether there are valid tokens available.
159 *
160 * @return bool Whether there are valid tokens.
161 */
162 public function has_valid_tokens() {
163 return ! empty( $this->token ) && $this->token->has_expired() === false;
164 }
165
166 /**
167 * Gets the stored tokens and refreshes them if they've expired.
168 *
169 * @return OAuth_Token The stored tokens.
170 *
171 * @throws Empty_Token_Exception Exception thrown if the token is empty.
172 */
173 public function get_tokens() {
174 if ( empty( $this->token ) ) {
175 throw new Empty_Token_Exception();
176 }
177
178 if ( $this->token->has_expired() ) {
179 $this->token = $this->refresh_tokens( $this->token );
180 }
181
182 return $this->token;
183 }
184
185 /**
186 * Stores the passed token.
187 *
188 * @param OAuth_Token $token The token to store.
189 *
190 * @return OAuth_Token The stored token.
191 *
192 * @throws Failed_Storage_Exception Exception thrown if storing of the token fails.
193 */
194 public function store_token( OAuth_Token $token ) {
195 $saved = $this->options_helper->set( $this->token_option, $token->to_array() );
196
197 if ( $saved === false ) {
198 throw new Failed_Storage_Exception();
199 }
200
201 return $token;
202 }
203
204 /**
205 * Performs the specified request.
206 *
207 * @param string $method The HTTP method to use.
208 * @param string $url The URL to send the request to.
209 * @param array $options The options to pass along to the request.
210 *
211 * @return mixed The parsed API response.
212 *
213 * @throws IdentityProviderException Exception thrown if there's something wrong with the identifying data.
214 * @throws Authentication_Failed_Exception Exception thrown if authentication has failed.
215 * @throws Empty_Token_Exception Exception thrown if the token is empty.
216 */
217 protected function do_request( $method, $url, array $options ) {
218 $defaults = [
219 'headers' => $this->provider->getHeaders( $this->get_tokens()->access_token ),
220 ];
221
222 $options = \array_merge_recursive( $defaults, $options );
223
224 if ( \array_key_exists( 'params', $options ) ) {
225 $url .= '?' . \http_build_query( $options['params'] );
226 unset( $options['params'] );
227 }
228
229 $request = $this->provider
230 ->getAuthenticatedRequest( $method, $url, null, $options );
231
232 return $this->provider->getParsedResponse( $request );
233 }
234
235 /**
236 * Refreshes the outdated tokens.
237 *
238 * @param OAuth_Token $tokens The outdated tokens.
239 *
240 * @return OAuth_Token The refreshed tokens.
241 *
242 * @throws Authentication_Failed_Exception Exception thrown if authentication has failed.
243 */
244 protected function refresh_tokens( OAuth_Token $tokens ) {
245 try {
246 $new_tokens = $this->provider->getAccessToken(
247 'refresh_token',
248 [
249 'refresh_token' => $tokens->refresh_token,
250 ]
251 );
252
253 $token = OAuth_Token::from_response( $new_tokens );
254
255 return $this->store_token( $token );
256 } catch ( Exception $exception ) {
257 throw new Authentication_Failed_Exception( $exception );
258 }
259 }
260 }
261