Completed
Push — master ( eca42f...9df72d )
by Aleksandr
02:11
created

Client::guzzleOptions()   C

Complexity

Conditions 7
Paths 14

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 20
nc 14
nop 0
1
<?php
2
3
namespace carono\rest;
4
5
use function GuzzleHttp\Psr7\build_query;
6
use GuzzleHttp\Client as GuzzleClient;
7
8
class Client
9
{
10
    public $login;
11
    public $password;
12
    public $proxy;
13
    public $method = 'GET';
14
    public $postDataInBody = false;
15
16
    const TYPE_JSON = 'json';
17
    const TYPE_XML = 'xml';
18
    const TYPE_FORM = 'form';
19
20
    protected $protocol = 'https';
21
    protected $url = '';
22
    protected $type = 'json';
23
    protected $output_type;
24
    protected $_guzzleOptions = [];
25
    protected $_guzzle;
26
    protected $_errors;
27
28
    /**
29
     * Client constructor.
30
     * @param array $config
31
     */
32
    public function __construct(array $config = [])
33
    {
34
        $this->_guzzle = new GuzzleClient();
35
        foreach ($config as $prop => $value) {
36
            $this->$prop = $value;
37
        }
38
        $this->init();
39
    }
40
41
    public function init()
42
    {
43
        $this->method = strtoupper($this->method);
44
        if (!in_array($this->method, ['GET', 'POST'])) {
45
            $this->method = 'GET';
46
        }
47
    }
48
49
    public function getError($asString = true)
50
    {
51
        if (!$asString) {
52
            return $this->_errors;
53
        }
54
        $error = ['Ошибка валидации параметров'];
55
        foreach ($this->_errors as $param => $errors) {
56
            $error[] = $param . ' - ' . join('; ', $errors);
57
        }
58
        return join("\n", $error);
59
    }
60
61
    public function validate(array $data)
62
    {
63
        foreach ($data as $param => $value) {
64
            $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...
65
        }
66
        return !count($this->_errors);
67
    }
68
69
    /**
70
     * @param array $data
71
     * @return array
72
     */
73
    public function filter(array $data)
74
    {
75
        $result = [];
76
        foreach ($data as $param => $value) {
77
            if (!is_null($filtered = $this->filterParam($param, $value))) {
78
                $result[$param] = $filtered;
79
            }
80
        }
81
        return $result;
82
    }
83
84
    /**
85
     * @param $param
86
     * @param $value
87
     * @return mixed
88
     */
89
    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...
90
    {
91
        return $value;
92
    }
93
94
    /**
95
     * @param $param
96
     * @param $value
97
     * @return bool
98
     */
99
    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...
100
    {
101
        return true;
102
    }
103
104
    /**
105
     * @param $url
106
     * @return string
107
     */
108
    protected function buildUrl($url)
109
    {
110
        if (strpos($this->url, '://')) {
111
            return $this->url . ($url ? '/' . $url : '');
112
        } else {
113
            return $this->protocol . '://' . $this->url . ($url ? '/' . $url : '');
114
        }
115
    }
116
117
    /**
118
     * @param $urlRequest
119
     * @param array $data
120
     * @return string
121
     */
122
    public function getContent($urlRequest, $data = [])
123
    {
124
        $options = [];
125
        $this->guzzleOptions();
126
        $url = $this->buildUrl($urlRequest);
127
        $client = $this->_guzzle;
128
        $data = $this->prepareData($data);
129
        if ($this->method == 'GET') {
130
            $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 128 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...
131
        } elseif ($this->postDataInBody) {
132
            $options = ['body' => $data];
133
        } else {
134
            $options = ['form_params' => $data];
135
        }
136
        $request = $client->request($this->method, $url, array_merge($options, $this->_guzzleOptions));
137
        return $this->unSerialize($request->getBody()->getContents());
138
    }
139
140
    /**
141
     * @param $data
142
     * @return mixed|null|\SimpleXMLElement
143
     */
144
    public function unSerialize($data)
145
    {
146
        $type = $this->output_type ? $this->output_type : $this->type;
147
148
        switch ($type) {
149
            case self::TYPE_JSON:
150
                return \GuzzleHttp\json_decode($data);
151
                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...
152
            case self::TYPE_XML:
153
                return simplexml_load_string($data);
154
                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...
155
        }
156
        return $data;
157
    }
158
159
    public function addError($param, $message)
160
    {
161
        $this->_errors[$param][] = $message;
162
    }
163
164
    /**
165
     * @param $data
166
     * @return string|array
167
     * @throws \Exception
168
     */
169
    protected function prepareData(array $data)
170
    {
171
        $data = $this->filter($data);
172
        if (!$this->validate($data)) {
173
            throw new \Exception($this->getError());
174
        }
175
        if ($this->method == 'GET') {
176
            return $data;
177
        }
178
        switch ($this->type) {
179
            case self::TYPE_JSON:
180
                $data = \GuzzleHttp\json_encode($data);
181
                break;
182
            case self::TYPE_XML:
183
                throw new \Exception('Xml type is not implemented yet');
184
                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...
185
            case self::TYPE_FORM:
186
                break;
187
            default:
188
                throw new \Exception('Type is not supported');
189
                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...
190
        }
191
        return $data;
192
    }
193
194
    /**
195
     * @throws \Exception
196
     */
197
    public function guzzleOptions()
198
    {
199
        $options = [
200
            'headers' => []
201
        ];
202
        if ($this->proxy) {
203
            $options['proxy'] = $this->proxy;
204
        }
205
        switch ($this->type) {
206
            case self::TYPE_JSON:
207
                $options['headers']['content-type'] = 'application/json';
208
                break;
209
            case self::TYPE_XML:
210
                $options['headers']['content-type'] = 'application/xml';
211
                break;
212
            case self::TYPE_FORM:
213
                $options['headers']['content-type'] = 'application/x-www-form-urlencoded';
214
                break;
215
216
            default:
217
                throw new \Exception('Type is not supported');
218
        }
219
        if ($this->login || $this->password) {
220
            $options['auth'] = [$this->login, $this->password];
221
        }
222
        $this->_guzzleOptions = $options;
223
    }
224
}