Completed
Push — master ( a0c93c...320c17 )
by Aleksandr
01:49
created

Client   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 201
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 35
lcom 1
cbo 3
dl 0
loc 201
rs 9
c 0
b 0
f 0

13 Methods

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