Completed
Push — master ( 9df72d...41fedf )
by Aleksandr
02:01
created

Client::getGuzzle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
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
    /**
18
     * @var ResponseInterface
19
     */
20
    public $request;
21
22
    const TYPE_JSON = 'json';
23
    const TYPE_XML = 'xml';
24
    const TYPE_FORM = 'form';
25
26
    protected $protocol = 'https';
27
    protected $url = '';
28
    protected $type = 'json';
29
    protected $output_type;
30
    protected $_guzzleOptions = [];
31
    protected $_custom_guzzle_options = [];
32
    protected $_guzzle;
33
    protected $_errors;
34
35
    /**
36
     * Client constructor.
37
     * @param array $config
38
     */
39
    public function __construct(array $config = [])
40
    {
41
        $this->_guzzle = new GuzzleClient();
42
        foreach ($config as $prop => $value) {
43
            $this->$prop = $value;
44
        }
45
        $this->init();
46
    }
47
48
    public function init()
49
    {
50
        $this->method = strtoupper($this->method);
51
        if (!in_array($this->method, ['GET', 'POST'])) {
52
            $this->method = 'GET';
53
        }
54
    }
55
56
    public function getError($asString = true)
57
    {
58
        if (!$asString) {
59
            return $this->_errors;
60
        }
61
        $error = ['Ошибка валидации параметров'];
62
        foreach ($this->_errors as $param => $errors) {
63
            $error[] = $param . ' - ' . join('; ', $errors);
64
        }
65
        return join("\n", $error);
66
    }
67
68
    public function validate(array $data)
69
    {
70
        foreach ($data as $param => $value) {
71
            $this->validateParam($param, $value);
0 ignored issues
show
Unused Code introduced by
The call to the method carono\rest\Client::validateParam() seems un-needed as the method has no side-effects.

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:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

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:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

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:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
72
        }
73
        return !count($this->_errors);
74
    }
75
76
    /**
77
     * @param array $data
78
     * @return array
79
     */
80
    public function filter(array $data)
81
    {
82
        $result = [];
83
        foreach ($data as $param => $value) {
84
            if (!is_null($filtered = $this->filterParam($param, $value))) {
85
                $result[$param] = $filtered;
86
            }
87
        }
88
        return $result;
89
    }
90
91
    /**
92
     * @param $param
93
     * @param $value
94
     * @return mixed
95
     */
96
    public function filterParam($param, $value)
0 ignored issues
show
Unused Code introduced by
The parameter $param is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
97
    {
98
        return $value;
99
    }
100
101
    /**
102
     * @param $param
103
     * @param $value
104
     * @return bool
105
     */
106
    public function validateParam($param, $value)
0 ignored issues
show
Unused Code introduced by
The parameter $param is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
107
    {
108
        return true;
109
    }
110
111
    public function setGuzzleOptions($array)
112
    {
113
        $this->_custom_guzzle_options = $array;
114
    }
115
116
    /**
117
     * @param $url
118
     * @return string
119
     */
120
    protected function buildUrl($url)
121
    {
122
        if (strpos($this->url, '://')) {
123
            return $this->url . ($url ? '/' . $url : '');
124
        } else {
125
            return $this->protocol . '://' . $this->url . ($url ? '/' . $url : '');
126
        }
127
    }
128
129
    /**
130
     * @return GuzzleClient
131
     */
132
    public function getGuzzle()
133
    {
134
        return $this->_guzzle;
135
    }
136
137
    /**
138
     * @param $urlRequest
139
     * @param array $data
140
     * @return string
141
     */
142
    public function getContent($urlRequest, $data = [])
143
    {
144
        $options = [];
145
        $this->guzzleOptions();
146
        $url = $this->buildUrl($urlRequest);
147
        $client = $this->getGuzzle();
148
        $data = $this->prepareData($data);
149
        if ($this->method == 'GET') {
150
            $url = $url . (strpos($url, '?') ? '&' : '?') . build_query($data);
0 ignored issues
show
Bug introduced by
It seems like $data defined by $this->prepareData($data) on line 148 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.

Loading history...
151
        } elseif ($this->postDataInBody) {
152
            $options = ['body' => $data];
153
        } else {
154
            $options = ['form_params' => $data];
155
        }
156
        $request = $client->request($this->method, $url, array_merge($options, $this->_guzzleOptions));
157
        $this->request = $request;
158
        return $this->unSerialize($request->getBody()->getContents());
159
    }
160
161
    /**
162
     * @param $data
163
     * @return mixed|null|\SimpleXMLElement
164
     */
165
    public function unSerialize($data)
166
    {
167
        $type = $this->output_type ? $this->output_type : $this->type;
168
169
        switch ($type) {
170
            case self::TYPE_JSON:
171
                return \GuzzleHttp\json_decode($data);
172
                break;
0 ignored issues
show
Unused Code introduced by
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.

Loading history...
173
            case self::TYPE_XML:
174
                return simplexml_load_string($data);
175
                break;
0 ignored issues
show
Unused Code introduced by
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.

Loading history...
176
        }
177
        return $data;
178
    }
179
180
    public function addError($param, $message)
181
    {
182
        $this->_errors[$param][] = $message;
183
    }
184
185
    /**
186
     * @param $data
187
     * @return string|array
188
     * @throws \Exception
189
     */
190
    protected function prepareData(array $data)
191
    {
192
        $data = $this->filter($data);
193
        if (!$this->validate($data)) {
194
            throw new \Exception($this->getError());
195
        }
196
        if ($this->method == 'GET') {
197
            return $data;
198
        }
199
        switch ($this->type) {
200
            case self::TYPE_JSON:
201
                $data = \GuzzleHttp\json_encode($data);
202
                break;
203
            case self::TYPE_XML:
204
                throw new \Exception('Xml type is not implemented yet');
205
                break;
0 ignored issues
show
Unused Code introduced by
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 return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
206
            case self::TYPE_FORM:
207
                break;
208
            default:
209
                throw new \Exception('Type is not supported');
210
                break;
0 ignored issues
show
Unused Code introduced by
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 return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
211
        }
212
        return $data;
213
    }
214
215
    /**
216
     * @throws \Exception
217
     */
218
    public function guzzleOptions()
219
    {
220
        $options = [
221
            'headers' => []
222
        ];
223
        if ($this->proxy) {
224
            $options['proxy'] = $this->proxy;
225
        }
226
        switch ($this->type) {
227
            case self::TYPE_JSON:
228
                $options['headers']['content-type'] = 'application/json';
229
                break;
230
            case self::TYPE_XML:
231
                $options['headers']['content-type'] = 'application/xml';
232
                break;
233
            case self::TYPE_FORM:
234
                $options['headers']['content-type'] = 'application/x-www-form-urlencoded';
235
                break;
236
237
            default:
238
                throw new \Exception('Type is not supported');
239
        }
240
        if ($this->login || $this->password) {
241
            $options['auth'] = [$this->login, $this->password];
242
        }
243
        $this->_guzzleOptions = array_merge($options, $this->_custom_guzzle_options);
244
    }
245
}