Notification Setup Error

We have detected an error in your notification set-up (Event-ID dab39dc24f564ec7bd4628d1305fd03c). Currently, we cannot inform you about inspection progress. Please check that the user 557058:bca11929-8c2d-43f2-8a82-c5416880d395 still has access to your repository or update the API account.

Completed
Push — develop ( 3cd11f...81f8de )
by Alexandru
04:30 queued 12s
created

Client   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 307
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 97.2%

Importance

Changes 0
Metric Value
wmc 44
lcom 1
cbo 6
dl 0
loc 307
ccs 104
cts 107
cp 0.972
rs 8.8798
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
A get() 0 9 4
A post() 0 4 1
A put() 0 4 1
A delete() 0 4 1
A getClient() 0 4 1
A getResponseFormat() 0 4 1
A setResponseFormat() 0 10 2
A getApiVersion() 0 4 1
A setApiVersion() 0 10 2
A isApiVersion() 0 4 1
A getApiBaseUrl() 0 4 1
A getLastRequest() 0 4 1
A getLastResponse() 0 4 1
A setResponse() 0 4 1
A setRequest() 0 4 1
C request() 0 40 12
B createRequest() 0 22 6
A executeListeners() 0 25 4

How to fix   Complexity   

Complex Class

Complex classes like Client often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Client, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * This file is part of the bitbucket-api package.
5
 *
6
 * (c) Alexandru G. <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
namespace Bitbucket\API\Http;
12
13
use Buzz\Client\ClientInterface as BuzzClientInterface;
14
use Buzz\Client\Curl;
15
use Buzz\Message\MessageInterface;
16
use Buzz\Message\RequestInterface;
17
use Buzz\Message\Request;
18
use Buzz\Message\Response;
19
use Bitbucket\API\Http\Listener\ListenerInterface;
20
21
/**
22
 * @author  Alexandru G.    <[email protected]>
23
 */
24
class Client extends ClientListener implements ClientInterface
25
{
26
    /**
27
     * @var array
28
     */
29
    protected $options = array(
30
        'base_url'      => 'https://api.bitbucket.org',
31
        'api_version'   => '1.0',
32
        'api_versions'  => array('1.0', '2.0'),     // supported versions
33
        'format'        => 'json',
34
        'formats'       => array('json', 'xml'),    // supported response formats
35
        'user_agent'    => 'bitbucket-api-php/1.1.2 (https://bitbucket.org/gentlero/bitbucket-api)',
36
        'timeout'       => 10,
37
        'verify_peer'   => true
38
    );
39
40
    /**
41
     * @var BuzzClientInterface
42
     */
43
    protected $client;
44
45
    /**
46
     * @var RequestInterface
47
     */
48
    private $lastRequest;
49
50
    /**
51
     * @var MessageInterface
52
     */
53
    private $lastResponse;
54
55
    /**
56
     * @var MessageInterface
57
     */
58
    protected $responseObj;
59
60
    /**
61
     * @var RequestInterface
62
     */
63
    protected $requestObj;
64
65 312
    public function __construct(array $options = array(), BuzzClientInterface $client = null)
66
    {
67 312
        $this->client   = (null === $client) ? new Curl() : $client;
68 312
        $this->options  = array_merge($this->options, $options);
69
70 312
        $this->client->setTimeout($this->options['timeout']);
71 312
        $this->client->setVerifyPeer($this->options['verify_peer']);
72 312
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77 8
    public function get($endpoint, $params = array(), $headers = array())
78
    {
79 8
        if (is_array($params) && count($params) > 0) {
80 1
            $endpoint   .= (strpos($endpoint, '?') === false ? '?' : '&').http_build_query($params, '', '&');
81 1
            $params     = array();
82 1
        }
83
84 8
        return $this->request($endpoint, $params, 'GET', $headers);
85 1
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90 3
    public function post($endpoint, $params = array(), $headers = array())
91
    {
92 3
        return $this->request($endpoint, $params, 'POST', $headers);
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98 1
    public function put($endpoint, $params = array(), $headers = array())
99
    {
100 1
        return $this->request($endpoint, $params, 'PUT', $headers);
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106 2
    public function delete($endpoint, $params = array(), $headers = array())
107
    {
108 2
        return $this->request($endpoint, $params, 'DELETE', $headers);
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114 16
    public function request($endpoint, $params = array(), $method = 'GET', array $headers = array())
115
    {
116
        //$request = $this->createRequest($method, $endpoint);
117 16
        $request = ($this->requestObj !== null) ? $this->requestObj : $this->createRequest($method, $endpoint);
118
119
        // add a default content-type if none was set
120 16
        if (empty($headers['Content-Type']) && in_array(strtoupper($method), array('POST', 'PUT'), true)) {
121 2
            $headers['Content-Type'] = 'application/x-www-form-urlencoded';
122 2
        }
123
124 16
        if (count($headers) > 0) {
125 10
            $request->addHeaders($headers);
126 10
        }
127
128 16
        $paramsString = null;
129 16
        if (is_array($params) && count($params) > 0) {
130 4
            $paramsString = http_build_query($params);
131 4
        }
132
133 16
        if (is_string($paramsString) && $paramsString !== null) {
134 4
            $request->setContent($paramsString);
135 4
        }
136
137 16
        if (is_string($params) && $params !== null) {
138 2
            $request->setContent($params);
139 2
        }
140
141 16
        $response = is_object($this->responseObj) ? $this->responseObj : new Response();
142
143 16
        $this->executeListeners($request, 'preSend');
144
145 14
        $this->client->send($request, $response);
146
147 14
        $this->executeListeners($request, 'postSend', $response);
148
149 14
        $this->lastRequest  = $request;
150 14
        $this->lastResponse = $response;
151
152 14
        return $response;
153
    }
154
155
    /**
156
     * @access public
157
     * @return BuzzClientInterface
158
     */
159 1
    public function getClient()
160
    {
161 1
        return $this->client;
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167 12
    public function getResponseFormat()
168
    {
169 12
        return $this->options['format'];
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175 4
    public function setResponseFormat($format)
176
    {
177 4
        if (!in_array($format, $this->options['formats'], true)) {
178 2
            throw new \InvalidArgumentException(sprintf('Unsupported response format %s', $format));
179
        }
180
181 3
        $this->options['format'] = $format;
182
183 3
        return $this;
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189 17
    public function getApiVersion()
190
    {
191 17
        return $this->options['api_version'];
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197 107
    public function setApiVersion($version)
198
    {
199 107
        if (!in_array($version, $this->options['api_versions'], true)) {
200 8
            throw new \InvalidArgumentException(sprintf('Unsupported API version %s', $version));
201
        }
202
203 99
        $this->options['api_version'] = $version;
204
205 99
        return $this;
206
    }
207
208
    /**
209
     * Check if specified API version is the one currently in use.
210
     *
211
     * @access public
212
     * @param  float $version
213
     * @return bool
214
     */
215 1
    public function isApiVersion($version)
216
    {
217 1
        return abs($this->options['api_version'] - $version) < 0.00001;
218
    }
219
220
    /**
221
     * {@inheritdoc}
222
     */
223 16
    public function getApiBaseUrl()
224
    {
225 16
        return $this->options['base_url'].'/'.$this->getApiVersion();
226
    }
227
228
    /**
229
     * @access public
230
     * @return MessageInterface
231
     */
232 7
    public function getLastRequest()
233
    {
234 7
        return $this->lastRequest;
235
    }
236
237
    /**
238
     * @access public
239
     * @return RequestInterface
240
     */
241 2
    public function getLastResponse()
242
    {
243 2
        return $this->lastResponse;
244
    }
245
246
    /**
247
     * @access public
248
     * @param  MessageInterface $response
249
     * @return void
250
     */
251
    public function setResponse(MessageInterface $response)
252
    {
253
        $this->responseObj = $response;
254
    }
255
256
    /**
257
     * @access public
258
     * @param  RequestInterface $request
259
     * @return void
260
     */
261 1
    public function setRequest(RequestInterface $request)
262
    {
263 1
        $this->requestObj = $request;
264 1
    }
265
266
    /**
267
     * @access protected
268
     * @param  string           $method
269
     * @param  string           $url
270
     * @return RequestInterface
271
     */
272 15
    protected function createRequest($method, $url)
273
    {
274
        // do not set base URL if a full one was provided
275 15
        if (false === strpos($url, $this->getApiBaseUrl())) {
276 14
            $url = $this->getApiBaseUrl().'/'.$url;
277 14
        }
278
279
        // change the response format
280 15
        if ($this->getApiVersion() === '1.0' && strpos($url, 'format=') === false) {
281 9
            $url .= (strpos($url, '?') === false ? '?' : '&').'format='.$this->getResponseFormat();
282 9
        }
283
284 15
        $request = is_object($this->requestObj) ? $this->requestObj : new Request();
285 15
        $request->setMethod($method);
286 15
        $request->addHeaders(array(
287 15
                'User-Agent' => $this->options['user_agent']
288 15
            ));
289 15
        $request->setProtocolVersion(1.1);
290 15
        $request->fromUrl($url);
291
292 15
        return $request;
293
    }
294
295
    /**
296
     * Execute all available listeners.
297
     *
298
     * $when can be: preSend or postSend
299
     *
300
     * @access protected
301
     * @param RequestInterface $request
302
     * @param string           $when     When to execute the listener
303
     * @param MessageInterface $response
304
     */
305 16
    protected function executeListeners(RequestInterface $request, $when = 'preSend', MessageInterface $response = null)
306
    {
307 16
        $haveListeners  = count($this->listeners) > 0;
308
309 16
        if (!$haveListeners) {
310 10
            return;
311
        }
312
313 6
        $params = array($request);
314
315 6
        if (null !== $response) {
316 4
            $params[] = $response;
317 4
        }
318
319 6
        ksort($this->listeners, SORT_ASC);
320
321 6
        array_walk_recursive(
322 6
            $this->listeners,
323 6
            function ($class) use ($when, $params) {
324 6
                if ($class instanceof ListenerInterface) {
325 6
                    call_user_func_array(array($class, $when), $params);
326 6
                }
327 6
            }
328 6
        );
329 4
    }
330
}
331