Completed
Push — master ( cb556d...3ecce5 )
by Stefan
29s
created

Tracking::formatResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Ups;
4
5
use DOMDocument;
6
use Exception;
7
use Psr\Log\LoggerInterface;
8
use SimpleXMLElement;
9
use stdClass;
10
use DateTime;
11
12
/**
13
 * Tracking API Wrapper.
14
 */
15
class Tracking extends Ups
16
{
17
    const ENDPOINT = '/Track';
18
19
    /**
20
     * @var RequestInterface
21
     */
22
    private $request;
23
24
    /**
25
     * @var ResponseInterface
26
     *                        // todo make private
27
     */
28
    public $response;
29
30
    /**
31
     * @var string
32
     */
33
    private $trackingNumber;
34
35
    /**
36
     * @var string
37
     */
38
    private $referenceNumber;
39
40
    /**
41
     * @var string
42
     */
43
    private $requestOption;
44
45
    /**
46
     * @var string
47
     */
48
    private $shipperNumber;
49
50
    /**
51
     * @var \DateTime
52
     */
53
    private $beginDate;
54
55
    /**
56
     * @var \DateTime
57
     */
58
    private $endDate;
59
60
    /**
61
     * @param string|null $accessKey UPS License Access Key
62
     * @param string|null $userId UPS User ID
63
     * @param string|null $password UPS User Password
64
     * @param bool $useIntegration Determine if we should use production or CIE URLs.
65
     * @param RequestInterface|null $request
66
     * @param LoggerInterface|null $logger PSR3 compatible logger (optional)
67
     */
68 6 View Code Duplication
    public function __construct($accessKey = null, $userId = null, $password = null, $useIntegration = false, RequestInterface $request = null, LoggerInterface $logger = 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...
69
    {
70 6
        if (null !== $request) {
71
            $this->setRequest($request);
72
        }
73 6
        parent::__construct($accessKey, $userId, $password, $useIntegration, $logger);
74 6
    }
75
76
    /**
77
     * Get package tracking information.
78
     *
79
     * @param string $trackingNumber The package's tracking number.
80
     * @param string $requestOption Optional processing. For Mail Innovations the only valid options are Last Activity and All activity.
81
     *
82
     * @throws Exception
83
     *
84
     * @return stdClass
85
     */
86 5 View Code Duplication
    public function track($trackingNumber, $requestOption = 'activity')
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...
87
    {
88 5
        $this->trackingNumber = $trackingNumber;
89 5
        $this->requestOption = $requestOption;
90
91 5
        $access = $this->createAccess();
92 5
        $request = $this->createRequest();
93
94 5
        $this->response = $this->getRequest()->request($access, $request, $this->compileEndpointUrl(self::ENDPOINT));
95 5
        $response = $this->response->getResponse();
96
97 5
        if (null === $response) {
98 2
            throw new Exception('Failure (0): Unknown error', 0);
99
        }
100
101 3
        if ($response instanceof SimpleXMLElement && $response->Response->ResponseStatusCode == 0) {
102
            throw new Exception(
103
                "Failure ({$response->Response->Error->ErrorSeverity}): {$response->Response->Error->ErrorDescription}",
104
                (int)$response->Response->Error->ErrorCode
105
            );
106
        } else {
107 3
            return $this->formatResponse($response);
108
        }
109
    }
110
111
    /**
112
     * Get package tracking information.
113
     *
114
     * @param string $referenceNumber Reference numbers can be a purchase order number, job number, etc. Reference number can be added when creating a shipment.
115
     * @param string $requestOption
116
     *
117
     * @throws Exception
118
     *
119
     * @return stdClass
120
     */
121 1 View Code Duplication
    public function trackByReference($referenceNumber, $requestOption = 'activity')
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...
122
    {
123 1
        $this->referenceNumber = $referenceNumber;
124 1
        $this->requestOption = $requestOption;
125
126 1
        $access = $this->createAccess();
127 1
        $request = $this->createRequest();
128
129 1
        $this->response = $this->getRequest()->request($access, $request, $this->compileEndpointUrl(self::ENDPOINT));
130 1
        $response = $this->response->getResponse();
131
132 1
        if (null === $response) {
133 1
            throw new Exception('Failure (0): Unknown error', 0);
134
        }
135
136
        if ($response instanceof SimpleXMLElement && $response->Response->ResponseStatusCode == 0) {
137
            throw new Exception(
138
                "Failure ({$response->Response->Error->ErrorSeverity}): {$response->Response->Error->ErrorDescription}",
139
                (int)$response->Response->Error->ErrorCode
140
            );
141
        } else {
142
            return $this->formatResponse($response);
143
        }
144
    }
145
146
    /**
147
     * Set shipper number
148
     *
149
     * @param string $shipperNumber
150
     *
151
     */
152
    public function setShipperNumber($shipperNumber)
153
    {
154
        $this->shipperNumber = $shipperNumber;
155
    }
156
157
    /**
158
     * Set begin date
159
     *
160
     * @param string $beginDate
161
     *
162
     */
163
    public function setBeginDate(DateTime $beginDate)
164
    {
165
        $this->beginDate = $beginDate;
166
    }
167
168
    /**
169
     * Set end date
170
     *
171
     * @param string $endDate
172
     *
173
     */
174
    public function setEndDate(DateTime $endDate)
175
    {
176
        $this->endDate = $endDate;
177
    }
178
179
    /**
180
     * Check if tracking number is for mail innovations.
181
     *
182
     * @return bool
183
     */
184 6
    private function isMailInnovations()
185
    {
186
        $patterns = [
187
188
            // UPS Mail Innovations tracking numbers
189 6
            '/^MI\d{6}\d{1,22}$/',// MI 000000 00000000+
190
191
            // USPS - Certified Mail
192 6
            '/^94071\d{17}$/',    // 9407 1000 0000 0000 0000 00
193 6
            '/^7\d{19}$/',        // 7000 0000 0000 0000 0000
194
195
            // USPS - Collect on Delivery
196 6
            '/^93033\d{17}$/',    // 9303 3000 0000 0000 0000 00
197 6
            '/^M\d{9}$/',         // M000 0000 00
198
199
            // USPS - Global Express Guaranteed
200 6
            '/^82\d{10}$/',       // 82 000 000 00
201
202
            // USPS - Priority Mail Express International
203 6
            '/^EC\d{9}US$/',      // EC 000 000 000 US
204
205
            // USPS - Priority Mail Express
206 6
            '/^927\d{19}$/',      // 9270 1000 0000 0000 0000 00
207 6
            '/^EA\d{9}US$/',      // EA 000 000 000 US
208
209
            // USPS - Priority Mail International
210 6
            '/^CP\d{9}US$/',      // CP 000 000 000 US
211
212
            // USPS - Priority Mail
213 6
            '/^92055\d{17}$/',    // 9205 5000 0000 0000 0000 00
214 6
            '/^14\d{18}$/',       // 1400 0000 0000 0000 0000
215
216
            // USPS - Registered Mail
217 6
            '/^92088\d{17}$/',    // 9208 8000 0000 0000 0000 00
218 6
            '/^RA\d{9}US$/',      // RA 000 000 000 US
219
220
            // USPS - Signature Confirmation
221 6
            '/^9202\d{16}US$/',   // 9202 1000 0000 0000 0000 00
222 6
            '/^23\d{16}US$/',     // 2300 0000 0000 0000 0000
223
224
            // USPS - Tracking
225 6
            '/^94\d{20}$/',       // 9400 1000 0000 0000 0000 00
226
            '/^03\d{18}$/'        // 0300 0000 0000 0000 0000
227 6
        ];
228
229 6
        foreach ($patterns as $pattern) {
230 6
            if (preg_match($pattern, $this->trackingNumber)) {
231 1
                return true;
232
            }
233 6
        }
234
235 5
        return false;
236
    }
237
238
    /**
239
     * Create the Tracking request.
240
     *
241
     * @return string
242
     */
243 6
    private function createRequest()
244
    {
245 6
        $xml = new DOMDocument();
246 6
        $xml->formatOutput = true;
247
248 6
        $trackRequest = $xml->appendChild($xml->createElement('TrackRequest'));
249 6
        $trackRequest->setAttribute('xml:lang', 'en-US');
250
251 6
        $request = $trackRequest->appendChild($xml->createElement('Request'));
252
253 6
        $node = $xml->importNode($this->createTransactionNode(), true);
254 6
        $request->appendChild($node);
255
256 6
        $request->appendChild($xml->createElement('RequestAction', 'Track'));
257
258 6
        if (null !== $this->requestOption) {
259 6
            $request->appendChild($xml->createElement('RequestOption', $this->requestOption));
260 6
        }
261
262 6
        if (null !== $this->trackingNumber) {
263 5
            $trackRequest->appendChild($xml->createElement('TrackingNumber', $this->trackingNumber));
264 5
        }
265
266 6
        if ($this->isMailInnovations()) {
267 1
            $trackRequest->appendChild($xml->createElement('IncludeMailInnovationIndicator'));
268 1
        }
269
270 6
        if (null !== $this->referenceNumber) {
271 1
            $trackRequest->appendChild($xml->createElement('ReferenceNumber'))->appendChild($xml->createElement('Value', $this->referenceNumber));
272 1
        }
273
274 6
        if (null !== $this->shipperNumber) {
275
            $trackRequest->appendChild($xml->createElement('ShipperNumber', $this->shipperNumber));
276
        }
277
278 6
        if (null !== $this->beginDate) {
279
            $beginDate = $this->beginDate->format('Ymd');
280
            $trackRequest->appendChild($xml->createElement('BeginDate', $beginDate));
281
        }
282
283 6
        if (null !== $this->endDate) {
284
            $endDate = $this->endDate->format('Ymd');
285
            $trackRequest->appendChild($xml->createElement('EndDate', $endDate));
286
        }
287
288 6
        return $xml->saveXML();
289
    }
290
291
    /**
292
     * Format the response.
293
     *
294
     * @param SimpleXMLElement $response
295
     *
296
     * @return stdClass
297
     */
298 3
    private function formatResponse(SimpleXMLElement $response)
299
    {
300 3
        return $this->convertXmlObject($response->Shipment);
301
    }
302
303
    /**
304
     * @return RequestInterface
305
     */
306 6 View Code Duplication
    public function getRequest()
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...
307
    {
308 6
        if (null === $this->request) {
309
            $this->request = new Request($this->logger);
310
        }
311
312 6
        return $this->request;
313
    }
314
315
    /**
316
     * @param RequestInterface $request
317
     *
318
     * @return $this
319
     */
320 6
    public function setRequest(RequestInterface $request)
321
    {
322 6
        $this->request = $request;
323
324 6
        return $this;
325
    }
326
327
    /**
328
     * @return ResponseInterface
329
     */
330 2
    public function getResponse()
331
    {
332 2
        return $this->response;
333
    }
334
335
    /**
336
     * @param ResponseInterface $response
337
     *
338
     * @return $this
339
     */
340
    public function setResponse(ResponseInterface $response)
341
    {
342
        $this->response = $response;
343
344
        return $this;
345
    }
346
}
347