Completed
Push — master ( 79d74a...43d504 )
by Stefan
05:34
created

Tracking::setEndDate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
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
     *
26
     * Workaround flag to handle Multiple shipment nodes in tracking response
27
     * See GitHub Issue #117
28
     *
29
     * @todo: fix in next major release
30
     *
31
     * @var boolean
32
     */
33
    protected $allowMultipleShipments = false;
34
35
    /**
36
     * @todo: make private
37
     *
38
     * @var ResponseInterface
39
     */
40
    public $response;
41
42
    /**
43
     * @var string
44
     */
45
    private $trackingNumber;
46
47
    /**
48
     * @var string
49
     */
50
    private $referenceNumber;
51
52
    /**
53
     * @var string
54
     */
55
    private $requestOption;
56
57
    /**
58
     * @var string
59
     */
60
    private $shipperNumber;
61
62
    /**
63
     * @var \DateTime
64
     */
65
    private $beginDate;
66
67
    /**
68
     * @var \DateTime
69
     */
70
    private $endDate;
71
72
    /**
73
     * @param string|null $accessKey UPS License Access Key
74
     * @param string|null $userId UPS User ID
75
     * @param string|null $password UPS User Password
76
     * @param bool $useIntegration Determine if we should use production or CIE URLs.
77
     * @param RequestInterface|null $request
78
     * @param LoggerInterface|null $logger PSR3 compatible logger (optional)
79
     */
80 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...
81
    {
82 6
        if (null !== $request) {
83
            $this->setRequest($request);
84
        }
85 6
        parent::__construct($accessKey, $userId, $password, $useIntegration, $logger);
86 6
    }
87
88
    /**
89
     * Get package tracking information.
90
     *
91
     * @param string $trackingNumber The package's tracking number.
92
     * @param string $requestOption Optional processing. For Mail Innovations the only valid options are Last Activity and All activity.
93
     *
94
     * @throws Exception
95
     *
96
     * @return stdClass
97
     */
98 5
    public function track($trackingNumber, $requestOption = 'activity')
99
    {
100 5
        $this->trackingNumber = $trackingNumber;
101 5
        $this->requestOption = $requestOption;
102
103 5
        return $this->getFormattedResponse();
104
    }
105
106
    /**
107
     * Get package tracking information.
108
     *
109
     * @param string $referenceNumber Reference numbers can be a purchase order number, job number, etc. Reference number can be added when creating a shipment.
110
     * @param string $requestOption
111
     *
112
     * @throws Exception
113
     *
114
     * @return stdClass
115
     */
116 1
    public function trackByReference($referenceNumber, $requestOption = 'activity')
117
    {
118 1
        $this->referenceNumber = $referenceNumber;
119 1
        $this->requestOption = $requestOption;
120
121 1
        return $this->getFormattedResponse();
122
    }
123
124
    /**
125
     * Set shipper number
126
     *
127
     * @param string $shipperNumber
128
     *
129
     */
130
    public function setShipperNumber($shipperNumber)
131
    {
132
        $this->shipperNumber = $shipperNumber;
133
    }
134
135
    /**
136
     * Set begin date
137
     *
138
     * @param DateTime $beginDate
139
     *
140
     */
141
    public function setBeginDate(DateTime $beginDate)
142
    {
143
        $this->beginDate = $beginDate;
144
    }
145
146
    /**
147
     * Set end date
148
     *
149
     * @param DateTime $endDate
150
     *
151
     */
152
    public function setEndDate(DateTime $endDate)
153
    {
154
        $this->endDate = $endDate;
155
    }
156
157
    /**
158
     * @return stdClass
159
     * @throws Exception
160
     */
161 6
    private function getFormattedResponse()
162
    {
163 6
        $this->response = $this->getRequest()->request(
164 6
            $this->createAccess(),
165 6
            $this->createRequest(),
166 6
            $this->compileEndpointUrl(self::ENDPOINT)
167 6
        );
168 6
        $response = $this->response->getResponse();
169
170 6
        if (null === $response) {
171 3
            throw new Exception('Failure (0): Unknown error', 0);
172
        }
173
174 3
        if ($response instanceof SimpleXMLElement && $response->Response->ResponseStatusCode == 0) {
175
            throw new Exception(
176
                "Failure ({$response->Response->Error->ErrorSeverity}): {$response->Response->Error->ErrorDescription}",
177
                (int)$response->Response->Error->ErrorCode
178
            );
179
        }
180
181 3
        return $this->formatResponse($response);
182
    }
183
184
    /**
185
     * Check if tracking number is for mail innovations.
186
     *
187
     * @return bool
188
     */
189 6
    private function isMailInnovations()
190
    {
191
        $patterns = [
192
193
            // UPS Mail Innovations tracking numbers
194 6
            '/^MI\d{6}\d{1,22}$/',// MI 000000 00000000+
195
196
            // USPS - Certified Mail
197 6
            '/^94071\d{17}$/',    // 9407 1000 0000 0000 0000 00
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
198 6
            '/^7\d{19}$/',        // 7000 0000 0000 0000 0000
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
199
200
            // USPS - Collect on Delivery
201 6
            '/^93033\d{17}$/',    // 9303 3000 0000 0000 0000 00
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
202 6
            '/^M\d{9}$/',         // M000 0000 00
203
204
            // USPS - Global Express Guaranteed
205 6
            '/^82\d{10}$/',       // 82 000 000 00
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
206
207
            // USPS - Priority Mail Express International
208 6
            '/^EC\d{9}US$/',      // EC 000 000 000 US
209
210
            // USPS Innovations Expedited
211 6
            '/^927\d{23}$/',      // 9270 8900 8900 8900 8900 8900 00
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
212
213
            // USPS - Priority Mail Express
214 6
            '/^927\d{19}$/',      // 9270 1000 0000 0000 0000 00
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
215 6
            '/^EA\d{9}US$/',      // EA 000 000 000 US
216
217
            // USPS - Priority Mail International
218 6
            '/^CP\d{9}US$/',      // CP 000 000 000 US
219
220
            // USPS - Priority Mail
221 6
            '/^92055\d{17}$/',    // 9205 5000 0000 0000 0000 00
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
222 6
            '/^14\d{18}$/',       // 1400 0000 0000 0000 0000
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
223
224
            // USPS - Registered Mail
225 6
            '/^92088\d{17}$/',    // 9208 8000 0000 0000 0000 00
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
226 6
            '/^RA\d{9}US$/',      // RA 000 000 000 US
227
228
            // USPS - Signature Confirmation
229 6
            '/^9202\d{16}US$/',   // 9202 1000 0000 0000 0000 00
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
230 6
            '/^23\d{16}US$/',     // 2300 0000 0000 0000 0000
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
231
232
            // USPS - Tracking
233 6
            '/^94\d{20}$/',       // 9400 1000 0000 0000 0000 00
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
234
            '/^03\d{18}$/'        // 0300 0000 0000 0000 0000
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
235 6
        ];
236
237 6
        foreach ($patterns as $pattern) {
238 6
            if (preg_match($pattern, $this->trackingNumber)) {
239 1
                return true;
240
            }
241 6
        }
242
243 5
        return false;
244
    }
245
246
    /**
247
     * Create the Tracking request.
248
     *
249
     * @return string
250
     */
251 6
    private function createRequest()
252
    {
253 6
        $xml = new DOMDocument();
254 6
        $xml->formatOutput = true;
255
256 6
        $trackRequest = $xml->appendChild($xml->createElement('TrackRequest'));
257 6
        $trackRequest->setAttribute('xml:lang', 'en-US');
258
259 6
        $request = $trackRequest->appendChild($xml->createElement('Request'));
260
261 6
        $node = $xml->importNode($this->createTransactionNode(), true);
262 6
        $request->appendChild($node);
263
264 6
        $request->appendChild($xml->createElement('RequestAction', 'Track'));
265
266 6
        if (null !== $this->requestOption) {
267 6
            $request->appendChild($xml->createElement('RequestOption', $this->requestOption));
268 6
        }
269
270 6
        if (null !== $this->trackingNumber) {
271 5
            $trackRequest->appendChild($xml->createElement('TrackingNumber', $this->trackingNumber));
272 5
        }
273
274 6
        if ($this->isMailInnovations()) {
275 1
            $trackRequest->appendChild($xml->createElement('IncludeMailInnovationIndicator'));
276 1
        }
277
278 6
        if (null !== $this->referenceNumber) {
279 1
            $trackRequest->appendChild($xml->createElement('ReferenceNumber'))->appendChild($xml->createElement('Value', $this->referenceNumber));
280 1
        }
281
282 6
        if (null !== $this->shipperNumber) {
283
            $trackRequest->appendChild($xml->createElement('ShipperNumber', $this->shipperNumber));
284
        }
285
286 6
        if (null !== $this->beginDate || null !== $this->endDate) {
287
            $DateRange = $xml->createElement('PickupDateRange');
288
289
            if (null !== $this->beginDate) {
290
                $beginDate = $this->beginDate->format('Ymd');
291
                $DateRange->appendChild($xml->createElement('BeginDate', $beginDate));
292
            }
293
294
            if (null !== $this->endDate) {
295
                $endDate = $this->endDate->format('Ymd');
296
                $DateRange->appendChild($xml->createElement('EndDate', $endDate));
297
            }
298
299
            $trackRequest->appendChild($DateRange);
300
        }
301
302 6
        return $xml->saveXML();
303
    }
304
305
    /**
306
     * Format the response.
307
     *
308
     * @param SimpleXMLElement $response
309
     *
310
     * @return stdClass
311
     */
312 3
    private function formatResponse(SimpleXMLElement $response)
313
    {
314 3
        if ($this->allowMultipleShipments) {
315
            $response = $this->convertXmlObject($response);
316
            if (!is_array($response->Shipment)) {
317
                $response->Shipment = [$response->Shipment];
318
            }
319
            return $response;
320
        }
321
322 3
        return $this->convertXmlObject($response->Shipment);
323
    }
324
325
    /**
326
     * @return RequestInterface
327
     */
328 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...
329
    {
330 6
        if (null === $this->request) {
331
            $this->request = new Request($this->logger);
332
        }
333
334 6
        return $this->request;
335
    }
336
337
    /**
338
     * @param RequestInterface $request
339
     *
340
     * @return $this
341
     */
342 6
    public function setRequest(RequestInterface $request)
343
    {
344 6
        $this->request = $request;
345
346 6
        return $this;
347
    }
348
349
    /**
350
     * @return ResponseInterface
351
     */
352 2
    public function getResponse()
353
    {
354 2
        return $this->response;
355
    }
356
357
    /**
358
     * @param ResponseInterface $response
359
     *
360
     * @return $this
361
     */
362
    public function setResponse(ResponseInterface $response)
363
    {
364
        $this->response = $response;
365
366
        return $this;
367
    }
368
369
    /**
370
     * @param bool $value
371
     * @return $this
372
     */
373
    public function allowMultipleShipments($value = true)
374
    {
375
        $this->allowMultipleShipments = $value ? true : false;
376
377
        return $this;
378
    }
379
}
380