These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace carono\rest; |
||
4 | |||
5 | use function GuzzleHttp\Psr7\build_query; |
||
6 | use GuzzleHttp\Client as GuzzleClient; |
||
7 | use Psr\Http\Message\ResponseInterface; |
||
8 | use Psr\Http\Message\StreamInterface; |
||
9 | |||
10 | class Client |
||
11 | { |
||
12 | public $login; |
||
13 | public $password; |
||
14 | public $proxy; |
||
15 | public $method = 'GET'; |
||
16 | public $postDataInBody = false; |
||
17 | public $useAuth = true; |
||
18 | |||
19 | /** |
||
20 | * @var ResponseInterface |
||
21 | */ |
||
22 | public $request; |
||
23 | |||
24 | const TYPE_JSON = 'json'; |
||
25 | const TYPE_XML = 'xml'; |
||
26 | const TYPE_FORM = 'form'; |
||
27 | |||
28 | protected $protocol = 'https'; |
||
29 | protected $url = ''; |
||
30 | protected $type = 'json'; |
||
31 | protected $output_type; |
||
32 | protected $_guzzleOptions = []; |
||
33 | protected $_custom_guzzle_options = []; |
||
34 | protected $_guzzle; |
||
35 | protected $_errors; |
||
36 | |||
37 | /** |
||
38 | * Client constructor. |
||
39 | * |
||
40 | * @param array $config |
||
41 | */ |
||
42 | public function __construct(array $config = []) |
||
43 | { |
||
44 | $this->_guzzle = new GuzzleClient(); |
||
45 | foreach ($config as $prop => $value) { |
||
46 | $this->$prop = $value; |
||
47 | } |
||
48 | $this->init(); |
||
49 | } |
||
50 | |||
51 | public function init() |
||
52 | { |
||
53 | $this->method = strtoupper($this->method); |
||
54 | if (!in_array($this->method, ['GET', 'POST'])) { |
||
55 | $this->method = 'GET'; |
||
56 | } |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * @param bool $asString |
||
61 | * @return string |
||
62 | */ |
||
63 | public function getError($asString = true) |
||
64 | { |
||
65 | if (!$asString) { |
||
66 | return $this->_errors; |
||
67 | } |
||
68 | $error = ['Ошибка валидации параметров']; |
||
69 | foreach ($this->_errors as $param => $errors) { |
||
70 | $error[] = $param . ' - ' . join('; ', $errors); |
||
71 | } |
||
72 | return join("\n", $error); |
||
73 | } |
||
74 | |||
75 | public function validate(array $data) |
||
76 | { |
||
77 | foreach ($data as $param => $value) { |
||
78 | $this->validateParam($param, $value); |
||
0 ignored issues
–
show
|
|||
79 | } |
||
80 | return !count($this->_errors); |
||
81 | } |
||
82 | |||
83 | /** |
||
84 | * @param array $data |
||
85 | * @return array |
||
86 | */ |
||
87 | public function filter(array $data) |
||
88 | { |
||
89 | $result = []; |
||
90 | foreach ($data as $param => $value) { |
||
91 | if (!is_null($filtered = $this->filterParam($param, $value))) { |
||
92 | $result[$param] = $filtered; |
||
93 | } |
||
94 | } |
||
95 | return $result; |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * @param $param |
||
100 | * @param $value |
||
101 | * @return mixed |
||
102 | */ |
||
103 | public function filterParam($param, $value) |
||
0 ignored issues
–
show
|
|||
104 | { |
||
105 | return $value; |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * @param $param |
||
110 | * @param $value |
||
111 | * @return bool |
||
112 | */ |
||
113 | public function validateParam($param, $value) |
||
0 ignored issues
–
show
|
|||
114 | { |
||
115 | return true; |
||
116 | } |
||
117 | |||
118 | public function setGuzzleOptions($array) |
||
119 | { |
||
120 | $this->_custom_guzzle_options = $array; |
||
121 | } |
||
122 | |||
123 | /** |
||
124 | * @param $url |
||
125 | * @return string |
||
126 | */ |
||
127 | protected function buildUrl($url) |
||
128 | { |
||
129 | if (strpos($this->url, '://')) { |
||
130 | return $this->url . ($url ? '/' . $url : ''); |
||
131 | } else { |
||
132 | return $this->protocol . '://' . $this->url . ($url ? '/' . $url : ''); |
||
133 | } |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * @return GuzzleClient |
||
138 | */ |
||
139 | public function getGuzzle() |
||
140 | { |
||
141 | return $this->_guzzle; |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * @param $urlRequest |
||
146 | * @param array $data |
||
147 | * @return string|\stdClass|\SimpleXMLElement |
||
148 | */ |
||
149 | public function getContent($urlRequest, $data = []) |
||
150 | { |
||
151 | $options = []; |
||
152 | $this->guzzleOptions(); |
||
153 | $url = $this->buildUrl($urlRequest); |
||
154 | $client = $this->getGuzzle(); |
||
155 | $data = $this->prepareData($data); |
||
156 | if ($this->method == 'GET') { |
||
157 | $url = $url . (strpos($url, '?') ? '&' : '?') . build_query($data); |
||
0 ignored issues
–
show
It seems like
$data defined by $this->prepareData($data) on line 155 can also be of type string ; however, GuzzleHttp\Psr7\build_query() does only seem to accept array , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
158 | } elseif ($this->postDataInBody) { |
||
159 | $options = ['body' => $data]; |
||
160 | } else { |
||
161 | $options = ['form_params' => $data]; |
||
162 | } |
||
163 | $request = $client->request($this->method, $url, array_merge($options, $this->_guzzleOptions)); |
||
164 | $this->request = $request; |
||
165 | return $this->unSerialize($request->getBody()->getContents()); |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * @param $data |
||
170 | * @return mixed |
||
171 | */ |
||
172 | protected function unSerializeJson($data) |
||
173 | { |
||
174 | return \GuzzleHttp\json_decode($data); |
||
175 | } |
||
176 | |||
177 | /** |
||
178 | * @param $data |
||
179 | * @return \SimpleXMLElement |
||
180 | */ |
||
181 | protected function unSerializeXml($data) |
||
182 | { |
||
183 | return simplexml_load_string($data); |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * @param $data |
||
188 | * @return mixed|null|\SimpleXMLElement |
||
189 | */ |
||
190 | public function unSerialize($data) |
||
191 | { |
||
192 | $type = $this->output_type ? $this->output_type : $this->type; |
||
193 | |||
194 | switch ($type) { |
||
195 | case self::TYPE_JSON: |
||
196 | return $this->unSerializeJson($data); |
||
197 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
198 | case self::TYPE_XML: |
||
199 | return $this->unSerializeXml($data); |
||
200 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
201 | } |
||
202 | return $data; |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * @param $param |
||
207 | * @param $message |
||
208 | */ |
||
209 | public function addError($param, $message) |
||
210 | { |
||
211 | $this->_errors[$param][] = $message; |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * @param array $data |
||
216 | * @return array |
||
217 | */ |
||
218 | protected function beforePrepareData(array $data) |
||
219 | { |
||
220 | return $data; |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * @param $data |
||
225 | * @return string|array |
||
226 | * @throws \Exception |
||
227 | */ |
||
228 | protected function prepareData(array $data) |
||
229 | { |
||
230 | $data = $this->beforePrepareData($data); |
||
231 | $data = $this->filter($data); |
||
232 | |||
233 | if (!$this->validate($data)) { |
||
234 | throw new \Exception($this->getError()); |
||
235 | } |
||
236 | if ($this->method == 'GET') { |
||
237 | return $data; |
||
238 | } |
||
239 | switch ($this->type) { |
||
240 | case self::TYPE_JSON: |
||
241 | $data = \GuzzleHttp\json_encode($data); |
||
242 | break; |
||
243 | case self::TYPE_XML: |
||
244 | throw new \Exception('Xml type is not implemented yet'); |
||
245 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
246 | case self::TYPE_FORM: |
||
247 | break; |
||
248 | default: |
||
249 | throw new \Exception('Type is not supported'); |
||
250 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
251 | } |
||
252 | return $data; |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * @throws \Exception |
||
257 | */ |
||
258 | public function guzzleOptions() |
||
259 | { |
||
260 | $options = [ |
||
261 | 'headers' => [] |
||
262 | ]; |
||
263 | if ($this->proxy) { |
||
264 | $options['proxy'] = $this->proxy; |
||
265 | } |
||
266 | switch ($this->type) { |
||
267 | case self::TYPE_JSON: |
||
268 | $options['headers']['content-type'] = 'application/json'; |
||
269 | break; |
||
270 | case self::TYPE_XML: |
||
271 | $options['headers']['content-type'] = 'application/xml'; |
||
272 | break; |
||
273 | case self::TYPE_FORM: |
||
274 | $options['headers']['content-type'] = 'application/x-www-form-urlencoded'; |
||
275 | break; |
||
276 | |||
277 | default: |
||
278 | throw new \Exception('Type is not supported'); |
||
279 | } |
||
280 | if (($this->login || $this->password) && $this->useAuth) { |
||
281 | $options['auth'] = [$this->login, $this->password]; |
||
282 | } |
||
283 | $this->_guzzleOptions = array_merge($options, $this->_custom_guzzle_options); |
||
284 | } |
||
285 | } |
PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.
Let’s take a look at an example:
If we look at the
getEmail()
method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:On the hand, if we look at the
setEmail()
, this method _has_ side-effects. In the following case, we could not remove the method call: