DrTeamRocks /
uon
| 1 | <?php |
||||
| 2 | |||||
| 3 | namespace Uon; |
||||
| 4 | |||||
| 5 | use GuzzleHttp\Client as HttpClient; |
||||
| 6 | use GuzzleHttp\Exception\GuzzleException; |
||||
| 7 | use GuzzleHttp\RequestOptions; |
||||
| 8 | use Psr\Http\Message\ResponseInterface; |
||||
| 9 | use Uon\Exceptions\UonEmptyResponseException; |
||||
| 10 | use Uon\Exceptions\UonHttpClientException; |
||||
| 11 | use Uon\Exceptions\UonTooManyRequests; |
||||
| 12 | use Uon\Interfaces\ClientInterface; |
||||
| 13 | use function str_replace; |
||||
| 14 | use function strtoupper; |
||||
| 15 | use function ucwords; |
||||
| 16 | |||||
| 17 | /** |
||||
| 18 | * @author Paul Rock <[email protected]> |
||||
| 19 | * @link http://drteam.rocks |
||||
| 20 | * @license MIT |
||||
| 21 | * @package Uon |
||||
| 22 | * |
||||
| 23 | * @property \Uon\Endpoints\Avia $avia Aero transfer |
||||
| 24 | * @property \Uon\Endpoints\Bcard $bcard Bonus cards |
||||
| 25 | * @property \Uon\Endpoints\CallHistory $callHistory History of calls |
||||
| 26 | * @property \Uon\Endpoints\Cash $cash Money operations |
||||
| 27 | * @property \Uon\Endpoints\Catalog $catalog Catalog of products |
||||
| 28 | * @property \Uon\Endpoints\Chat $chat For work with chat messages |
||||
| 29 | * @property \Uon\Endpoints\Cities $cities Cities of countries |
||||
| 30 | * @property \Uon\Endpoints\Countries $countries Work with countries |
||||
| 31 | * @property \Uon\Endpoints\Currencies $currencies Work with currencies |
||||
| 32 | * @property \Uon\Endpoints\ExtendedFields $extendedFields For manipulation with extended fields |
||||
| 33 | * @property \Uon\Endpoints\Hotels $hotels Hotels methods |
||||
| 34 | * @property \Uon\Endpoints\Leads $leads Details about clients |
||||
| 35 | * @property \Uon\Endpoints\Mails $mails For work with emails |
||||
| 36 | * @property \Uon\Endpoints\Managers $managers Get access to list of managers (sale operators) |
||||
| 37 | * @property \Uon\Endpoints\Misc $misc Optional single methods |
||||
| 38 | * @property \Uon\Endpoints\Notifications $notifications For creating new notifications for managers |
||||
| 39 | * @property \Uon\Endpoints\Nutrition $nutrition Some methods about eat |
||||
| 40 | * @property \Uon\Endpoints\Offices $offices Get access to list of all offices |
||||
| 41 | * @property \Uon\Endpoints\Payments $payments Payment methods |
||||
| 42 | * @property \Uon\Endpoints\ReasonsDeny $reasonsDeny List of all deny reasons |
||||
| 43 | * @property \Uon\Endpoints\Reminders $reminders Work with reminders |
||||
| 44 | * @property \Uon\Endpoints\Requests $requests New requests from people |
||||
| 45 | * @property \Uon\Endpoints\Services $services All available services |
||||
| 46 | * @property \Uon\Endpoints\Sources $sources All available sources |
||||
| 47 | * @property \Uon\Endpoints\Statuses $statuses Request statuses |
||||
| 48 | * @property \Uon\Endpoints\Suppliers $suppliers External companies |
||||
| 49 | * @property \Uon\Endpoints\Users $users For work with users |
||||
| 50 | * @property \Uon\Endpoints\Visa $visa For work with visa statuses |
||||
| 51 | * @property \Uon\Endpoints\Webhooks $webhooks Webhooks management |
||||
| 52 | */ |
||||
| 53 | class Client implements ClientInterface |
||||
| 54 | { |
||||
| 55 | /** |
||||
| 56 | * @var string |
||||
| 57 | */ |
||||
| 58 | protected $namespace = __NAMESPACE__ . '\\Endpoints'; |
||||
| 59 | |||||
| 60 | /** |
||||
| 61 | * Initial state of some variables |
||||
| 62 | * |
||||
| 63 | * @var null|\GuzzleHttp\Client |
||||
| 64 | */ |
||||
| 65 | public $client; |
||||
| 66 | |||||
| 67 | /** |
||||
| 68 | * Object of main config |
||||
| 69 | * |
||||
| 70 | * @var \Uon\Config |
||||
| 71 | 2 | */ |
|||
| 72 | public $config; |
||||
| 73 | |||||
| 74 | 2 | /** |
|||
| 75 | * Type of query |
||||
| 76 | * |
||||
| 77 | 2 | * @var string |
|||
| 78 | */ |
||||
| 79 | protected $type; |
||||
| 80 | |||||
| 81 | /** |
||||
| 82 | 2 | * Endpoint of query |
|||
| 83 | * |
||||
| 84 | * @var string |
||||
| 85 | */ |
||||
| 86 | protected $endpoint; |
||||
| 87 | 2 | ||||
| 88 | /** |
||||
| 89 | * Parameters of query |
||||
| 90 | * |
||||
| 91 | * @var array |
||||
| 92 | 2 | */ |
|||
| 93 | protected $params = []; |
||||
| 94 | |||||
| 95 | 2 | /** |
|||
| 96 | 2 | * @var array |
|||
| 97 | */ |
||||
| 98 | protected static $variables = []; |
||||
| 99 | |||||
| 100 | /** |
||||
| 101 | * API constructor. |
||||
| 102 | * |
||||
| 103 | * @param array|\Uon\Config $config |
||||
| 104 | * @param bool $init |
||||
| 105 | * |
||||
| 106 | * @throws \ErrorException |
||||
| 107 | 61 | */ |
|||
| 108 | public function __construct($config, bool $init = true) |
||||
| 109 | 61 | { |
|||
| 110 | if (!$config instanceof Config) { |
||||
| 111 | $config = new Config($config); |
||||
| 112 | 61 | } |
|||
| 113 | 61 | ||||
| 114 | 61 | // Save config into local variable |
|||
| 115 | $this->config = $config; |
||||
| 116 | |||||
| 117 | 61 | // Init if need |
|||
| 118 | if ($init) { |
||||
| 119 | $this->client = $this->initClient($config->guzzle()); |
||||
| 120 | 61 | } |
|||
| 121 | 60 | } |
|||
| 122 | |||||
| 123 | /** |
||||
| 124 | * Get current client instance |
||||
| 125 | 1 | * |
|||
| 126 | 1 | * @return null|\GuzzleHttp\Client |
|||
| 127 | */ |
||||
| 128 | public function getClient(): ?HttpClient |
||||
| 129 | 1 | { |
|||
| 130 | return $this->client; |
||||
| 131 | } |
||||
| 132 | |||||
| 133 | /** |
||||
| 134 | * Store the client object |
||||
| 135 | * |
||||
| 136 | * @param array $configs |
||||
| 137 | * |
||||
| 138 | * @return \GuzzleHttp\Client |
||||
| 139 | */ |
||||
| 140 | public function initClient(array $configs = []): HttpClient |
||||
| 141 | 61 | { |
|||
| 142 | return new HttpClient($configs); |
||||
| 143 | } |
||||
| 144 | 61 | ||||
| 145 | /** |
||||
| 146 | * Convert underscore_strings to camelCase (medial capitals). |
||||
| 147 | 61 | * |
|||
| 148 | * @param string $str |
||||
| 149 | * |
||||
| 150 | * @return string |
||||
| 151 | 61 | */ |
|||
| 152 | private function snakeToPascal(string $str): string |
||||
| 153 | { |
||||
| 154 | // Remove underscores, capitalize words, squash, lowercase first. |
||||
| 155 | 61 | return str_replace(' ', '', ucwords(str_replace('_', ' ', $str))); |
|||
| 156 | 61 | } |
|||
| 157 | 1 | ||||
| 158 | 60 | /** |
|||
| 159 | 60 | * Magic method required for call of another classes |
|||
| 160 | 60 | * |
|||
| 161 | 61 | * @param string $name |
|||
| 162 | * |
||||
| 163 | * @return bool|object |
||||
| 164 | */ |
||||
| 165 | public function __get(string $name) |
||||
| 166 | { |
||||
| 167 | if (isset(self::$variables[$name])) { |
||||
| 168 | return self::$variables[$name]; |
||||
| 169 | } |
||||
| 170 | |||||
| 171 | // Set class name as namespace |
||||
| 172 | $class = $this->namespace . '\\' . $this->snakeToPascal($name); |
||||
| 173 | |||||
| 174 | // Try to create object by name |
||||
| 175 | return new $class($this->config); |
||||
| 176 | } |
||||
| 177 | |||||
| 178 | /** |
||||
| 179 | * Check if class is exist in folder |
||||
| 180 | * |
||||
| 181 | * @param string $name |
||||
| 182 | * |
||||
| 183 | * @return bool |
||||
| 184 | */ |
||||
| 185 | public function __isset(string $name): bool |
||||
| 186 | { |
||||
| 187 | return isset(self::$variables[$name]); |
||||
| 188 | } |
||||
| 189 | |||||
| 190 | /** |
||||
| 191 | * Ordinary dummy setter, it should be ignored (added to PSR reasons) |
||||
| 192 | * |
||||
| 193 | * @param string $name |
||||
| 194 | * @param mixed $value |
||||
| 195 | */ |
||||
| 196 | public function __set(string $name, $value) |
||||
| 197 | { |
||||
| 198 | self::$variables[$name] = $value; |
||||
| 199 | } |
||||
| 200 | |||||
| 201 | /** |
||||
| 202 | * Request executor with timeout and repeat tries |
||||
| 203 | * |
||||
| 204 | * @param string $type Request method |
||||
| 205 | * @param string $url endpoint url |
||||
| 206 | * @param array $params List of parameters |
||||
| 207 | * |
||||
| 208 | * @return \Psr\Http\Message\ResponseInterface|null |
||||
| 209 | * |
||||
| 210 | * @throws \Uon\Exceptions\UonTooManyRequests |
||||
| 211 | * @throws \Uon\Exceptions\UonParameterNotSetException |
||||
| 212 | * @throws \Uon\Exceptions\UonHttpClientException |
||||
| 213 | */ |
||||
| 214 | private function repeatRequest(string $type, string $url, array $params = []): ?ResponseInterface |
||||
| 215 | { |
||||
| 216 | $type = strtoupper($type); |
||||
| 217 | |||||
| 218 | for ($i = 1; $i <= $this->config->get('tries'); $i++) { |
||||
| 219 | |||||
| 220 | $requestEndpoint = |
||||
| 221 | $this->config->get('base_uri') . '/' |
||||
| 222 | . $this->config->get('token') . '/' |
||||
| 223 | . $url . '.' . $this->config->get('format'); |
||||
| 224 | |||||
| 225 | if ($this->config->get('verbose')) { |
||||
| 226 | var_dump('[' . $type . '] endpoint:' . $requestEndpoint . ' parameters:' . json_encode($params)); |
||||
| 227 | } |
||||
| 228 | |||||
| 229 | try { |
||||
| 230 | |||||
| 231 | if (empty($params)) { |
||||
| 232 | // Execute the request to server |
||||
| 233 | $result = $this->client->request($type, $requestEndpoint); |
||||
|
0 ignored issues
–
show
|
|||||
| 234 | } else { |
||||
| 235 | // Execute the request to server |
||||
| 236 | $result = $this->client->request($type, $requestEndpoint, [RequestOptions::FORM_PARAMS => $params]); |
||||
| 237 | } |
||||
| 238 | |||||
| 239 | // Check the code status |
||||
| 240 | $code = $result->getStatusCode(); |
||||
| 241 | |||||
| 242 | // If success response from server |
||||
| 243 | if ($code === 200 || $code === 201) { |
||||
| 244 | return $result; |
||||
| 245 | } |
||||
| 246 | |||||
| 247 | // If not "too many requests", then probably some bug on remote or our side |
||||
| 248 | if ($code !== 429) { |
||||
| 249 | throw new UonTooManyRequests(); |
||||
| 250 | } |
||||
| 251 | |||||
| 252 | } catch (GuzzleException $exception) { |
||||
| 253 | throw new UonHttpClientException($exception); |
||||
| 254 | } |
||||
| 255 | |||||
| 256 | // Waiting in seconds |
||||
| 257 | sleep($this->config->get('seconds')); |
||||
|
0 ignored issues
–
show
It seems like
$this->config->get('seconds') can also be of type boolean and null and string; however, parameter $seconds of sleep() does only seem to accept integer, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 258 | } |
||||
| 259 | |||||
| 260 | // Return false if loop is done but no answer from server |
||||
| 261 | return null; |
||||
| 262 | } |
||||
| 263 | |||||
| 264 | /** |
||||
| 265 | * Execute request and return response |
||||
| 266 | * |
||||
| 267 | * @return null|object Array with data or NULL if error |
||||
| 268 | * |
||||
| 269 | * @throws \Uon\Exceptions\UonEmptyResponseException |
||||
| 270 | * @throws \Uon\Exceptions\UonTooManyRequests |
||||
| 271 | * @throws \Uon\Exceptions\UonHttpClientException |
||||
| 272 | */ |
||||
| 273 | public function exec() |
||||
| 274 | { |
||||
| 275 | return $this->doRequest($this->type, $this->endpoint, $this->params); |
||||
| 276 | } |
||||
| 277 | |||||
| 278 | /** |
||||
| 279 | * Execute query and return RAW response from remote API |
||||
| 280 | * |
||||
| 281 | * @return null|\Psr\Http\Message\ResponseInterface RAW response or NULL if error |
||||
| 282 | * |
||||
| 283 | * @throws \Uon\Exceptions\UonEmptyResponseException |
||||
| 284 | * @throws \Uon\Exceptions\UonTooManyRequests |
||||
| 285 | * @throws \Uon\Exceptions\UonHttpClientException |
||||
| 286 | */ |
||||
| 287 | public function raw(): ?ResponseInterface |
||||
| 288 | { |
||||
| 289 | return $this->doRequest($this->type, $this->endpoint, $this->params, true); |
||||
| 290 | } |
||||
| 291 | |||||
| 292 | /** |
||||
| 293 | * Make the request and analyze the result |
||||
| 294 | * |
||||
| 295 | * @param string $type Request method |
||||
| 296 | * @param string $requestEndpoint Api request endpoint |
||||
| 297 | * @param mixed $params List of parameters |
||||
| 298 | * @param bool $raw Return data in raw format |
||||
| 299 | * |
||||
| 300 | * @return null|object|ResponseInterface Array with data, RAW response or NULL if error |
||||
| 301 | * |
||||
| 302 | * @throws \Uon\Exceptions\UonEmptyResponseException If empty response received from U-On |
||||
| 303 | * @throws \Uon\Exceptions\UonTooManyRequests If amount or repeats is more than allowed |
||||
| 304 | * @throws \Uon\Exceptions\UonHttpClientException If http exception occurred |
||||
| 305 | */ |
||||
| 306 | private function doRequest(string $type, string $requestEndpoint, array $params = [], bool $raw = false) |
||||
| 307 | { |
||||
| 308 | // Execute the request to server |
||||
| 309 | $result = $this->repeatRequest($type, $requestEndpoint, $params); |
||||
| 310 | |||||
| 311 | // If debug then return Guzzle object |
||||
| 312 | if ($this->config->get('debug') === true) { |
||||
| 313 | return $result; |
||||
| 314 | } |
||||
| 315 | |||||
| 316 | if (null === $result) { |
||||
| 317 | throw new UonEmptyResponseException(); |
||||
| 318 | } |
||||
| 319 | |||||
| 320 | // Return RAW result if required |
||||
| 321 | if ($raw) { |
||||
| 322 | return $result; |
||||
| 323 | } |
||||
| 324 | |||||
| 325 | return json_decode($result->getBody(), false); |
||||
| 326 | } |
||||
| 327 | |||||
| 328 | /** |
||||
| 329 | * @since 2.0 |
||||
| 330 | * |
||||
| 331 | * @return null|object|\Uon\Interfaces\ClientInterface |
||||
| 332 | * |
||||
| 333 | * @throws \Uon\Exceptions\UonEmptyResponseException |
||||
| 334 | * @throws \Uon\Exceptions\UonHttpClientException |
||||
| 335 | * @throws \Uon\Exceptions\UonTooManyRequests |
||||
| 336 | */ |
||||
| 337 | protected function done() |
||||
| 338 | { |
||||
| 339 | return $this->config->get('auto_exec') ? $this->exec() : $this; |
||||
| 340 | } |
||||
| 341 | } |
||||
| 342 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.