-
Notifications
You must be signed in to change notification settings - Fork 0
/
ApiClient.php
190 lines (167 loc) · 5.51 KB
/
ApiClient.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
<?php
namespace futuretek\api;
use futuretek\shared\Tools;
use Yii;
use yii\helpers\Url;
use yii\web\Application;
/**
* Class ApiClient
*
* @package futuretek\api
* @author Lukas Cerny <[email protected]>
* @license http://www.futuretek.cz/license FTSLv1
* @link http://www.futuretek.cz
*/
abstract class ApiClient
{
private $_serverHost;
private $_curl;
/**
* @var bool Exception mode. If set to true, all REMOTE API errors will be thrown as exceptions.
*/
public $exceptionMode = false;
/**
* ApiClient constructor.
*
* @param bool $exceptionMode Exception mode. If set to true, all REMOTE API errors will be thrown as exceptions.
*/
public function __construct($exceptionMode = false)
{
$this->exceptionMode = $exceptionMode;
$this->_curl = curl_init();
$this->_setCurlOpt();
}
/**
* Set server host
*
* @param string $serverHostUrl Server host URL
*
* @return void
*/
public function setServerHostUrl($serverHostUrl)
{
$this->_serverHost = $serverHostUrl;
}
/**
* Get API URL part
*
* @return string API URL part
*/
abstract public function getApiUrl();
/**
* Authorize method
*
* @return array Array of input variables uses to authorize against the API
*/
abstract protected function authorize();
/**
* Send API request
*
* @param string $method Method name in format (method-name)
* @param array $params Method input parameters
*
* @return array Method API response
* @throws \futuretek\api\ApiException
*/
public function send($method, array $params)
{
if (!$this->_serverHost) {
throw new ApiException(Yii::t('fts-yii2-api', 'API URL not set.'));
}
$auth = $this->authorize();
if (is_array($auth)) {
$params = array_merge($params, $auth);
}
$request = json_encode($params);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new ApiException(Yii::t('fts-yii2-api', 'Error while encoding request to JSON.'));
}
$response = false;
if (is_array($this->_serverHost)) {
foreach ($this->_serverHost as $url) {
$response = $this->_innerSend(rtrim($url, '/') . $this->getApiUrl() . $method, $request);
if ($response) {
break;
}
}
} else {
$response = $this->_innerSend(rtrim($this->_serverHost, '/') . $this->getApiUrl() . $method, $request);
}
if (!$response) {
throw new ApiException(Yii::t('fts-yii2-api', 'Remote API error.'));
}
$response = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new ApiException(Yii::t('fts-yii2-api', 'Error while decoding response from JSON.'));
}
if ($this->exceptionMode && $response['hasErrors'] && 0 !== count($response['errors'])) {
throw new ApiException($response['errors'][0]['message'], 0, null, $response['errors'][0]['file'], $response['errors'][0]['line']);
}
return $response;
}
/**
* Inner method for sending API call
*
* @param $url
* @param $request
* @return mixed
*/
private function _innerSend($url, $request)
{
curl_setopt($this->_curl, CURLOPT_URL, $url);
curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $request);
return curl_exec($this->_curl);
}
/**
* Test API
*
* @return bool If API is OK
* @throws \futuretek\api\ApiException
*/
public function ping()
{
$response = $this->send('ping', []);
return (is_array($response) && array_key_exists('message', $response) && $response['message'] === 'pong');
}
/**
* Set CURL options
*/
private function _setCurlOpt()
{
curl_setopt($this->_curl, CURLOPT_POST, true);
curl_setopt($this->_curl, CURLOPT_USERAGENT, 'FTS-API-Client');
curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->_curl, CURLOPT_MAXREDIRS, 10);
curl_setopt($this->_curl, CURLOPT_REFERER, (Yii::$app instanceof Application ? Url::base() : ''));
curl_setopt($this->_curl, CURLOPT_HTTPHEADER, ['Content-Type: application/json; charset=utf-8']);
curl_setopt($this->_curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($this->_curl, CURLOPT_SSL_VERIFYPEER, false);
}
/**
* Wrap API call
*
* @param mixed $class Class name
* @param string $function Function name
* @param array $arguments Function arguments
* @return ApiResult
* @throws \futuretek\api\ApiException
*/
protected function apiCallEnumerator($class, $function, $arguments)
{
$inputParams = [];
$i = 0;
foreach ((new \ReflectionMethod($class, $function))->getParameters() as $param) {
$paramName = $param->getName();
$inputParams[$paramName] = $arguments[$i];
$i++;
if ($i === count($arguments)) {
break;
}
}
$response = $this->send(Tools::toCommaCase($function), $inputParams);
$namespace = (new \ReflectionClass($class))->getNamespaceName();
/** @var ApiResult $newInstance */
$newInstance = (new \ReflectionClass($namespace . '\\' . $function . 'Result'))->newInstanceArgs([$response]);
return $newInstance;
}
}