Completed
Pull Request — master (#81)
by
unknown
03:42
created

Tracking::trackByReference()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 24
Code Lines 15

Duplication

Lines 24
Ratio 100 %

Code Coverage

Tests 9
CRAP Score 5.024

Importance

Changes 3
Bugs 1 Features 1
Metric Value
c 3
b 1
f 1
dl 24
loc 24
ccs 9
cts 15
cp 0.6
rs 8.6845
cc 4
eloc 15
nc 3
nop 2
crap 5.024
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 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...
53
    {
54 6
        if (null !== $request) {
55
            $this->setRequest($request);
56
        }
57 6
        parent::__construct($accessKey, $userId, $password, $useIntegration, $logger);
58 6
    }
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 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...
71
    {
72 5
        $this->trackingNumber = $trackingNumber;
73 5
        $this->requestOption = $requestOption;
74
75 5
        $access = $this->createAccess();
76 5
        $request = $this->createRequest();
77
78 5
        $this->response = $this->getRequest()->request($access, $request, $this->compileEndpointUrl(self::ENDPOINT));
79 5
        $response = $this->response->getResponse();
80
81 5
        if (null === $response) {
82 2
            throw new Exception('Failure (0): Unknown error', 0);
83
        }
84
85 3
        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 3
            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 6
    private function isMailInnovations()
134
    {
135
136
        $patterns = [
137
138
            // UPS Mail Innovations tracking numbers
139 6
            '/^MI\d{6}\d{1,22}$/',// MI 000000 00000000+
140
141
            // USPS - Certified Mail
142 6
            '/^94071\d{17}$/',    // 9407 1000 0000 0000 0000 00
143 6
            '/^7\d{19}$/',        // 7000 0000 0000 0000 0000
144
145
            // USPS - Collect on Delivery
146 6
            '/^93033\d{17}$/',    // 9303 3000 0000 0000 0000 00
147 6
            '/^M\d{9}$/',         // M000 0000 00
148
149
            // USPS - Global Express Guaranteed
150 6
            '/^82\d{10}$/',       // 82 000 000 00
151
152
            // USPS - Priority Mail Express International
153 6
            '/^EC\d{9}US$/',      // EC 000 000 000 US
154
155
            // USPS - Priority Mail Express
156 6
            '/^927\d{19}$/',      // 9270 1000 0000 0000 0000 00
157 6
            '/^EA\d{9}US$/',      // EA 000 000 000 US
158
159
            // USPS - Priority Mail International
160 6
            '/^CP\d{9}US$/',      // CP 000 000 000 US
161
162
            // USPS - Priority Mail
163 6
            '/^92055\d{17}$/',    // 9205 5000 0000 0000 0000 00
164 6
            '/^14\d{18}$/',       // 1400 0000 0000 0000 0000
165
166
            // USPS - Registered Mail
167 6
            '/^92088\d{17}$/',    // 9208 8000 0000 0000 0000 00
168 6
            '/^RA\d{9}US$/',      // RA 000 000 000 US
169
170
            // USPS - Signature Confirmation
171 6
            '/^9202\d{16}US$/',   // 9202 1000 0000 0000 0000 00
172 6
            '/^23\d{16}US$/',     // 2300 0000 0000 0000 0000
173
174
            // USPS - Tracking
175 6
            '/^94\d{20}$/',       // 9400 1000 0000 0000 0000 00
176
            '/^03\d{18}$/'        // 0300 0000 0000 0000 0000
177 6
        ];
178
179 6
        foreach ($patterns as $pattern) {
180 6
            if (preg_match($pattern, $this->trackingNumber)) {
181 1
                return true;
182
            }
183 6
        }
184
185 5
        return false;
186
    }
187
188
    /**
189
     * Create the Tracking request.
190
     *
191
     * @return string
192
     */
193 6
    private function createRequest()
194
    {
195 6
        $xml = new DOMDocument();
196 6
        $xml->formatOutput = true;
197
198 6
        $trackRequest = $xml->appendChild($xml->createElement('TrackRequest'));
199 6
        $trackRequest->setAttribute('xml:lang', 'en-US');
200
201 6
        $request = $trackRequest->appendChild($xml->createElement('Request'));
202
203 6
        $node = $xml->importNode($this->createTransactionNode(), true);
204 6
        $request->appendChild($node);
205
206 6
        $request->appendChild($xml->createElement('RequestAction', 'Track'));
207
208 6
        if (null !== $this->requestOption) {
209 6
            $request->appendChild($xml->createElement('RequestOption', $this->requestOption));
210 6
        }
211
212 6
        if (null !== $this->trackingNumber) {
213 5
            $trackRequest->appendChild($xml->createElement('TrackingNumber', $this->trackingNumber));
214 5
        }
215
216 6
        if ($this->isMailInnovations()) {
217 1
            $trackRequest->appendChild($xml->createElement('IncludeMailInnovationIndicator'));
218 1
        }
219
220 6
        if (null !== $this->referenceNumber) {
221 1
            $trackRequest->appendChild($xml->createElement('ReferenceNumber'))->appendChild($xml->createElement('Value', $this->referenceNumber));
222 1
        }
223 6
        return $xml->saveXML();
224
    }
225
226
    /**
227
     * Format the response.
228
     *
229
     * @param SimpleXMLElement $response
230
     *
231
     * @return stdClass
232
     */
233 3
    private function formatResponse(SimpleXMLElement $response)
234
    {
235 3
        return $this->convertXmlObject($response->Shipment);
236
    }
237
238
    /**
239
     * @return RequestInterface
240
     */
241 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...
242
    {
243 6
        if (null === $this->request) {
244
            $this->request = new Request($this->logger);
245
        }
246
247 6
        return $this->request;
248
    }
249
250
    /**
251
     * @param RequestInterface $request
252
     *
253
     * @return $this
254
     */
255 6
    public function setRequest(RequestInterface $request)
256
    {
257 6
        $this->request = $request;
258
259 6
        return $this;
260
    }
261
262
    /**
263
     * @return ResponseInterface
264
     */
265 2
    public function getResponse()
266
    {
267 2
        return $this->response;
268
    }
269
270
    /**
271
     * @param ResponseInterface $response
272
     *
273
     * @return $this
274
     */
275
    public function setResponse(ResponseInterface $response)
276
    {
277
        $this->response = $response;
278
279
        return $this;
280
    }
281
}
282