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 — master ( c1a320...90d744 )
by Alexandru
04:00
created

Client   B

Complexity

Total Complexity 40

Size/Duplication

Total Lines 298
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 96.59%

Importance

Changes 0
Metric Value
wmc 40
lcom 1
cbo 6
dl 0
loc 298
ccs 85
cts 88
cp 0.9659
rs 8.2608
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
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
A get() 0 9 4
C request() 0 31 8
B createRequest() 0 22 6
B 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.0 (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 305
    public function __construct(array $options = array(), BuzzClientInterface $client = null)
66
    {
67 305
        $this->client   = (null === $client) ? new Curl() : $client;
68 305
        $this->options  = array_merge($this->options, $options);
69
70 305
        $this->client->setTimeout($this->options['timeout']);
71 305
        $this->client->setVerifyPeer($this->options['verify_peer']);
72 305
    }
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
        }
83
84 8
        return $this->request($endpoint, $params, 'GET', $headers);
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90 1
    public function post($endpoint, $params = array(), $headers = array())
91
    {
92 1
        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 1
    public function delete($endpoint, $params = array(), $headers = array())
107
    {
108 1
        return $this->request($endpoint, $params, 'DELETE', $headers);
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114 14
    public function request($endpoint, $params = array(), $method = 'GET', array $headers = array())
115
    {
116
        //$request = $this->createRequest($method, $endpoint);
117 14
        $request = ($this->requestObj !== null) ? $this->requestObj : $this->createRequest($method, $endpoint);
118
119
        // add a default content-type if none was set
120 14
        if (empty($headers['Content-Type']) && in_array(strtoupper($method), array('POST', 'PUT'), true)) {
121 2
            $headers['Content-Type'] = 'application/x-www-form-urlencoded';
122
        }
123
124 14
        if (count($headers) > 0) {
125 8
            $request->addHeaders($headers);
126
        }
127
128 14
        if (count($params) > 0) {
129 4
            $request->setContent(is_array($params) ? http_build_query($params) : $params);
130
        }
131
132 14
        $response = is_object($this->responseObj) ? $this->responseObj : new Response();
133
134 14
        $this->executeListeners($request, 'preSend');
135
136 12
        $this->client->send($request, $response);
137
138 12
        $this->executeListeners($request, 'postSend', $response);
139
140 12
        $this->lastRequest  = $request;
141 12
        $this->lastResponse = $response;
142
143 12
        return $response;
144
    }
145
146
    /**
147
     * @access public
148
     * @return BuzzClientInterface
149
     */
150 1
    public function getClient()
151
    {
152 1
        return $this->client;
153
    }
154
155
    /**
156
     * {@inheritdoc}
157
     */
158 11
    public function getResponseFormat()
159
    {
160 11
        return $this->options['format'];
161
    }
162
163
    /**
164
     * {@inheritdoc}
165
     */
166 4
    public function setResponseFormat($format)
167
    {
168 4
        if (!in_array($format, $this->options['formats'], true)) {
169 2
            throw new \InvalidArgumentException(sprintf('Unsupported response format %s', $format));
170
        }
171
172 3
        $this->options['format'] = $format;
173
174 3
        return $this;
175
    }
176
177
    /**
178
     * {@inheritdoc}
179
     */
180 15
    public function getApiVersion()
181
    {
182 15
        return $this->options['api_version'];
183
    }
184
185
    /**
186
     * {@inheritdoc}
187
     */
188 99
    public function setApiVersion($version)
189
    {
190 99
        if (!in_array($version, $this->options['api_versions'], true)) {
191 8
            throw new \InvalidArgumentException(sprintf('Unsupported API version %s', $version));
192
        }
193
194 91
        $this->options['api_version'] = $version;
195
196 91
        return $this;
197
    }
198
199
    /**
200
     * Check if specified API version is the one currently in use.
201
     *
202
     * @access public
203
     * @param  float $version
204
     * @return bool
205
     */
206 1
    public function isApiVersion($version)
207
    {
208 1
        return abs($this->options['api_version'] - $version) < 0.00001;
209
    }
210
211
    /**
212
     * {@inheritdoc}
213
     */
214 14
    public function getApiBaseUrl()
215
    {
216 14
        return $this->options['base_url'].'/'.$this->getApiVersion();
217
    }
218
219
    /**
220
     * @access public
221
     * @return MessageInterface
222
     */
223 6
    public function getLastRequest()
224
    {
225 6
        return $this->lastRequest;
226
    }
227
228
    /**
229
     * @access public
230
     * @return RequestInterface
231
     */
232 2
    public function getLastResponse()
233
    {
234 2
        return $this->lastResponse;
235
    }
236
237
    /**
238
     * @access public
239
     * @param  MessageInterface $response
240
     * @return void
241
     */
242
    public function setResponse(MessageInterface $response)
243
    {
244
        $this->responseObj = $response;
245
    }
246
247
    /**
248
     * @access public
249
     * @param  RequestInterface $request
250
     * @return void
251
     */
252 1
    public function setRequest(RequestInterface $request)
253
    {
254 1
        $this->requestObj = $request;
255 1
    }
256
257
    /**
258
     * @access protected
259
     * @param  string           $method
260
     * @param  string           $url
261
     * @return RequestInterface
262
     */
263 13
    protected function createRequest($method, $url)
264
    {
265
        // do not set base URL if a full one was provided
266 13
        if (false === strpos($url, $this->getApiBaseUrl())) {
267 12
            $url = $this->getApiBaseUrl().'/'.$url;
268
        }
269
270
        // change the response format
271 13
        if ($this->getApiVersion() === '1.0' && strpos($url, 'format=') === false) {
272 8
            $url .= (strpos($url, '?') === false ? '?' : '&').'format='.$this->getResponseFormat();
273
        }
274
275 13
        $request = is_object($this->requestObj) ? $this->requestObj : new Request();
276 13
        $request->setMethod($method);
277 13
        $request->addHeaders(array(
278 13
                'User-Agent' => $this->options['user_agent']
279
            ));
280 13
        $request->setProtocolVersion(1.1);
281 13
        $request->fromUrl($url);
282
283 13
        return $request;
284
    }
285
286
    /**
287
     * Execute all available listeners.
288
     *
289
     * $when can be: preSend or postSend
290
     *
291
     * @access protected
292
     * @param RequestInterface $request
293
     * @param string           $when     When to execute the listener
294
     * @param MessageInterface $response
295
     */
296 14
    protected function executeListeners(RequestInterface $request, $when = 'preSend', MessageInterface $response = null)
297
    {
298 14
        $haveListeners  = count($this->listeners) > 0;
299
300 14
        if (!$haveListeners) {
301 8
            return;
302
        }
303
304 6
        $params = array($request);
305
306 6
        if (null !== $response) {
307 4
            $params[] = $response;
308
        }
309
310 6
        ksort($this->listeners, SORT_ASC);
311
312 6
        array_walk_recursive(
313 6
            $this->listeners,
314
            function ($class) use ($when, $params) {
315 6
                if ($class instanceof ListenerInterface) {
316 6
                    call_user_func_array(array($class, $when), $params);
317
                }
318 6
            }
319
        );
320 4
    }
321
}
322