PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 18.3
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v18.3
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 / wincher-client.php

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

133 lines 3.9 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 Yoast\WP\SEO\Exceptions\OAuth\Authentication_Failed_Exception;
6 use Yoast\WP\SEO\Exceptions\OAuth\Tokens\Empty_Property_Exception;
7 use Yoast\WP\SEO\Exceptions\OAuth\Tokens\Empty_Token_Exception;
8 use Yoast\WP\SEO\Helpers\Options_Helper;
9 use Yoast\WP\SEO\Values\OAuth\OAuth_Token;
10 use Yoast\WP\SEO\Wrappers\WP_Remote_Handler;
11 use YoastSEO_Vendor\GuzzleHttp\Client;
12 use YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException;
13
14 /**
15 * Class Wincher_Client
16 */
17 class Wincher_Client extends OAuth_Client {
18
19 /**
20 * The option's key.
21 */
22 const TOKEN_OPTION = 'wincher_tokens';
23
24 /**
25 * Name of the temporary PKCE cookie.
26 */
27 const PKCE_COOKIE_NAME = 'yoast_wincher_pkce';
28
29 /**
30 * The WP_Remote_Handler instance.
31 *
32 * @var WP_Remote_Handler
33 */
34 protected $wp_remote_handler;
35
36 /**
37 * Wincher_Client constructor.
38 *
39 * @param Options_Helper $options_helper The Options_Helper instance.
40 * @param WP_Remote_Handler $wp_remote_handler The request handler.
41 *
42 * @throws Empty_Property_Exception Exception thrown if a token property is empty.
43 */
44 public function __construct(
45 Options_Helper $options_helper,
46 WP_Remote_Handler $wp_remote_handler
47 ) {
48
49 $provider = new Wincher_PKCE_Provider(
50 [
51 'clientId' => 'yoast',
52 'redirectUri' => 'https://auth.wincher.com/yoast/setup',
53 'urlAuthorize' => 'https://auth.wincher.com/connect/authorize',
54 'urlAccessToken' => 'https://auth.wincher.com/connect/token',
55 'urlResourceOwnerDetails' => 'https://api.wincher.com/beta/user',
56 'scopes' => [ 'profile', 'account', 'websites:read', 'websites:write', 'offline_access' ],
57 'scopeSeparator' => ' ',
58 'pkceMethod' => 'S256',
59 ],
60 [
61 'httpClient' => new Client( [ 'handler' => $wp_remote_handler ] ),
62 ]
63 );
64
65 parent::__construct(
66 self::TOKEN_OPTION,
67 $provider,
68 $options_helper
69 );
70 }
71
72 /**
73 * Return the authorization URL.
74 *
75 * @return string The authentication URL.
76 */
77 public function get_authorization_url() {
78 $parsed_site_url = \wp_parse_url( \get_site_url() );
79
80 $url = $this->provider->getAuthorizationUrl(
81 [
82 'state' => \WPSEO_Utils::format_json_encode( [ 'domain' => $parsed_site_url['host'] ] ),
83 ]
84 );
85
86 $pkce_code = $this->provider->getPkceCode();
87
88 // Store a session cookie with the PKCE code that we need in order to
89 // exchange the returned code for a token after authorization.
90 $secure = ! empty( $_SERVER['HTTPS'] );
91 setcookie( self::PKCE_COOKIE_NAME, $pkce_code, 0, '/', '', $secure, true );
92
93 return $url;
94 }
95
96 /**
97 * Requests the access token and refresh token based on the passed code.
98 *
99 * @param string $code The code to send.
100 *
101 * @return OAuth_Token The requested tokens.
102 *
103 * @throws Authentication_Failed_Exception Exception thrown if authentication has failed.
104 */
105 public function request_tokens( $code ) {
106 $pkce_code = ! empty( $_COOKIE[ self::PKCE_COOKIE_NAME ] ) ? \sanitize_text_field( \wp_unslash( $_COOKIE[ self::PKCE_COOKIE_NAME ] ) ) : null;
107 if ( $pkce_code ) {
108 $this->provider->setPkceCode( $pkce_code );
109 }
110 return parent::request_tokens( $code );
111 }
112
113 /**
114 * Performs the specified request.
115 *
116 * @param string $method The HTTP method to use.
117 * @param string $url The URL to send the request to.
118 * @param array $options The options to pass along to the request.
119 *
120 * @return mixed The parsed API response.
121 *
122 * @throws IdentityProviderException Exception thrown if there's something wrong with the identifying data.
123 * @throws Authentication_Failed_Exception Exception thrown if authentication has failed.
124 * @throws Empty_Token_Exception Exception thrown if the token is empty.
125 *
126 * @codeCoverageIgnore
127 */
128 protected function do_request( $method, $url, array $options ) {
129 $options['headers'] = [ 'Content-Type' => 'application/json' ];
130 return parent::do_request( $method, $url, $options );
131 }
132 }
133