AbstractDistanceMatrixQuery::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
1
<?php
2
3
namespace DH\NavigationBundle\Contract\DistanceMatrix;
4
5
use DateTime;
6
use DH\NavigationBundle\Exception\DestinationException;
7
use DH\NavigationBundle\Exception\OriginException;
8
use DH\NavigationBundle\Exception\ResponseException;
9
use DH\NavigationBundle\Provider\ProviderInterface;
10
use Psr\Http\Message\ResponseInterface;
11
12
abstract class AbstractDistanceMatrixQuery implements DistanceMatrixQueryInterface
13
{
14
    /**
15
     * @var ProviderInterface
16
     */
17
    private $provider;
18
19
    /**
20
     * @var array
21
     */
22
    protected $origins;
23
24
    /**
25
     * @var array
26
     */
27
    protected $destinations;
28
29
    /**
30
     * @var ?DateTime
31
     */
32
    private $departure_time;
33
34
    /**
35
     * @var string|null
36
     */
37
    private $language;
38
39
    /**
40
     * DistanceMatrixQuery constructor.
41
     */
42
    public function __construct(ProviderInterface $provider)
43
    {
44
        $this->provider = $provider;
45
        $this->origins = [];
46
        $this->destinations = [];
47
    }
48
49
    public function getProvider(): ProviderInterface
50
    {
51
        return $this->provider;
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    public function getDepartureTime(): ?DateTime
58
    {
59
        return $this->departure_time;
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    public function setDepartureTime(DateTime $departureTime): DistanceMatrixQueryInterface
66
    {
67
        $this->departure_time = $departureTime;
68
69
        return $this;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    public function addOrigin($origin): DistanceMatrixQueryInterface
76
    {
77
        $this->origins[] = $origin;
78
79
        return $this;
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85
    public function getOrigins(): array
86
    {
87
        return $this->origins;
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function addDestination($destination): DistanceMatrixQueryInterface
94
    {
95
        $this->destinations[] = $destination;
96
97
        return $this;
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103
    public function getDestinations(): array
104
    {
105
        return $this->destinations;
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111
    public function setLanguage(string $language): DistanceMatrixQueryInterface
112
    {
113
        $this->language = $language;
114
115
        return $this;
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121
    public function getLanguage(): string
122
    {
123
        return $this->language ?? 'en-US';
124
    }
125
126
    /**
127
     * @throws DestinationException
128
     * @throws OriginException
129
     * @throws ResponseException
130
     * @throws \GuzzleHttp\Exception\GuzzleException
131
     *
132
     * {@inheritdoc}
133
     */
134
    public function execute(): DistanceMatrixResponseInterface
135
    {
136
        $this->validateRequest();
137
        $request = $this->buildRequest();
138
        $rawResponse = $this->request('GET', $request);
139
        $response = $this->buildResponse($rawResponse);
140
        $this->validateResponse($response);
141
142
        return $response;
143
    }
144
145
    abstract protected function buildRequest(): string;
146
147
    abstract protected function buildResponse(ResponseInterface $response): DistanceMatrixResponseInterface;
148
149
    /**
150
     * @throws \GuzzleHttp\Exception\GuzzleException
151
     */
152
    private function request(string $method, string $url): ResponseInterface
153
    {
154
        $client = $this->getProvider()->getClient();
155
        $response = $client->request($method, $url);
156
157
        if (200 !== $response->getStatusCode()) {
158
            throw new \Exception('Response with status code '.$response->getStatusCode());
159
        }
160
161
        return $response;
162
    }
163
164
    /**
165
     * @throws ResponseException
166
     */
167
    private function validateResponse(DistanceMatrixResponseInterface $response): void
168
    {
169
        switch ($response->getStatus()) {
170
            case DistanceMatrixResponseInterface::RESPONSE_STATUS_OK:
171
                break;
172
            case DistanceMatrixResponseInterface::RESPONSE_STATUS_INVALID_REQUEST:
173
                throw new ResponseException('Invalid request.', 1);
174
                break;
175
            case DistanceMatrixResponseInterface::RESPONSE_STATUS_MAX_ELEMENTS_EXCEEDED:
176
                throw new ResponseException('The product of the origin and destination exceeds the limit per request.', 2);
177
                break;
178
            case DistanceMatrixResponseInterface::RESPONSE_STATUS_OVER_QUERY_LIMIT:
179
                throw new ResponseException('The service has received too many requests from your application in the allowed time range.', 3);
180
                break;
181
            case DistanceMatrixResponseInterface::RESPONSE_STATUS_REQUEST_DENIED:
182
                throw new ResponseException('The service denied the use of the Distance Matrix API service by your application.', 4);
183
                break;
184
            case DistanceMatrixResponseInterface::RESPONSE_STATUS_UNKNOWN_ERROR:
185
                throw new ResponseException('Unknown error.', 5);
186
                break;
187
            default:
188
                throw new ResponseException(sprintf('Unknown status code: %s', $response->getStatus()), 6);
189
                break;
190
        }
191
    }
192
193
    /**
194
     * @throws DestinationException
195
     * @throws OriginException
196
     */
197
    private function validateRequest(): void
198
    {
199
        if (empty($this->getOrigins())) {
200
            throw new OriginException('Origin must be set.');
201
        }
202
        if (empty($this->getDestinations())) {
203
            throw new DestinationException('Destination must be set.');
204
        }
205
    }
206
}
207