PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 18.4
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v18.4
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.4, at src/config/wincher-client.php

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