Completed
Push — master ( 3f0652...6ef7a8 )
by Taosikai
10:39
created

EMSTracker::parseXml()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
1
<?php
2
/**
3
 * Slince shipment tracker library
4
 * @author Tao <[email protected]>
5
 */
6
namespace Slince\ShipmentTracking\EMS;
7
8
use GuzzleHttp\Client as HttpClient;
9
use GuzzleHttp\Psr7\Request;
10
use GuzzleHttp\Exception\GuzzleException;
11
use Psr\Http\Message\RequestInterface;
12
use Slince\ShipmentTracking\Foundation\Exception\InvalidArgumentException;
13
use Slince\ShipmentTracking\Foundation\Exception\TrackException;
14
use Slince\ShipmentTracking\Foundation\HttpAwareTracker;
15
use Slince\ShipmentTracking\Foundation\Shipment;
16
use Slince\ShipmentTracking\Foundation\ShipmentEvent;
17
use Slince\ShipmentTracking\Utility;
18
19
class EMSTracker extends HttpAwareTracker
20
{
21
    /**
22
     * @var string
23
     */
24
    const TRACKING_ENDPOINT = 'http://shipping.ems.com.cn/partner/api/public/p/track/query/{language}/{trackingNumber}';
25
26
    /**
27
     * @var string
28
     */
29
    protected $language;
30
31
    /**
32
     * @var string
33
     */
34
    protected static $version = 'international_eub_us_1.1';
35
36
    /**
37
     * @var string
38
     */
39
    protected $authenticate;
40
41
    public function __construct($authenticate, $language, HttpClient $httpClient = null)
42
    {
43
        $this->authenticate = $authenticate;
44
        $this->setLanguage($language);
45
        $httpClient && $this->setHttpClient($httpClient);
46
    }
47
48
    /**
49
     * @return string
50
     */
51
    public function getLanguage()
52
    {
53
        return $this->language;
54
    }
55
56
    /**
57
     * @param string $language
58
     * @return EMSTracker
59
     */
60
    public function setLanguage($language)
61
    {
62
        if ($language != 'en' && $language != 'cn') {
63
            throw new InvalidArgumentException(sprintf('Invalid language, expect "cn" or "en", giving "%s"', $language));
64
        }
65
        $this->language = $language;
66
        return $this;
67
    }
68
69
    /**
70
     * @return string
71
     */
72
    public function getAuthenticate()
73
    {
74
        return $this->authenticate;
75
    }
76
77
    /**
78
     * @param string $authenticate
79
     * @return EMSTracker
80
     */
81
    public function setAuthenticate($authenticate)
82
    {
83
        $this->authenticate = $authenticate;
84
        return $this;
85
    }
86
87
    /**
88
     * @param string $version
89
     */
90
    public static function setVersion($version)
91
    {
92
        static::$version = $version;
93
    }
94
95
    /**
96
     * @return string
97
     */
98
    public static function getVersion()
99
    {
100
        return static::$version;
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function track($trackingNumber)
107
    {
108
        $request = new Request('GET', static::formatEndpoint($this->language, $trackingNumber));
109
        try {
110
            $array = Utility::parseXml($this->sendRequest($request));
111
        } catch (InvalidArgumentException $exception) {
112
            throw new TrackException($exception->getMessage());
113
        }
114
        if (!isset($array['trace'])) {
115
            throw new TrackException(sprintf('Bad response,code: "%s", message:"%s"', $array['code'], $array['description']));
116
        }
117
        return static::buildShipment($array);
118
    }
119
120
    /**
121
     * @param RequestInterface $request
122
     * @param array $options
123
     * @return string
124
     * @codeCoverageIgnore
125
     */
126
    protected function sendRequest(RequestInterface $request, array $options = [])
127
    {
128
        try {
129
            $request = $request->withHeader('version', static::$version)
130
                ->withHeader('authenticate', $this->authenticate);
131
            $response = $this->getHttpClient()->send($request, $options);
132
            return (string)$response->getBody();
133
        } catch (GuzzleException $exception) {
134
            throw new TrackException($exception->getMessage());
135
        }
136
    }
137
138
    /**
139
     * @param string $language
140
     * @param string $trackingNumber
141
     * @return string
142
     */
143
    protected static function formatEndpoint($language, $trackingNumber)
144
    {
145
        return str_replace(['{language}', '{trackingNumber}'], [$language, $trackingNumber], static::TRACKING_ENDPOINT);
146
    }
147
148
    /**
149
     * @param array $json
150
     * @return Shipment
151
     */
152
    protected static function buildShipment($json)
153
    {
154
        $events = array_map(function($item) {
155
            return ShipmentEvent::fromArray([
156
                'location' => $item['acceptAddress'],
157
                'description' => $item['remark'],
158
                'date' => $item['acceptTime'],
159
            ]);
160
        }, $json['trace']);
161
        $shipment = new Shipment($events);
162
        if ($firstEvent = reset($events)) {
163
            $shipment->setDeliveredAt($firstEvent->getDate());
164
        }
165
        return $shipment;
166
    }
167
}