Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
87.50% |
7 / 8 |
CRAP | |
86.79% |
46 / 53 |
GoogleClient | |
0.00% |
0 / 1 |
|
87.50% |
7 / 8 |
14.18 | |
90.20% |
46 / 51 |
__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% |
8 / 8 |
|||
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 | return self::AUTHORIZE_URL . '?' . http_build_query( |
136 | [ |
137 | 'client_id' => $this->client_id, |
138 | 'redirect_uri' => $this->gt_redirect_url(), |
139 | 'state' => $this->state(), |
140 | 'scope' => 'email profile openid', |
141 | 'access_type' => 'online', |
142 | 'response_type' => 'code', |
143 | ] |
144 | ); |
145 | } |
146 | |
147 | /** |
148 | * Get the access token. |
149 | * |
150 | * @param string $code Response code received during authorization. |
151 | * |
152 | * @return \stdClass |
153 | * @throws Exception For access token errors. |
154 | */ |
155 | public function access_token( string $code ): \stdClass { |
156 | $response = wp_remote_post( |
157 | self::TOKEN_URL, |
158 | [ |
159 | 'headers' => [ |
160 | 'Accept' => 'application/json', |
161 | ], |
162 | 'body' => [ |
163 | 'client_id' => $this->client_id, |
164 | 'client_secret' => $this->client_secret, |
165 | 'redirect_uri' => $this->gt_redirect_url(), |
166 | 'code' => $code, |
167 | 'grant_type' => 'authorization_code', |
168 | ], |
169 | ] |
170 | ); |
171 | |
172 | if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { |
173 | throw new Exception( __( 'Could not retrieve the access token, please try again.', 'login-with-google' ) ); |
174 | } |
175 | |
176 | return json_decode( wp_remote_retrieve_body( $response ) ); |
177 | } |
178 | |
179 | /** |
180 | * Make an API request. |
181 | * |
182 | * @return \stdClass |
183 | * @throws \Throwable Exception during API. |
184 | * @throws Exception API Exception. |
185 | */ |
186 | public function user(): \stdClass { |
187 | try { |
188 | //phpcs:disable WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get |
189 | $user = wp_remote_get( |
190 | trailingslashit( self::API_BASE ) . 'oauth2/v2/userinfo?access_token=' . $this->access_token, |
191 | [ |
192 | 'headers' => [ |
193 | 'Accept' => 'application/json', |
194 | ], |
195 | ] |
196 | ); |
197 | |
198 | if ( 200 !== wp_remote_retrieve_response_code( $user ) ) { |
199 | throw new Exception( __( 'Could not retrieve the user information, please try again.', 'login-with-google' ) ); |
200 | } |
201 | |
202 | return json_decode( wp_remote_retrieve_body( $user ) ); |
203 | |
204 | } catch ( \Throwable $e ) { |
205 | |
206 | throw $e; |
207 | } |
208 | } |
209 | |
210 | /** |
211 | * State to pass in GH API. |
212 | * |
213 | * @return string |
214 | */ |
215 | public function state(): string { |
216 | $state_data['nonce'] = wp_create_nonce( 'login_with_google' ); |
217 | $state_data = apply_filters( 'rtcamp.google_login_state', $state_data ); |
218 | $state_data['provider'] = 'google'; |
219 | |
220 | return base64_encode( wp_json_encode( $state_data ) ); |
221 | } |
222 | |
223 | } |