Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
87.50% |
7 / 8 |
CRAP | |
88.33% |
53 / 60 |
GoogleClient | |
0.00% |
0 / 1 |
|
87.50% |
7 / 8 |
14.13 | |
91.38% |
53 / 58 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
5 / 5 |
|||
__call | |
100.00% |
1 / 1 |
3 | |
100.00% |
5 / 5 |
|||
set_access_token | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
gt_redirect_url | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
authorization_url | |
100.00% |
1 / 1 |
1 | |
100.00% |
15 / 15 |
|||
access_token | |
100.00% |
1 / 1 |
2 | |
100.00% |
12 / 12 |
|||
user | |
100.00% |
1 / 1 |
3 | |
100.00% |
9 / 9 |
|||
state | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
1 | <?php |
2 | /** |
3 | * Google API Client. |
4 | * |
5 | * Useful for authenticating the user and other API related operations. |
6 | * |
7 | * @package RtCamp\GoogleLogin |
8 | * @since 1.0.0 |
9 | */ |
10 | |
11 | declare(strict_types=1); |
12 | |
13 | namespace RtCamp\GoogleLogin\Utils; |
14 | |
15 | use Exception; |
16 | |
17 | /** |
18 | * Class GoogleClient |
19 | * |
20 | * @package RtCamp\GoogleLogin\Utils |
21 | */ |
22 | class GoogleClient { |
23 | /** |
24 | * Authorization URL. |
25 | * |
26 | * @var string |
27 | */ |
28 | const AUTHORIZE_URL = 'https://accounts.google.com/o/oauth2/auth'; |
29 | |
30 | /** |
31 | * Access Token URL. |
32 | * |
33 | * @var string |
34 | */ |
35 | const TOKEN_URL = 'https://oauth2.googleapis.com/token'; |
36 | |
37 | /** |
38 | * API base for google. |
39 | * |
40 | * @var string |
41 | */ |
42 | const API_BASE = 'https://www.googleapis.com'; |
43 | |
44 | /** |
45 | * Client ID. |
46 | * |
47 | * @var string |
48 | */ |
49 | public $client_id; |
50 | |
51 | /** |
52 | * Client secret. |
53 | * |
54 | * @var string |
55 | */ |
56 | public $client_secret; |
57 | |
58 | /** |
59 | * Redirect URI. |
60 | * |
61 | * @var string |
62 | */ |
63 | public $redirect_uri; |
64 | |
65 | /** |
66 | * Access token. |
67 | * |
68 | * @var string |
69 | */ |
70 | private $access_token; |
71 | |
72 | /** |
73 | * GoogleClient constructor. |
74 | * |
75 | * @param array $config Configuration for client. |
76 | */ |
77 | public function __construct( array $config ) { |
78 | $this->client_id = $config['client_id'] ?? ''; |
79 | $this->client_secret = $config['client_secret'] ?? ''; |
80 | $this->redirect_uri = $config['redirect_uri'] ?? ''; |
81 | } |
82 | |
83 | /** |
84 | * Check if access token is set before calling API methods. |
85 | * |
86 | * @param string $name Name of method called. |
87 | * @param mixed $args Arguments for method. |
88 | * |
89 | * @throws Exception Empty access token. |
90 | */ |
91 | public function __call( string $name, $args ) { |
92 | $methods = [ |
93 | 'user', |
94 | 'emails', |
95 | ]; |
96 | |
97 | if ( in_array( $name, $methods, true ) && empty( $this->access_token ) ) { |
98 | throw new Exception( __( 'Access token must be set to make this API call', 'login-with-google' ) ); |
99 | } |
100 | } |
101 | |
102 | /** |
103 | * Set access token. |
104 | * |
105 | * @param string $code Token. |
106 | * |
107 | * @return self |
108 | * @throws \Throwable Exception for fetching access token. |
109 | */ |
110 | public function set_access_token( string $code ): self { |
111 | try { |
112 | $this->access_token = $this->access_token( $code )->access_token; |
113 | |
114 | return $this; |
115 | } catch ( \Throwable $e ) { |
116 | throw $e; |
117 | } |
118 | } |
119 | |
120 | /** |
121 | * Return redirect url. |
122 | * |
123 | * @return string |
124 | */ |
125 | public function gt_redirect_url(): string { |
126 | return apply_filters( 'rtcamp.google_redirect_url', $this->redirect_uri ); |
127 | } |
128 | |
129 | /** |
130 | * Get the authorize URL |
131 | * |
132 | * @return string |
133 | */ |
134 | public function authorization_url(): string { |
135 | $plugin_scope = [ |
136 | 'email', |
137 | 'profile', |
138 | 'openid', |
139 | ]; |
140 | |
141 | $scope = apply_filters_deprecated( |
142 | 'wp_google_login_scopes', |
143 | [ |
144 | $plugin_scope |
145 | ], |
146 | '1.0.15', |
147 | 'rtcamp.google_scope' |
148 | ); |
149 | |
150 | $scope = apply_filters( 'rtcamp.google_scope', $scope ); |
151 | |
152 | return self::AUTHORIZE_URL . '?' . http_build_query( |
153 | [ |
154 | 'client_id' => $this->client_id, |
155 | 'redirect_uri' => $this->gt_redirect_url(), |
156 | 'state' => $this->state(), |
157 | 'scope' => implode( ' ', $scope ), |
158 | 'access_type' => 'online', |
159 | 'response_type' => 'code', |
160 | ] |
161 | ); |
162 | } |
163 | |
164 | /** |
165 | * Get the access token. |
166 | * |
167 | * @param string $code Response code received during authorization. |
168 | * |
169 | * @return \stdClass |
170 | * @throws Exception For access token errors. |
171 | */ |
172 | public function access_token( string $code ): \stdClass { |
173 | $response = wp_remote_post( |
174 | self::TOKEN_URL, |
175 | [ |
176 | 'headers' => [ |
177 | 'Accept' => 'application/json', |
178 | ], |
179 | 'body' => [ |
180 | 'client_id' => $this->client_id, |
181 | 'client_secret' => $this->client_secret, |
182 | 'redirect_uri' => $this->gt_redirect_url(), |
183 | 'code' => $code, |
184 | 'grant_type' => 'authorization_code', |
185 | ], |
186 | ] |
187 | ); |
188 | |
189 | if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { |
190 | throw new Exception( __( 'Could not retrieve the access token, please try again.', 'login-with-google' ) ); |
191 | } |
192 | |
193 | return json_decode( wp_remote_retrieve_body( $response ) ); |
194 | } |
195 | |
196 | /** |
197 | * Make an API request. |
198 | * |
199 | * @return \stdClass |
200 | * @throws \Throwable Exception during API. |
201 | * @throws Exception API Exception. |
202 | */ |
203 | public function user(): \stdClass { |
204 | try { |
205 | //phpcs:disable WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get |
206 | $user = wp_remote_get( |
207 | trailingslashit( self::API_BASE ) . 'oauth2/v2/userinfo?access_token=' . $this->access_token, |
208 | [ |
209 | 'headers' => [ |
210 | 'Accept' => 'application/json', |
211 | ], |
212 | ] |
213 | ); |
214 | |
215 | if ( 200 !== wp_remote_retrieve_response_code( $user ) ) { |
216 | throw new Exception( __( 'Could not retrieve the user information, please try again.', 'login-with-google' ) ); |
217 | } |
218 | |
219 | return json_decode( wp_remote_retrieve_body( $user ) ); |
220 | |
221 | } catch ( \Throwable $e ) { |
222 | |
223 | throw $e; |
224 | } |
225 | } |
226 | |
227 | /** |
228 | * State to pass in GH API. |
229 | * |
230 | * @return string |
231 | */ |
232 | public function state(): string { |
233 | $state_data['nonce'] = wp_create_nonce( 'login_with_google' ); |
234 | $state_data = apply_filters( 'rtcamp.google_login_state', $state_data ); |
235 | $state_data['provider'] = 'google'; |
236 | |
237 | return base64_encode( wp_json_encode( $state_data ) ); |
238 | } |
239 | |
240 | } |