Completed
Push — master ( 430d0f...253a49 )
by Taosikai
14:05
created

USPSTracker::buildShipment()   C

Complexity

Conditions 11
Paths 16

Size

Total Lines 40
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 40
rs 5.2653
c 0
b 0
f 0
cc 11
eloc 30
nc 16
nop 1

How to fix   Complexity   

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
2
/**
3
 * Slince shipment tracker library
4
 * @author Tao <[email protected]>
5
 */
6
namespace Slince\ShipmentTracking\USPS;
7
8
use Psr\Http\Message\ResponseInterface;
9
use Slince\ShipmentTracking\Foundation\Exception\TrackException;
10
use Slince\ShipmentTracking\Foundation\HttpAwareTracker;
11
use GuzzleHttp\Client as HttpClient;
12
use Slince\ShipmentTracking\Foundation\Shipment;
13
use Slince\ShipmentTracking\Utility;
14
15
class USPSTracker extends HttpAwareTracker
16
{
17
    const TRACKING_ENDPOINT  = 'http://production.shippingapis.com/ShippingAPI.dll';
18
19
    /**
20
     * @var string
21
     */
22
    protected $userId;
23
24
    /**
25
     * You can get your userID from the following url
26
     * {@link https://www.usps.com/business/web-tools-apis/welcome.htm}
27
     */
28
    public function __construct($userId, HttpClient $httpClient = null)
29
    {
30
        $this->userId = $userId;
31
        $httpClient && $this->setHttpClient($httpClient);
32
    }
33
34
    /**
35
     * @return string
36
     */
37
    public function getUserId()
38
    {
39
        return $this->userId;
40
    }
41
42
    /**
43
     * @param string $userId
44
     * @return USPSTracker
45
     */
46
    public function setUserId($userId)
47
    {
48
        $this->userId = $userId;
49
        return $this;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function track($trackingNumber)
56
    {
57
        try {
58
            $response = $this->request([
59
                'query' => [
60
                    'API' => 'TrackV2',
61
                    'XML' => static::buildXml($this->userId, $trackingNumber)
62
                ]
63
            ]);
64
            $array = Utility::parseXml($response->getBody());
65
        } catch (\Exception $exception) {
66
            throw new TrackException($exception->getMessage());
67
        }
68
        if (!isset($array['TrackInfo'])) {
69
            throw new TrackException($array['Description']);
70
        }
71
        if (isset($array['TrackInfo']['Error'])) {
72
            throw new TrackException($array['TrackInfo']['Error']['Description']);
73
        }
74
        if (!isset($array['TrackInfo']['TrackDetail'])) {
75
            throw new TrackException('Cannot find any events');
76
        }
77
        $shipment = static::buildShipment($array);
78
        return $shipment;
79
    }
80
81
    /**
82
     * @param array $options
83
     * @return ResponseInterface
84
     * @codeCoverageIgnore
85
     */
86
    protected function request($options)
87
    {
88
        return $this->getHttpClient()->get(static::TRACKING_ENDPOINT, $options);
89
    }
90
91
    /**
92
     * @param string $userId
93
     * @param string $trackID
94
     * @return string
95
     */
96
    protected static function buildXml($userId, $trackID)
97
    {
98
        $xmlTemplate = <<<XML
99
<?xml version="1.0" encoding="UTF-8" ?>
100
<TrackFieldRequest USERID="%s">
101
  <ClientIp>111.0.0.1</ClientIp>
102
  <TrackID ID="%s"></TrackID>
103
</TrackFieldRequest>
104
XML;
105
        return sprintf($xmlTemplate, $userId, $trackID);
106
    }
107
108
    /**
109
     * @param array $array
110
     * @return Shipment
111
     */
112
    protected static function buildShipment($array)
113
    {
114
        $trackDetails = is_numeric(key($array['TrackInfo']['TrackDetail']))
115
            ? $array['TrackInfo']['TrackDetail']
116
            : [$array['TrackInfo']['TrackDetail']];
117
118
        //The track summary is also valid
119
        if (isset($array['TrackInfo']['TrackSummary'])) {
120
            array_unshift($trackDetails, $array['TrackInfo']['TrackSummary']);
121
        }
122
123
        $events = array_map(function($eventData){
124
            $time = empty($eventData['EventTime']) ? '' : $eventData['EventTime'];
125
            $day = empty($eventData['EventDate']) ? '' : $eventData['EventDate'];
126
            $country = empty($eventData['EventCountry']) ? '' : $eventData['EventCountry'];
127
            $state = empty($eventData['EventState']) ? '' : $eventData['EventState'];
128
            $city = empty($eventData['EventCity']) ? '' : $eventData['EventCity'];
129
            $zipCode = empty($eventData['EventZIPCode']) ? '' : $eventData['EventZIPCode'];
130
            return ShipmentEvent::fromArray([
131
                'date' => "{$day} {$time}",
132
                'location' => "{$city} {$state} {$country}",
133
                'description' => $eventData['Event'],
134
                'time' => $time,
135
                'day' => $day,
136
                'city' => $city,
137
                'state' => $state,
138
                'country' => $country,
139
                'zipCode' => $zipCode
140
            ]);
141
        }, array_reverse($trackDetails));
142
        
143
        $shipment = new Shipment($events);
144
        if (isset($array['TrackInfo']['TrackSummary']['DeliveryAttributeCode'])) {
145
            $shipment->setIsDelivered($array['TrackInfo']['TrackSummary']['DeliveryAttributeCode'] == '01');
146
        }
147
        if ($firstEvent = reset($events)) {
148
            $shipment->setDeliveredAt($firstEvent->getDate());
149
        }
150
        return $shipment;
151
    }
152
}