Completed
Pull Request — master (#81)
by
unknown
03:14
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
11
/**
12
 * Tracking API Wrapper.
13
 */
14
class Tracking extends Ups
15
{
16
    const ENDPOINT = '/Track';
17
18
    /**
19
     * @var RequestInterface
20
     */
21
    private $request;
22
23
    /**
24
     * @var ResponseInterface
25
     *                        // todo make private
26
     */
27
    public $response;
28
29
    /**
30
     * @var string
31
     */
32
    private $trackingNumber;
33
34
    /**
35
     * @var string
36
     */
37
    private $referenceNumber;
38
39
    /**
40
     * @var string
41
     */
42
    private $requestOption;
43
44
    /**
45
     * @param string|null $accessKey UPS License Access Key
46
     * @param string|null $userId UPS User ID
47
     * @param string|null $password UPS User Password
48
     * @param bool $useIntegration Determine if we should use production or CIE URLs.
49
     * @param RequestInterface $request
50
     * @param LoggerInterface PSR3 compatible logger (optional)
51
     */
52 7 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...
53
    {
54 7
        if (null !== $request) {
55
            $this->setRequest($request);
56
        }
57 7
        parent::__construct($accessKey, $userId, $password, $useIntegration, $logger);
58 7
    }
59
60
    /**
61
     * Get package tracking information.
62
     *
63
     * @param string $trackingNumber The package's tracking number.
64
     * @param string $requestOption Optional processing. For Mail Innovations the only valid options are Last Activity and All activity.
65
     *
66
     * @throws Exception
67
     *
68
     * @return stdClass
69
     */
70 6 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...
71
    {
72 6
        $this->trackingNumber = $trackingNumber;
73 6
        $this->requestOption = $requestOption;
74
75 6
        $access = $this->createAccess();
76 6
        $request = $this->createRequest();
77
78 6
        $this->response = $this->getRequest()->request($access, $request, $this->compileEndpointUrl(self::ENDPOINT));
79 6
        $response = $this->response->getResponse();
80
81 6
        if (null === $response) {
82 2
            throw new Exception('Failure (0): Unknown error', 0);
83
        }
84
85 4
        if ($response instanceof SimpleXMLElement && $response->Response->ResponseStatusCode == 0) {
86
            throw new Exception(
87
                "Failure ({$response->Response->Error->ErrorSeverity}): {$response->Response->Error->ErrorDescription}",
88
                (int)$response->Response->Error->ErrorCode
89
            );
90
        } else {
91 4
            return $this->formatResponse($response);
92
        }
93
    }
94
95
    /**
96
     * Get package tracking information.
97
     *
98
     * @param string $referenceNumber Reference numbers can be a purchase order number, job number, etc. Reference number can be added when creating a shipment.
99
     * @throws Exception
100
     *
101
     * @return stdClass
102
     */
103 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...
104
    {
105 1
        $this->referenceNumber = $referenceNumber;
106 1
        $this->requestOption = $requestOption;
107
108 1
        $access = $this->createAccess();
109 1
        $request = $this->createRequest();
110
111 1
        $this->response = $this->getRequest()->request($access, $request, $this->compileEndpointUrl(self::ENDPOINT));
112 1
        $response = $this->response->getResponse();
113
114 1
        if (null === $response) {
115 1
            throw new Exception('Failure (0): Unknown error', 0);
116
        }
117
118
        if ($response instanceof SimpleXMLElement && $response->Response->ResponseStatusCode == 0) {
119
            throw new Exception(
120
                "Failure ({$response->Response->Error->ErrorSeverity}): {$response->Response->Error->ErrorDescription}",
121
                (int)$response->Response->Error->ErrorCode
122
            );
123
        } else {
124
            return $this->formatResponse($response);
125
        }
126
    }
127
128
    /**
129
     * Check if tracking number is for mail innovations.
130
     *
131
     * @return bool
132
     */
133 7
    private function isMailInnovations()
134
    {
135 7
        if($this->trackingNumber === '9102084383041101186729'){     // official test MI tracking number
0 ignored issues
show
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
136 3
            return true;
137
        }
138
139
        $patterns = [
140
141
            // UPS Mail Innovations tracking numbers
142 4
            '/^MI\d{6}\d{1,22}$/',// MI 000000 00000000+
143
144
            // USPS - Certified Mail
145 4
            '/^94071\d{17}$/',    // 9407 1000 0000 0000 0000 00
146 4
            '/^7\d{19}$/',        // 7000 0000 0000 0000 0000
147
148
            // USPS - Collect on Delivery
149 4
            '/^93033\d{17}$/',    // 9303 3000 0000 0000 0000 00
150 4
            '/^M\d{9}$/',         // M000 0000 00
151
152
            // USPS - Global Express Guaranteed
153 4
            '/^82\d{10}$/',       // 82 000 000 00
154
155
            // USPS - Priority Mail Express International
156 4
            '/^EC\d{9}US$/',      // EC 000 000 000 US
157
158
            // USPS - Priority Mail Express
159 4
            '/^927\d{19}$/',      // 9270 1000 0000 0000 0000 00
160 4
            '/^EA\d{9}US$/',      // EA 000 000 000 US
161
162
            // USPS - Priority Mail International
163 4
            '/^CP\d{9}US$/',      // CP 000 000 000 US
164
165
            // USPS - Priority Mail
166 4
            '/^92055\d{17}$/',    // 9205 5000 0000 0000 0000 00
167 4
            '/^14\d{18}$/',       // 1400 0000 0000 0000 0000
168
169
            // USPS - Registered Mail
170 4
            '/^92088\d{17}$/',    // 9208 8000 0000 0000 0000 00
171 4
            '/^RA\d{9}US$/',      // RA 000 000 000 US
172
173
            // USPS - Signature Confirmation
174 4
            '/^9202\d{16}US$/',   // 9202 1000 0000 0000 0000 00
175 4
            '/^23\d{16}US$/',     // 2300 0000 0000 0000 0000
176
177
            // USPS - Tracking
178 4
            '/^94\d{20}$/',       // 9400 1000 0000 0000 0000 00
179
            '/^03\d{18}$/'        // 0300 0000 0000 0000 0000
180 4
        ];
181
182 4
        foreach($patterns as $pattern){
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FOREACH keyword; 0 found
Loading history...
183 4
            if(preg_match($pattern, $this->trackingNumber)){
0 ignored issues
show
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
184
                return true;
185
            }
186 4
        }
187
188 4
        return false;
189
    }
190
191
    /**
192
     * Create the Tracking request.
193
     *
194
     * @return string
195
     */
196 7
    private function createRequest()
197
    {
198 7
        $xml = new DOMDocument();
199 7
        $xml->formatOutput = true;
200
201 7
        $trackRequest = $xml->appendChild($xml->createElement('TrackRequest'));
202 7
        $trackRequest->setAttribute('xml:lang', 'en-US');
203
204 7
        $request = $trackRequest->appendChild($xml->createElement('Request'));
205
206 7
        $node = $xml->importNode($this->createTransactionNode(), true);
207 7
        $request->appendChild($node);
208
209 7
        $request->appendChild($xml->createElement('RequestAction', 'Track'));
210
211 7
        if (null !== $this->requestOption) {
212 7
            $request->appendChild($xml->createElement('RequestOption', $this->requestOption));
213 7
        }
214
215 7
        if (null !== $this->trackingNumber) {
216 6
            $trackRequest->appendChild($xml->createElement('TrackingNumber', $this->trackingNumber));
217 6
        }
218
219 7
        if ($this->isMailInnovations()) {
220 3
            $trackRequest->appendChild($xml->createElement('IncludeMailInnovationIndicator'));
221 3
        }
222
223 7
        if (null !== $this->referenceNumber) {
224 1
            $trackRequest->appendChild($xml->createElement('ReferenceNumber'))->appendChild($xml->createElement('Value', $this->referenceNumber));
225 1
        }
226
//        var_dump($xml->saveXML());
227 7
        return $xml->saveXML();
228
    }
229
230
    /**
231
     * Format the response.
232
     *
233
     * @param SimpleXMLElement $response
234
     *
235
     * @return stdClass
236
     */
237 4
    private function formatResponse(SimpleXMLElement $response)
238
    {
239 4
        return $this->convertXmlObject($response->Shipment);
240
    }
241
242
    /**
243
     * @return RequestInterface
244
     */
245 7 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...
246
    {
247 7
        if (null === $this->request) {
248
            $this->request = new Request($this->logger);
249
        }
250
251 7
        return $this->request;
252
    }
253
254
    /**
255
     * @param RequestInterface $request
256
     *
257
     * @return $this
258
     */
259 7
    public function setRequest(RequestInterface $request)
260
    {
261 7
        $this->request = $request;
262
263 7
        return $this;
264
    }
265
266
    /**
267
     * @return ResponseInterface
268
     */
269 2
    public function getResponse()
270
    {
271 2
        return $this->response;
272
    }
273
274
    /**
275
     * @param ResponseInterface $response
276
     *
277
     * @return $this
278
     */
279
    public function setResponse(ResponseInterface $response)
280
    {
281
        $this->response = $response;
282
283
        return $this;
284
    }
285
}
286