Completed
Pull Request — 23 (#431)
by Harald
10:27
created

Http::_doUrlRequest()   D

Complexity

Conditions 12
Paths 240

Size

Total Lines 64
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 44
nc 240
nop 3
dl 0
loc 64
rs 4.6758
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace Braintree;
3
4
/**
5
 * Braintree HTTP Client
6
 * processes Http requests using curl
7
 *
8
 * @copyright  2015 Braintree, a division of PayPal, Inc.
9
 */
10
class Http
11
{
12
    protected $_config;
13
    private $_useClientCredentials = false;
14
15
    public function __construct($config)
16
    {
17
        $this->_config = $config;
18
    }
19
20 View Code Duplication
    public function delete($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
21
    {
22
        $response = $this->_doRequest('DELETE', $path);
23
        if($response['status'] === 200) {
24
            return true;
25
        } else {
26
            Util::throwStatusCodeException($response['status']);
27
        }
28
    }
29
30 View Code Duplication
    public function get($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
31
    {
32
        $response = $this->_doRequest('GET', $path);
33
        if ($response['status'] === 200) {
34
            return Xml::buildArrayFromXml($response['body']);
35
        } else {
36
            Util::throwStatusCodeException($response['status']);
37
        }
38
    }
39
40 View Code Duplication
    public function post($path, $params = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
41
    {
42
        $response = $this->_doRequest('POST', $path, $this->_buildXml($params));
43
        $responseCode = $response['status'];
44
        if($responseCode === 200 || $responseCode === 201 || $responseCode === 422 || $responseCode == 400) {
45
            return Xml::buildArrayFromXml($response['body']);
46
        } else {
47
            Util::throwStatusCodeException($responseCode);
48
        }
49
    }
50
51 View Code Duplication
    public function put($path, $params = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
52
    {
53
        $response = $this->_doRequest('PUT', $path, $this->_buildXml($params));
54
        $responseCode = $response['status'];
55
        if($responseCode === 200 || $responseCode === 201 || $responseCode === 422 || $responseCode == 400) {
56
            return Xml::buildArrayFromXml($response['body']);
57
        } else {
58
            Util::throwStatusCodeException($responseCode);
59
        }
60
    }
61
62
    private function _buildXml($params)
63
    {
64
        return empty($params) ? null : Xml::buildXmlFromArray($params);
65
    }
66
67
    private function _getHeaders()
68
    {
69
        return [
70
            'Accept: application/xml',
71
            'Content-Type: application/xml',
72
        ];
73
    }
74
75
    private function _getAuthorization()
76
    {
77
        if ($this->_useClientCredentials) {
78
            return [
79
                'user' => $this->_config->getClientId(),
80
                'password' => $this->_config->getClientSecret(),
81
            ];
82
        } else if ($this->_config->isAccessToken()) {
83
            return [
84
                'token' => $this->_config->getAccessToken(),
85
            ];
86
        } else {
87
            return [
88
                'user' => $this->_config->getPublicKey(),
89
                'password' => $this->_config->getPrivateKey(),
90
            ];
91
        }
92
    }
93
94
    public function useClientCredentials()
95
    {
96
        $this->_useClientCredentials = true;
97
    }
98
99
    private function _doRequest($httpVerb, $path, $requestBody = null)
100
    {
101
        return $this->_doUrlRequest($httpVerb, $this->_config->baseUrl() . $path, $requestBody);
102
    }
103
104
    public function _doUrlRequest($httpVerb, $url, $requestBody = null)
105
    {
106
        $curl = curl_init();
107
        curl_setopt($curl, CURLOPT_TIMEOUT, $this->_config->timeout());
108
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $httpVerb);
109
        curl_setopt($curl, CURLOPT_URL, $url);
110
        curl_setopt($curl, CURLOPT_ENCODING, 'gzip');
111
112
        $headers = $this->_getHeaders($curl);
0 ignored issues
show
Unused Code introduced by
The call to Http::_getHeaders() has too many arguments starting with $curl.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
113
        $headers[] = 'User-Agent: Braintree PHP Library ' . Version::get();
114
        $headers[] = 'X-ApiVersion: ' . Configuration::API_VERSION;
115
116
        $authorization = $this->_getAuthorization();
117
        if (isset($authorization['user'])) {
118
            curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
119
            curl_setopt($curl, CURLOPT_USERPWD, $authorization['user'] . ':' . $authorization['password']);
120
        } else if (isset($authorization['token'])) {
121
            $headers[] = 'Authorization: Bearer ' . $authorization['token'];
122
        }
123
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
124
125
        // curl_setopt($curl, CURLOPT_VERBOSE, true);
126
        if ($this->_config->sslOn()) {
127
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
128
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
129
            curl_setopt($curl, CURLOPT_CAINFO, $this->getCaFile());
130
        }
131
132
        if(!empty($requestBody)) {
133
            curl_setopt($curl, CURLOPT_POSTFIELDS, $requestBody);
134
        }
135
136
        if($this->_config->isUsingProxy()) {
137
            $proxyHost = $this->_config->getProxyHost();
138
            $proxyPort = $this->_config->getProxyPort();
139
            $proxyType = $this->_config->getProxyType();
140
            $proxyUser = $this->_config->getProxyUser();
141
            $proxyPwd= $this->_config->getProxyPassword();
142
            curl_setopt($curl, CURLOPT_PROXY, $proxyHost . ':' . $proxyPort);
143
            if(!empty($proxyType)) {
144
                curl_setopt($curl, CURLOPT_PROXYTYPE, $proxyType);
145
            }
146
            if($this->_config->isAuthenticatedProxy()) {
147
                curl_setopt($curl, CURLOPT_PROXYUSERPWD, $proxyUser . ':' . $proxyPwd);
148
            }
149
        }
150
151
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
152
        $response = curl_exec($curl);
153
        $httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
154
        $error_code = curl_errno($curl);
155
156
        if ($error_code == 28 && $httpStatus == 0) {
157
            throw new Exception\Timeout();
158
        }
159
160
        curl_close($curl);
161
        if ($this->_config->sslOn()) {
162
            if ($httpStatus == 0) {
163
                throw new Exception\SSLCertificate();
164
            }
165
        }
166
        return ['status' => $httpStatus, 'body' => $response];
167
    }
168
169
    private function getCaFile()
170
    {
171
        static $memo;
172
173
        if ($memo === null) {
174
            $caFile = $this->_config->caFile();
175
176
            if (substr($caFile, 0, 7) !== 'phar://') {
177
                return $caFile;
178
            }
179
180
            $extractedCaFile = sys_get_temp_dir() . '/api_braintreegateway_com.ca.crt';
181
182
            if (!file_exists($extractedCaFile) || sha1_file($extractedCaFile) != sha1_file($caFile)) {
183
                if (!copy($caFile, $extractedCaFile)) {
184
                    throw new Exception\SSLCaFileNotFound();
185
                }
186
            }
187
            $memo = $extractedCaFile;
188
        }
189
190
        return $memo;
191
    }
192
}
193
class_alias('Braintree\Http', 'Braintree_Http');
194