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)); |
||||||
|
0 ignored issues
–
show
Security
Debugging Code
introduced
by
Loading history...
|
|||||||
| 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
The method
request() does not exist on null.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
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. Loading history...
|
|||||||
| 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 |