| Total Complexity | 60 | 
| Total Lines | 567 | 
| Duplicated Lines | 0 % | 
| Changes | 0 | ||
Complex classes like GClient often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use GClient, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 25 | class GClient  | 
            ||
| 26 | {
 | 
            ||
| 27 | /** GET request */  | 
            ||
| 28 | public const GET = 0;  | 
            ||
| 29 | /** POST request */  | 
            ||
| 30 | public const POST = 1;  | 
            ||
| 31 | /** PUT request */  | 
            ||
| 32 | public const PUT = 2;  | 
            ||
| 33 | /** PATCH request */  | 
            ||
| 34 | public const PATCH = 3;  | 
            ||
| 35 | /** DELETE request */  | 
            ||
| 36 | public const DELETE = 4;  | 
            ||
| 37 | |||
| 38 | /** Default endpoint for the google OAuth2 authentication */  | 
            ||
| 39 | protected const DEF_AUTH_URI = 'https://accounts.google.com/o/oauth2/auth';  | 
            ||
| 40 | /** Default endpoint to request access/refresh tokens */  | 
            ||
| 41 | protected const DEF_TOKEN_URI = 'https://oauth2.googleapis.com/token';  | 
            ||
| 42 | |||
| 43 | /** @var string client-ID of the google cloud project */  | 
            ||
| 44 | protected string $strProjectID = '';  | 
            ||
| 45 | /** @var string client-ID within the google cloud project */  | 
            ||
| 46 | protected string $strClientID = '';  | 
            ||
| 47 | /** @var string Endpoint for the google OAuth2 authentication */  | 
            ||
| 48 | protected string $strAuthURI = '';  | 
            ||
| 49 | /** @var string Endpoint to request access/refresh tokens */  | 
            ||
| 50 | protected string $strTokenURI = '';  | 
            ||
| 51 | /** @var string client secret for authentication */  | 
            ||
| 52 | protected string $strClientSecret = '';  | 
            ||
| 53 | /** @var string redirect URI configured for the client */  | 
            ||
| 54 | protected string $strRedirectURI = '';  | 
            ||
| 55 | /** @var array<string> requested scope */  | 
            ||
| 56 | protected array $aScope = [];  | 
            ||
| 57 | /** @var array<mixed> received access token */  | 
            ||
| 58 | protected array $aAccessToken = [];  | 
            ||
| 59 | /** @var string received refresh token */  | 
            ||
| 60 | protected string $strRefreshToken = '';  | 
            ||
| 61 | |||
| 62 | /** @var int response code of the latest HTTP request */  | 
            ||
| 63 | protected int $iLastResponseCode = 0;  | 
            ||
| 64 | /** @var string error description if the latest HTTP request has failed */  | 
            ||
| 65 | protected string $strLastError = '';  | 
            ||
| 66 | /** @var string status if the latest HTTP request has failed */  | 
            ||
| 67 | protected string $strLastStatus = '';  | 
            ||
| 68 | |||
| 69 | /** @var LoggerInterface loger */  | 
            ||
| 70 | protected LoggerInterface $oLogger;  | 
            ||
| 71 | |||
| 72 | /**  | 
            ||
| 73 | * @param LoggerInterface $oLogger  | 
            ||
| 74 | */  | 
            ||
| 75 | public function __construct(LoggerInterface $oLogger = null)  | 
            ||
| 76 |     {
 | 
            ||
| 77 | // ensure we have a valid logger instance  | 
            ||
| 78 | $this->oLogger = $oLogger ?? new NullLogger();  | 
            ||
| 79 | $this->strAuthURI = self::DEF_AUTH_URI;  | 
            ||
| 80 | $this->strTokenURI = self::DEF_TOKEN_URI;  | 
            ||
| 81 | }  | 
            ||
| 82 | |||
| 83 | /**  | 
            ||
| 84 | * Set the OAuth2 client configuration from the google API console.  | 
            ||
| 85 | * The method tries to extract  | 
            ||
| 86 | * - $strClientID  | 
            ||
| 87 | * - $strProjectID  | 
            ||
| 88 | * - $strAuthURI  | 
            ||
| 89 | * - $strTokenURI  | 
            ||
| 90 | * - $strClientSecret  | 
            ||
| 91 | * - $strRedirectURI  | 
            ||
| 92 | * from the JSON config file.  | 
            ||
| 93 | * @param string $strClientSecrets filename  | 
            ||
| 94 | */  | 
            ||
| 95 | public function setOAuthClient(string $strClientSecrets) : void  | 
            ||
| 96 |     {
 | 
            ||
| 97 |         if (file_exists($strClientSecrets)) {
 | 
            ||
| 98 | $strOAuthClient = file_get_contents($strClientSecrets);  | 
            ||
| 99 | $aOAuthClient = json_decode($strOAuthClient, true);  | 
            ||
| 100 |             if ($aOAuthClient !== null && (isset($aOAuthClient['web']) || isset($aOAuthClient['installed']))) {
 | 
            ||
| 101 | $aData = $aOAuthClient['web'] ?? $aOAuthClient['installed'];  | 
            ||
| 102 | $this->strClientID = $aData['client_id'] ?? '';  | 
            ||
| 103 | $this->strProjectID = $aData['project_id'] ?? '';  | 
            ||
| 104 | $this->strAuthURI = $aData['auth_uri'] ?? '';  | 
            ||
| 105 | $this->strTokenURI = $aData['token_uri'] ?? '';  | 
            ||
| 106 | $this->strClientSecret = $aData['client_secret'] ?? '';  | 
            ||
| 107 |                 if (isset($aData['redirect_uris']) and is_array($aData['redirect_uris'])) {
 | 
            ||
| 108 | $this->strRedirectURI = $aData['redirect_uris'][0];  | 
            ||
| 109 | }  | 
            ||
| 110 |             } else {
 | 
            ||
| 111 |                 throw new MissingClientInformationException('No valid client informations from google API console available.');
 | 
            ||
| 112 | }  | 
            ||
| 113 |         } else {
 | 
            ||
| 114 |             throw new MissingClientInformationException('Client secrets file [' . $strClientSecrets . '] not found!');
 | 
            ||
| 115 | }  | 
            ||
| 116 | }  | 
            ||
| 117 | |||
| 118 | /**  | 
            ||
| 119 | * Build the URL to call the google OAuth2.  | 
            ||
| 120 | * Description for the $strLoginHint param from google docs: <br/>  | 
            ||
| 121 | * > When your application knows which user it is trying to authenticate, it may provide  | 
            ||
| 122 | * > this parameter as a hint to the Authentication Server. Passing this hint will either  | 
            ||
| 123 | * > pre-fill the email box on the sign-in form or select the proper multi-login session,  | 
            ||
| 124 | * > thereby simplifying the login flow.  | 
            ||
| 125 | * @param string $strLoginHint an **existing** google account to preselect in the login form.  | 
            ||
| 126 | * @throws MissingPropertyException  | 
            ||
| 127 | * @return string  | 
            ||
| 128 | */  | 
            ||
| 129 | public function buildAuthURL(string $strLoginHint = '') : string  | 
            ||
| 130 |     {
 | 
            ||
| 131 | $this->checkProperty($this->strAuthURI, 'auth_uri');  | 
            ||
| 132 | $this->checkProperty($this->strClientID, 'client_id');  | 
            ||
| 133 | $this->checkProperty($this->strRedirectURI, 'redirect_uri');  | 
            ||
| 134 |         if (count($this->aScope) < 1) {
 | 
            ||
| 135 |             throw new MissingPropertyException('The scope must be specified before call this method!');
 | 
            ||
| 136 | }  | 
            ||
| 137 | $aLoginParams = [  | 
            ||
| 138 | 'response_type' => 'code',  | 
            ||
| 139 | 'access_type' => 'offline',  | 
            ||
| 140 | 'redirect_uri' => $this->strRedirectURI,  | 
            ||
| 141 | 'client_id' => $this->strClientID,  | 
            ||
| 142 |             'scope' => implode(' ', $this->aScope),
 | 
            ||
| 143 | 'prompt' => 'consent',  | 
            ||
| 144 | 'include_granted_scopes' => 'true',  | 
            ||
| 145 | ];  | 
            ||
| 146 |         if (!empty($strLoginHint)) {
 | 
            ||
| 147 | $aLoginParams['login_hint'] = $strLoginHint;  | 
            ||
| 148 | }  | 
            ||
| 149 |         $this->oLogger->info('GClient: succesfully build auth URL');
 | 
            ||
| 150 | return $this->strAuthURI . '?' . http_build_query($aLoginParams);  | 
            ||
| 151 | }  | 
            ||
| 152 | |||
| 153 | /**  | 
            ||
| 154 | * Send request to get access and refresh token from a passed auth code.  | 
            ||
| 155 | * @param string $strAuthCode the code passed from accounts.google.com  | 
            ||
| 156 | * @throws MissingPropertyException  | 
            ||
| 157 | * @return bool  | 
            ||
| 158 | */  | 
            ||
| 159 | public function fetchTokens(string $strAuthCode) : bool  | 
            ||
| 160 |     {
 | 
            ||
| 161 | $this->checkProperty($strAuthCode, 'auth code');  | 
            ||
| 162 | $this->checkProperty($this->strClientID, 'client_id');  | 
            ||
| 163 | $this->checkProperty($this->strClientSecret, 'client_secret');  | 
            ||
| 164 | $this->checkProperty($this->strTokenURI, 'token_uri');  | 
            ||
| 165 | $this->checkProperty($this->strRedirectURI, 'redirect_uri');  | 
            ||
| 166 | |||
| 167 | $aData = [  | 
            ||
| 168 | 'grant_type' => 'authorization_code',  | 
            ||
| 169 | 'code' => $strAuthCode,  | 
            ||
| 170 | 'redirect_uri' => $this->strRedirectURI,  | 
            ||
| 171 | 'client_id' => $this->strClientID,  | 
            ||
| 172 | 'client_secret' => $this->strClientSecret,  | 
            ||
| 173 | ];  | 
            ||
| 174 | |||
| 175 | $aHeader = array(  | 
            ||
| 176 | 'Host' => $this->strTokenURI,  | 
            ||
| 177 | 'Cache-Control' => 'no-store',  | 
            ||
| 178 | 'Content-Type' => 'application/x-www-form-urlencoded',  | 
            ||
| 179 | );  | 
            ||
| 180 | |||
| 181 | // since the request only provides an 'expires in' value, we have to keep  | 
            ||
| 182 | // track of the timestamp, we sent the request  | 
            ||
| 183 | $timeRequest = time();  | 
            ||
| 184 | |||
| 185 | $data = http_build_query($aData);  | 
            ||
| 186 |         if (($strResponse = $this->fetchJsonResponse($this->strTokenURI, self::POST, $aHeader, $data)) !== false) {
 | 
            ||
| 187 | // the body contains the access- and refresh token  | 
            ||
| 188 | $this->aAccessToken = json_decode($strResponse, true);  | 
            ||
| 189 | $this->aAccessToken['created'] = $timeRequest;  | 
            ||
| 190 | $this->strRefreshToken = $this->aAccessToken['refresh_token'] ?? '';  | 
            ||
| 191 | unset($this->aAccessToken['refresh_token']);  | 
            ||
| 192 |             $this->oLogger->info('GClient: succesfully fetched access token from auth code');
 | 
            ||
| 193 |         } else {
 | 
            ||
| 194 | $this->aAccessToken = [];  | 
            ||
| 195 | $this->strRefreshToken = '';  | 
            ||
| 196 | $this->oLogger->error(  | 
            ||
| 197 | 'GClient: error fetching access token from auth code', [  | 
            ||
| 198 | 'responsecode' => $this->iLastResponseCode,  | 
            ||
| 199 | 'authorization_code' => $strAuthCode,  | 
            ||
| 200 | ]  | 
            ||
| 201 | );  | 
            ||
| 202 | }  | 
            ||
| 203 | return count($this->aAccessToken) > 0;  | 
            ||
| 204 | }  | 
            ||
| 205 | |||
| 206 | /**  | 
            ||
| 207 | * Refresh expired access token.  | 
            ||
| 208 | * @param string $strRefreshToken  | 
            ||
| 209 | * @throws MissingPropertyException  | 
            ||
| 210 | * @return array<mixed> new access token  | 
            ||
| 211 | */  | 
            ||
| 212 | public function refreshAccessToken(string $strRefreshToken) : array  | 
            ||
| 213 |     {
 | 
            ||
| 214 | $this->checkProperty($strRefreshToken, 'refresh_token');  | 
            ||
| 215 | $this->checkProperty($this->strClientID, 'client_id');  | 
            ||
| 216 | $this->checkProperty($this->strClientSecret, 'client_secret');  | 
            ||
| 217 | $this->checkProperty($this->strTokenURI, 'token_uri');  | 
            ||
| 218 | $this->checkProperty($this->strRedirectURI, 'redirect_uri');  | 
            ||
| 219 | |||
| 220 | $aData = [  | 
            ||
| 221 | 'grant_type' => 'refresh_token',  | 
            ||
| 222 | 'refresh_token' => $strRefreshToken,  | 
            ||
| 223 | 'client_id' => $this->strClientID,  | 
            ||
| 224 | 'client_secret' => $this->strClientSecret,  | 
            ||
| 225 | ];  | 
            ||
| 226 | |||
| 227 | $aHeader = array(  | 
            ||
| 228 | 'Host' => $this->strTokenURI,  | 
            ||
| 229 | 'Cache-Control' => 'no-store',  | 
            ||
| 230 | 'Content-Type' => 'application/x-www-form-urlencoded',  | 
            ||
| 231 | );  | 
            ||
| 232 | |||
| 233 | // since the request only provides an 'expires in' value, we have to keep  | 
            ||
| 234 | // track of the timestamp, we sent the request  | 
            ||
| 235 | $timeRequest = time();  | 
            ||
| 236 | |||
| 237 | $data = http_build_query($aData);  | 
            ||
| 238 |         if (($strResponse = $this->fetchJsonResponse($this->strTokenURI, self::POST, $aHeader, $data)) !== false) {
 | 
            ||
| 239 | // the body contains the access- and refresh token  | 
            ||
| 240 | $this->aAccessToken = json_decode($strResponse, true);  | 
            ||
| 241 | $this->aAccessToken['created'] = $timeRequest;  | 
            ||
| 242 |             $this->oLogger->info('GClient: succesfully refreshed access token');
 | 
            ||
| 243 |         } else {
 | 
            ||
| 244 | $this->aAccessToken = [];  | 
            ||
| 245 | $this->strRefreshToken = '';  | 
            ||
| 246 | $this->oLogger->error(  | 
            ||
| 247 | 'GClient: error refreshing access token', [  | 
            ||
| 248 | 'responsecode' => $this->iLastResponseCode,  | 
            ||
| 249 | 'refresh_token' => $strRefreshToken,  | 
            ||
| 250 | ]  | 
            ||
| 251 | );  | 
            ||
| 252 | }  | 
            ||
| 253 | return $this->aAccessToken;  | 
            ||
| 254 | }  | 
            ||
| 255 | |||
| 256 | /**  | 
            ||
| 257 | * The current set access token.  | 
            ||
| 258 | * @return array<mixed>  | 
            ||
| 259 | */  | 
            ||
| 260 | public function getAccessToken() : array  | 
            ||
| 261 |     {
 | 
            ||
| 262 | return $this->aAccessToken;  | 
            ||
| 263 | }  | 
            ||
| 264 | |||
| 265 | /**  | 
            ||
| 266 | * Set a saved access token.  | 
            ||
| 267 | * @param string|array<mixed> $token accesstoken as string (JSON) or array  | 
            ||
| 268 | */  | 
            ||
| 269 | public function setAccessToken($token) : void  | 
            ||
| 270 |     {
 | 
            ||
| 271 |         if (is_array($token)) {
 | 
            ||
| 272 | $this->aAccessToken = $token;  | 
            ||
| 273 |         } else {
 | 
            ||
| 274 | $aToken = json_decode($token, true);  | 
            ||
| 275 |             if (is_array($aToken)) {
 | 
            ||
| 276 | $this->aAccessToken = $aToken;  | 
            ||
| 277 |             } else {
 | 
            ||
| 278 | $this->aAccessToken = [];  | 
            ||
| 279 | }  | 
            ||
| 280 | }  | 
            ||
| 281 | }  | 
            ||
| 282 | |||
| 283 | /**  | 
            ||
| 284 | * Check, if the actual set access token has expired.  | 
            ||
| 285 | * It is recommended to set an offset to give time for the execution of  | 
            ||
| 286 | * the next request.  | 
            ||
| 287 | * @param int $iOffset additional offset until 'real' expiration  | 
            ||
| 288 | * @return bool  | 
            ||
| 289 | */  | 
            ||
| 290 | public function isAccessTokenExpired(int $iOffset = 20) : bool  | 
            ||
| 291 |     {
 | 
            ||
| 292 | $bExpired = true;  | 
            ||
| 293 |         if (isset($this->aAccessToken['expires_in']) && isset($this->aAccessToken['created'])) {
 | 
            ||
| 294 | $bExpired = time() > $this->aAccessToken['created'] + $this->aAccessToken['expires_in'] + $iOffset;  | 
            ||
| 295 | }  | 
            ||
| 296 | return $bExpired;  | 
            ||
| 297 | }  | 
            ||
| 298 | |||
| 299 | /**  | 
            ||
| 300 | * Response code of the last API request.  | 
            ||
| 301 | * @return int  | 
            ||
| 302 | */  | 
            ||
| 303 | public function getLastResponseCode() : int  | 
            ||
| 304 |     {
 | 
            ||
| 305 | return $this->iLastResponseCode;  | 
            ||
| 306 | }  | 
            ||
| 307 | |||
| 308 | /**  | 
            ||
| 309 | * Error text if the last API request has failed.  | 
            ||
| 310 | * @return string  | 
            ||
| 311 | */  | 
            ||
| 312 | public function getLastError() : string  | 
            ||
| 313 |     {
 | 
            ||
| 314 | return $this->strLastError;  | 
            ||
| 315 | }  | 
            ||
| 316 | |||
| 317 | /**  | 
            ||
| 318 | * Status if the last API request has failed.  | 
            ||
| 319 | * @return string  | 
            ||
| 320 | */  | 
            ||
| 321 | public function getLastStatus() : string  | 
            ||
| 322 |     {
 | 
            ||
| 323 | return $this->strLastStatus;  | 
            ||
| 324 | }  | 
            ||
| 325 | |||
| 326 | /**  | 
            ||
| 327 | * Get the OAuth HTTP header for API requests.  | 
            ||
| 328 | * @return string  | 
            ||
| 329 | */  | 
            ||
| 330 | public function getAuthHeader() : string  | 
            ||
| 331 |     {
 | 
            ||
| 332 | return 'Authorization: ' . $this->aAccessToken['token_type'] . ' ' . $this->aAccessToken['access_token'];  | 
            ||
| 333 | }  | 
            ||
| 334 | |||
| 335 | /**  | 
            ||
| 336 | * Getter for the current refresh token.  | 
            ||
| 337 | * @return string  | 
            ||
| 338 | */  | 
            ||
| 339 | public function getRefreshToken() : string  | 
            ||
| 340 |     {
 | 
            ||
| 341 | return $this->strRefreshToken;  | 
            ||
| 342 | }  | 
            ||
| 343 | |||
| 344 | /**  | 
            ||
| 345 | * Getter for the current client ID.  | 
            ||
| 346 | * @return string  | 
            ||
| 347 | */  | 
            ||
| 348 | public function getClientID() : string  | 
            ||
| 349 |     {
 | 
            ||
| 350 | return $this->strClientID;  | 
            ||
| 351 | }  | 
            ||
| 352 | |||
| 353 | /**  | 
            ||
| 354 | * Getter for the current project ID.  | 
            ||
| 355 | * @return string  | 
            ||
| 356 | */  | 
            ||
| 357 | public function getProjectID() : string  | 
            ||
| 358 |     {
 | 
            ||
| 359 | return $this->strProjectID;  | 
            ||
| 360 | }  | 
            ||
| 361 | |||
| 362 | /**  | 
            ||
| 363 | * Getter for the current auth URI.  | 
            ||
| 364 | * @return string  | 
            ||
| 365 | */  | 
            ||
| 366 | public function getAuthURI() : string  | 
            ||
| 367 |     {
 | 
            ||
| 368 | return $this->strAuthURI;  | 
            ||
| 369 | }  | 
            ||
| 370 | |||
| 371 | /**  | 
            ||
| 372 | * Getter for the current token URI.  | 
            ||
| 373 | * @return string  | 
            ||
| 374 | */  | 
            ||
| 375 | public function getTokenURI() : string  | 
            ||
| 376 |     {
 | 
            ||
| 377 | return $this->strTokenURI;  | 
            ||
| 378 | }  | 
            ||
| 379 | |||
| 380 | /**  | 
            ||
| 381 | * Getter for the current client secret.  | 
            ||
| 382 | * @return string  | 
            ||
| 383 | */  | 
            ||
| 384 | public function getClientSecret() : string  | 
            ||
| 385 |     {
 | 
            ||
| 386 | return $this->strClientSecret;  | 
            ||
| 387 | }  | 
            ||
| 388 | |||
| 389 | /**  | 
            ||
| 390 | * Getter for the current redirect URI.  | 
            ||
| 391 | * @return string  | 
            ||
| 392 | */  | 
            ||
| 393 | public function getRedirectURI() : string  | 
            ||
| 396 | }  | 
            ||
| 397 | |||
| 398 | /**  | 
            ||
| 399 | * Set the current client ID.  | 
            ||
| 400 | * @param string $strClientID  | 
            ||
| 401 | */  | 
            ||
| 402 | public function setClientID(string $strClientID) : void  | 
            ||
| 403 |     {
 | 
            ||
| 404 | $this->strClientID = $strClientID;  | 
            ||
| 405 | }  | 
            ||
| 406 | |||
| 407 | /**  | 
            ||
| 408 | * Set the current project ID.  | 
            ||
| 409 | * @param string $strProjectID  | 
            ||
| 410 | */  | 
            ||
| 411 | public function setProjectID(string $strProjectID) : void  | 
            ||
| 412 |     {
 | 
            ||
| 413 | $this->strProjectID = $strProjectID;  | 
            ||
| 414 | }  | 
            ||
| 415 | |||
| 416 | /**  | 
            ||
| 417 | * Set the current auth URI.  | 
            ||
| 418 | * @param string $strAuthURI  | 
            ||
| 419 | */  | 
            ||
| 420 | public function setAuthURI(string $strAuthURI) : void  | 
            ||
| 421 |     {
 | 
            ||
| 422 | $this->strAuthURI = $strAuthURI;  | 
            ||
| 423 | }  | 
            ||
| 424 | |||
| 425 | /**  | 
            ||
| 426 | * Set the current token URI.  | 
            ||
| 427 | * @param string $strTokenURI  | 
            ||
| 428 | */  | 
            ||
| 429 | public function setTokenURI(string $strTokenURI) : void  | 
            ||
| 430 |     {
 | 
            ||
| 431 | $this->strTokenURI = $strTokenURI;  | 
            ||
| 432 | }  | 
            ||
| 433 | |||
| 434 | /**  | 
            ||
| 435 | * Set the current client secret.  | 
            ||
| 436 | * @param string $strClientSecret  | 
            ||
| 437 | */  | 
            ||
| 438 | public function setClientSecret(string $strClientSecret) : void  | 
            ||
| 441 | }  | 
            ||
| 442 | |||
| 443 | /**  | 
            ||
| 444 | * Set the current redirect URI.  | 
            ||
| 445 | * @param string $strRedirectURI  | 
            ||
| 446 | */  | 
            ||
| 447 | public function setRedirectURI(string $strRedirectURI) : void  | 
            ||
| 448 |     {
 | 
            ||
| 449 | $this->strRedirectURI = $strRedirectURI;  | 
            ||
| 450 | }  | 
            ||
| 451 | |||
| 452 | /**  | 
            ||
| 453 | * Add scope that is neede for following API requests.  | 
            ||
| 454 | * @param string|array<string> $scope  | 
            ||
| 455 | */  | 
            ||
| 456 | public function addScope($scope) : void  | 
            ||
| 457 |     {
 | 
            ||
| 458 |         if (is_array($scope)) {
 | 
            ||
| 459 | $this->aScope = array_merge($this->aScope, $scope);  | 
            ||
| 460 |         } else if (!in_array($scope, $this->aScope)) {
 | 
            ||
| 461 | $this->aScope[] = $scope;  | 
            ||
| 462 | }  | 
            ||
| 463 | }  | 
            ||
| 464 | |||
| 465 | /**  | 
            ||
| 466 | * Set a logger instance.  | 
            ||
| 467 | * @param \Psr\Log\LoggerInterface $oLogger  | 
            ||
| 468 | */  | 
            ||
| 469 | public function setLogger(LoggerInterface $oLogger) : void  | 
            ||
| 470 |     {
 | 
            ||
| 471 | $this->oLogger = $oLogger;  | 
            ||
| 472 | }  | 
            ||
| 473 | |||
| 474 | /**  | 
            ||
| 475 | * Cleint request to the API.  | 
            ||
| 476 | * @param string $strURI  | 
            ||
| 477 | * @param int $iMethod  | 
            ||
| 478 | * @param array<string> $aHeader  | 
            ||
| 479 | * @param string $data  | 
            ||
| 480 | * @return string|false  | 
            ||
| 481 | */  | 
            ||
| 482 | public function fetchJsonResponse(string $strURI, int $iMethod, array $aHeader = [], string $data = '')  | 
            ||
| 483 |     {
 | 
            ||
| 484 | $result = false;  | 
            ||
| 485 | |||
| 486 | $curl = curl_init();  | 
            ||
| 487 | |||
| 488 | curl_setopt($curl, CURLOPT_URL, $strURI);  | 
            ||
| 489 |         switch ($iMethod) {
 | 
            ||
| 490 | case self::POST:  | 
            ||
| 491 | curl_setopt($curl, CURLOPT_POST, true);  | 
            ||
| 492 | break;  | 
            ||
| 493 | case self::PUT:  | 
            ||
| 494 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');  | 
            ||
| 495 | break;  | 
            ||
| 496 | case self::PATCH:  | 
            ||
| 497 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH');  | 
            ||
| 498 | break;  | 
            ||
| 499 | case self::DELETE:  | 
            ||
| 500 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');  | 
            ||
| 501 | break;  | 
            ||
| 502 | }  | 
            ||
| 503 |         if (!empty($data)) {
 | 
            ||
| 504 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data);  | 
            ||
| 505 | }  | 
            ||
| 506 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);  | 
            ||
| 507 | curl_setopt($curl, CURLOPT_USERAGENT, 'PHP cURL Http Request');  | 
            ||
| 508 | curl_setopt($curl, CURLOPT_HTTPHEADER, $aHeader);  | 
            ||
| 509 | curl_setopt($curl, CURLOPT_HEADER, true);  | 
            ||
| 510 | |||
| 511 | $strResponse = curl_exec($curl);  | 
            ||
| 512 | |||
| 513 | $this->iLastResponseCode = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);  | 
            ||
| 514 | $iHeaderSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);  | 
            ||
| 515 | |||
| 516 | curl_close($curl);  | 
            ||
| 517 | |||
| 518 |         if ($this->iLastResponseCode == 200) {
 | 
            ||
| 519 | $this->strLastError = '';  | 
            ||
| 520 | $this->strLastStatus = '';  | 
            ||
| 521 | $result = is_string($strResponse) ? substr($strResponse, $iHeaderSize) : '';  | 
            ||
| 522 |         } else {
 | 
            ||
| 523 | $strError = is_string($strResponse) ? substr($strResponse, $iHeaderSize) : '';  | 
            ||
| 524 |             if (strlen($strError) > 0)  {
 | 
            ||
| 525 | $aError = json_decode($strError, true);  | 
            ||
| 526 |                 if (isset($aError['error'])) {
 | 
            ||
| 527 | $this->strLastError = $aError['error']['message'] ?? '';  | 
            ||
| 528 | $this->strLastStatus = $aError['error']['status'] ?? '';  | 
            ||
| 529 |                     $this->oLogger->error('GClient: ' . $this->strLastError);
 | 
            ||
| 530 | }  | 
            ||
| 531 | }  | 
            ||
| 532 | }  | 
            ||
| 533 | return $result;  | 
            ||
| 534 | }  | 
            ||
| 535 | |||
| 536 | /**  | 
            ||
| 537 | * Set information about the last error occured.  | 
            ||
| 538 | * If any error can be detected before an API request is made, use this  | 
            ||
| 539 | * method to set an reproduceable errormessage.  | 
            ||
| 540 | * @param int $iResponseCode  | 
            ||
| 541 | * @param string $strError  | 
            ||
| 542 | * @param string $strStatus  | 
            ||
| 543 | */  | 
            ||
| 544 | public function setError(int $iResponseCode, string $strError, string $strStatus) : void  | 
            ||
| 545 |     {
 | 
            ||
| 546 | $this->iLastResponseCode = $iResponseCode;  | 
            ||
| 547 | $this->strLastError = $strError;  | 
            ||
| 548 | $this->strLastStatus = $strStatus;  | 
            ||
| 549 |         $this->oLogger->error('GClient: ' . $this->strLastError);
 | 
            ||
| 550 | }  | 
            ||
| 551 | |||
| 552 | /**  | 
            ||
| 553 | * Parse the header of an HTTP response.  | 
            ||
| 554 | * @param string $strHeader  | 
            ||
| 555 | * @return array<string,string>  | 
            ||
| 556 | */  | 
            ||
| 557 | public function parseHttpHeader(string $strHeader) : array  | 
            ||
| 580 | }  | 
            ||
| 581 | |||
| 582 | /**  | 
            ||
| 583 | * Check, if given property is set and throw exception, if not so.  | 
            ||
| 584 | * @param string $strValue  | 
            ||
| 585 | * @param string $strName  | 
            ||
| 586 | * @throws MissingPropertyException  | 
            ||
| 587 | */  | 
            ||
| 588 | private function checkProperty(string $strValue, string $strName) : void  | 
            ||
| 592 | }  | 
            ||
| 593 | }  | 
            ||
| 594 | }  |