Request::sendRequest()   C
last analyzed

Complexity

Conditions 9
Paths 15

Size

Total Lines 64
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 40
c 1
b 0
f 0
nc 15
nop 0
dl 0
loc 64
rs 6.5449

How to fix   Long Method   

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 namespace SimpleUPS\Api;
2
3
use SimpleUPS\UPS;
4
5
/**
6
 * @internal
7
 */
8
abstract class Request
9
{
10
    const
11
        REQUEST_SUCCESSFUL = 1,
12
        REQUEST_FAIL = 0;
13
14
    private
15
        $debug = false,
16
        $timeout = 4;
17
18
    protected
19
        $xmlLang = 'en-US',
20
        $xpciVersion = '1.0001',
21
        $customerContext = 'SimpleUPS',
22
        $responseClass,
23
24
        $accessLicenseNumber,
25
        $userId,
26
        $password;
27
28
    public function __construct($debug = null)
29
    {
30
        if ($debug == null) {
31
            $this->debug = UPS::getDebug();
32
        }
33
34
        $loadedExtensions = get_loaded_extensions();
35
        if (!in_array('curl', $loadedExtensions)) {
36
            throw new \Exception('CURL extension must be installed in order to use ' . UPS::$libraryName);
37
        }
38
        if (!in_array('dom', $loadedExtensions)) {
39
            throw new \Exception('DOM extension must be installed in order to use ' . UPS::$libraryName);
40
        }
41
        if (!in_array('SimpleXML', $loadedExtensions)) {
42
            throw new \Exception('SimpleXML extension must be installed in order to use ' . UPS::$libraryName);
43
        }
44
        if (!in_array('date', $loadedExtensions)) {
45
            throw new \Exception('Date extension must be installed in order to use ' . UPS::$libraryName);
46
        }
47
        if (version_compare(PHP_VERSION, '5.3.0') < 1) {
48
            throw new \Exception(UPS::$libraryName . ' requires at least PHP version 5.3');
49
        }
50
        unset($loadedExtensions);
51
        $this->setAccessLicenseNumber(UPS::getAccessLicenseNumber());
52
        $this->setUserId(UPS::getUserId());
53
        $this->setPassword(UPS::getPassword());
54
55
        libxml_use_internal_errors(true);
56
    }
57
58
    /**
59
     * Build the request XML
60
     * @return string
61
     */
62
    abstract public function buildXml();
63
64
    /**
65
     * Get the URL for this request
66
     * @return string
67
     */
68
    abstract public function getUrl();
69
70
    /**
71
     * Build the authentication XML for a UPS API request
72
     * @throws AuthenticationException
73
     * @return string
74
     */
75
    protected function buildAuthenticationXml()
76
    {
77
        if (strlen($this->getAccessLicenseNumber()) == 0 || $this->getAccessLicenseNumber() === null) {
78
            throw new AuthenticationException('Authenticated requests require an access license number');
79
        }
80
81
        if (strlen($this->getUserId()) == 0 || $this->getUserId() === null) {
82
            throw new AuthenticationException('Authenticated requests require a user id');
83
        }
84
85
        if (strlen($this->getPassword()) == 0 || $this->getPassword() === null) {
86
            throw new AuthenticationException('Authenticated requests require a password');
87
        }
88
89
        //@todo What about account number?
90
91
        $dom = new \DomDocument('1.0');
92
        $dom->formatOutput = $this->getDebug();
93
        $dom->appendChild($accessRequest = $dom->createElement('AccessRequest'));
94
        $accessRequest->appendChild($request = $dom->createElement('AccessLicenseNumber', $this->accessLicenseNumber));
95
        $accessRequest->appendChild($request = $dom->createElement('UserId', $this->userId));
96
        $accessRequest->appendChild($request = $dom->createElement('Password', $this->password));
97
98
        return $dom->saveXML();
99
    }
100
101
    /**
102
     * Perform the request and get the response XML for a given request
103
     * @return Response|\SimpleXMLElement Returns SimpleXMLElement when response class is omitted
104
     * @throws \SimpleUPS\Api\InvalidResponseException
105
     * @throws \SimpleUPS\Api\RequestFailedException
106
     * @throws \SimpleUPS\Api\ResponseErrorException
107
     * @throws \SimpleUPS\Api\MissingParameterException
108
     */
109
    public function sendRequest()
110
    {
111
        try {
112
            $xml = $this->buildXml();
113
        } catch (\SimpleUPS\Api\MissingParameterException $e) {
114
            throw new \SimpleUPS\Api\MissingParameterException($e->getMessage());
115
        }
116
117
        $ch = curl_init();
118
        curl_setopt($ch, CURLOPT_URL, $this->getUrl());
119
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
120
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
121
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
122
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
123
124
        $result = curl_exec($ch);
125
126
        if (curl_errno($ch)) {
127
            throw new \SimpleUPS\Api\RequestFailedException('#' . curl_errno($ch) . ': ' . curl_error($ch));
128
        } else {
129
            $returnCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
130
131
            if ($returnCode != 200) {
132
                throw new \SimpleUPS\Api\RequestFailedException('Request returned header: ' . $returnCode);
133
            }
134
        }
135
136
        curl_close($ch);
137
138
        if ($this->getDebug()) {
139
            UPS::$request = $this;
140
141
            $dom = new \DOMDocument();
142
            $dom->preserveWhiteSpace = false;
143
            $dom->formatOutput = true;
144
145
            //if xml fails to load, still record the response even if it's not formatted
146
            if ($dom->loadXML($result)) {
147
                UPS::$response = $dom->saveXML();
148
            } else {
149
                UPS::$response = $result;
150
            }
151
        }
152
153
        try {
154
            $xml = new \SimpleXMLElement($result);
155
            if ($xml === false) {
156
                throw new \Exception();
157
            }
158
        } catch (\Exception $e) {
159
            throw new \SimpleUPS\Api\InvalidResponseException('Unable to parse XML response');
160
        }
161
162
        $this->handleResponseErrors($xml);
163
164
        if ($this->responseClass === false) {
165
            return $xml;
166
        }
167
168
        $response = new $this->responseClass();
169
        $response->fromXml($xml);
170
171
        return $response;
172
    }
173
174
    /**
175
     * Throw any errors if needed based on the response
176
     *
177
     * @param \SimpleXML $xml
178
     *
179
     * @throws ResponseErrorException
180
     */
181
    public function handleResponseErrors(\SimpleXMLElement $xml)
182
    {
183
        if ($xml->Response->ResponseStatusCode == Request::REQUEST_FAIL) {
184
            throw new \SimpleUPS\Api\ResponseErrorException(
185
                $xml->Response->Error->ErrorDescription,
186
                (int)$xml->Response->Error->ErrorCode,
187
                (int)$xml->Response->Error->ErrorSeverity
188
            );
189
        }
190
    }
191
192
    protected function getCustomerContext()
193
    {
194
        return $this->customerContext;
195
    }
196
197
    protected function getXmlLang()
198
    {
199
        return $this->xmlLang;
200
    }
201
202
    protected function getXpciVersion()
203
    {
204
        return $this->xpciVersion;
205
    }
206
207
    public function setAccessLicenseNumber($accessLicenseNumber)
208
    {
209
        $this->accessLicenseNumber = $accessLicenseNumber;
210
    }
211
212
    public function getAccessLicenseNumber()
213
    {
214
        return $this->accessLicenseNumber;
215
    }
216
217
    public function setPassword($password)
218
    {
219
        $this->password = $password;
220
    }
221
222
    public function getPassword()
223
    {
224
        return $this->password;
225
    }
226
227
    public function setUserId($userId)
228
    {
229
        $this->userId = $userId;
230
    }
231
232
    public function getUserId()
233
    {
234
        return $this->userId;
235
    }
236
237
    public function setDebug($debug)
238
    {
239
        $this->debug = $debug;
240
    }
241
242
    public function getDebug()
243
    {
244
        return $this->debug;
245
    }
246
247
    public function __destruct()
248
    {
249
        libxml_use_internal_errors(false);
250
    }
251
}