1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the Ivory Google Map package. |
5
|
|
|
* |
6
|
|
|
* (c) Eric GELOEN <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please read the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Ivory\GoogleMap\Service\Directions; |
13
|
|
|
|
14
|
|
|
use Http\Client\HttpClient; |
15
|
|
|
use Http\Message\MessageFactory; |
16
|
|
|
use Ivory\GoogleMap\Base\Bound; |
17
|
|
|
use Ivory\GoogleMap\Base\Coordinate; |
18
|
|
|
use Ivory\GoogleMap\Overlay\EncodedPolyline; |
19
|
|
|
use Ivory\GoogleMap\Service\AbstractService; |
20
|
|
|
use Ivory\GoogleMap\Service\Base\Distance; |
21
|
|
|
use Ivory\GoogleMap\Service\Base\Duration; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* @author GeLo <[email protected]> |
25
|
|
|
*/ |
26
|
|
|
class Directions extends AbstractService |
27
|
|
|
{ |
28
|
|
|
/** |
29
|
|
|
* @param HttpClient $client |
30
|
|
|
* @param MessageFactory $messageFactory |
31
|
|
|
*/ |
32
|
|
|
public function __construct(HttpClient $client, MessageFactory $messageFactory) |
33
|
|
|
{ |
34
|
|
|
parent::__construct($client, $messageFactory, 'http://maps.googleapis.com/maps/api/directions'); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @param DirectionsRequest $request |
39
|
|
|
* |
40
|
|
|
* @return DirectionsResponse |
41
|
|
|
*/ |
42
|
|
View Code Duplication |
public function route(DirectionsRequest $request) |
|
|
|
|
43
|
|
|
{ |
44
|
|
|
$response = $this->getClient()->sendRequest($this->createRequest($request->buildQuery())); |
45
|
|
|
$data = $this->parse((string) $response->getBody()); |
46
|
|
|
|
47
|
|
|
return $this->buildResponse($data); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @param string $data |
52
|
|
|
* |
53
|
|
|
* @return mixed[] |
54
|
|
|
*/ |
55
|
|
|
private function parse($data) |
56
|
|
|
{ |
57
|
|
|
if ($this->getFormat() === self::FORMAT_JSON) { |
58
|
|
|
return json_decode($data, true); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
return $this->getXmlParser()->parse($data, [ |
62
|
|
|
'leg' => 'legs', |
63
|
|
|
'route' => 'routes', |
64
|
|
|
'step' => 'steps', |
65
|
|
|
'waypoint_index' => 'waypoint_order', |
66
|
|
|
]); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @param mixed[] $data |
71
|
|
|
* |
72
|
|
|
* @return DirectionsResponse |
73
|
|
|
*/ |
74
|
|
|
private function buildResponse(array $data) |
75
|
|
|
{ |
76
|
|
|
$response = new DirectionsResponse(); |
77
|
|
|
$response->setStatus($data['status']); |
78
|
|
|
$response->setRoutes(isset($data['routes']) ? $this->buildRoutes($data['routes']) : []); |
79
|
|
|
|
80
|
|
|
$response->setGeocodedWaypoints( |
81
|
|
|
isset($data['geocoded_waypoints']) ? $this->buildGeocodedWaypoints($data['geocoded_waypoints']) : [] |
82
|
|
|
); |
83
|
|
|
|
84
|
|
|
$response->setAvailableTravelModes( |
85
|
|
|
isset($data['available_travel_modes']) ? $data['available_travel_modes'] : [] |
86
|
|
|
); |
87
|
|
|
|
88
|
|
|
return $response; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @param mixed[] $data |
93
|
|
|
* |
94
|
|
|
* @return DirectionsRoute[] |
95
|
|
|
*/ |
96
|
|
|
private function buildRoutes(array $data) |
97
|
|
|
{ |
98
|
|
|
$routes = []; |
99
|
|
|
foreach ($data as $item) { |
100
|
|
|
$routes[] = $this->buildRoute($item); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
return $routes; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* @param mixed[] $data |
108
|
|
|
* |
109
|
|
|
* @return DirectionsRoute |
110
|
|
|
*/ |
111
|
|
|
private function buildRoute(array $data) |
112
|
|
|
{ |
113
|
|
|
$route = new DirectionsRoute(); |
114
|
|
|
$route->setBound($this->buildBound($data['bounds'])); |
115
|
|
|
$route->setCopyrights(isset($data['copyrights']) ? $data['copyrights'] : null); |
116
|
|
|
$route->setLegs($this->buildLegs($data['legs'])); |
117
|
|
|
$route->setOverviewPolyline($this->buildEncodedPolyline($data['overview_polyline'])); |
118
|
|
|
$route->setSummary(isset($data['summary']) ? $data['summary'] : null); |
119
|
|
|
$route->setFare(isset($data['fare']) ? $this->buildFare($data['fare']) : null); |
120
|
|
|
$route->setWarnings(isset($data['warnings']) ? $data['warnings'] : []); |
121
|
|
|
$route->setWaypointOrders(isset($data['waypoint_order']) ? $data['waypoint_order'] : []); |
122
|
|
|
|
123
|
|
|
return $route; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* @param mixed[] $data |
128
|
|
|
* |
129
|
|
|
* @return DirectionsGeocoded[] |
130
|
|
|
*/ |
131
|
|
|
private function buildGeocodedWaypoints(array $data) |
132
|
|
|
{ |
133
|
|
|
$geocodedWaypoints = []; |
134
|
|
|
foreach ($data as $item) { |
135
|
|
|
$geocodedWaypoints[] = $this->buildGeocodedWaypoint($item); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
return $geocodedWaypoints; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* @param mixed[] $data |
143
|
|
|
* |
144
|
|
|
* @return DirectionsGeocoded |
145
|
|
|
*/ |
146
|
|
|
private function buildGeocodedWaypoint(array $data) |
147
|
|
|
{ |
148
|
|
|
$geocodedWaypoint = new DirectionsGeocoded(); |
149
|
|
|
$geocodedWaypoint->setStatus($data['geocoder_status']); |
150
|
|
|
$geocodedWaypoint->setPartialMatch(isset($data['partial_match']) ? $data['partial_match'] : null); |
151
|
|
|
$geocodedWaypoint->setPlaceId(isset($data['place_id']) ? $data['place_id'] : null); |
152
|
|
|
$geocodedWaypoint->setTypes($data['types']); |
153
|
|
|
|
154
|
|
|
return $geocodedWaypoint; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* @param mixed[] $data |
159
|
|
|
* |
160
|
|
|
* @return DirectionsLeg[] |
161
|
|
|
*/ |
162
|
|
|
private function buildLegs(array $data) |
163
|
|
|
{ |
164
|
|
|
$legs = []; |
165
|
|
|
foreach ($data as $item) { |
166
|
|
|
$legs[] = $this->buildLeg($item); |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
return $legs; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* @param mixed[] $data |
174
|
|
|
* |
175
|
|
|
* @return DirectionsLeg |
176
|
|
|
*/ |
177
|
|
|
private function buildLeg(array $data) |
178
|
|
|
{ |
179
|
|
|
$leg = new DirectionsLeg(); |
180
|
|
|
$leg->setDistance($this->buildDistance($data['distance'])); |
181
|
|
|
$leg->setDuration($this->buildDuration($data['duration'])); |
182
|
|
|
$leg->setEndAddress($data['end_address']); |
183
|
|
|
$leg->setEndLocation($this->buildCoordinate($data['end_location'])); |
184
|
|
|
$leg->setStartAddress($data['start_address']); |
185
|
|
|
$leg->setStartLocation($this->buildCoordinate($data['start_location'])); |
186
|
|
|
$leg->setSteps($this->buildSteps($data['steps'])); |
187
|
|
|
$leg->setViaWaypoints(isset($data['via_waypoint']) ? $data['via_waypoint'] : []); |
188
|
|
|
$leg->setDurationInTraffic( |
189
|
|
|
isset($data['duration_in_traffic']) ? $this->buildDuration($data['duration_in_traffic']) : null |
190
|
|
|
); |
191
|
|
|
|
192
|
|
|
return $leg; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* @codeCoverageIgnore |
197
|
|
|
* |
198
|
|
|
* @param mixed[] $data |
199
|
|
|
* |
200
|
|
|
* @return DirectionsFare |
201
|
|
|
*/ |
202
|
|
|
private function buildFare(array $data) |
203
|
|
|
{ |
204
|
|
|
$fare = new DirectionsFare(); |
205
|
|
|
$fare->setCurrency($data['currency']); |
206
|
|
|
$fare->setValue($data['value']); |
207
|
|
|
$fare->setText($data['text']); |
208
|
|
|
|
209
|
|
|
return $fare; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* @param mixed[] $data |
214
|
|
|
* |
215
|
|
|
* @return DirectionsStep[] |
216
|
|
|
*/ |
217
|
|
|
private function buildSteps(array $data) |
218
|
|
|
{ |
219
|
|
|
$steps = []; |
220
|
|
|
foreach ($data as $item) { |
221
|
|
|
$steps[] = $this->buildStep($item); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
return $steps; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* @param mixed[] $data |
229
|
|
|
* |
230
|
|
|
* @return DirectionsStep |
231
|
|
|
*/ |
232
|
|
|
private function buildStep(array $data) |
233
|
|
|
{ |
234
|
|
|
$step = new DirectionsStep(); |
235
|
|
|
$step->setDistance($this->buildDistance($data['distance'])); |
236
|
|
|
$step->setDuration($this->buildDuration($data['duration'])); |
237
|
|
|
$step->setEndLocation($this->buildCoordinate($data['end_location'])); |
238
|
|
|
$step->setInstructions($data['html_instructions']); |
239
|
|
|
$step->setEncodedPolyline($this->buildEncodedPolyline($data['polyline'])); |
240
|
|
|
$step->setStartLocation($this->buildCoordinate($data['start_location'])); |
241
|
|
|
$step->setTravelMode($data['travel_mode']); |
242
|
|
|
|
243
|
|
|
return $step; |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* @param mixed[] $data |
248
|
|
|
* |
249
|
|
|
* @return Bound |
250
|
|
|
*/ |
251
|
|
|
private function buildBound(array $data) |
252
|
|
|
{ |
253
|
|
|
return new Bound( |
254
|
|
|
$this->buildCoordinate($data['southwest']), |
255
|
|
|
$this->buildCoordinate($data['northeast']) |
256
|
|
|
); |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
/** |
260
|
|
|
* @param mixed[] $data |
261
|
|
|
* |
262
|
|
|
* @return Coordinate |
263
|
|
|
*/ |
264
|
|
|
private function buildCoordinate(array $data) |
265
|
|
|
{ |
266
|
|
|
return new Coordinate($data['lat'], $data['lng']); |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
/** |
270
|
|
|
* @param mixed[] $data |
271
|
|
|
* |
272
|
|
|
* @return Distance |
273
|
|
|
*/ |
274
|
|
|
private function buildDistance(array $data) |
275
|
|
|
{ |
276
|
|
|
return new Distance($data['text'], $data['value']); |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
/** |
280
|
|
|
* @param mixed[] $data |
281
|
|
|
* |
282
|
|
|
* @return Duration |
283
|
|
|
*/ |
284
|
|
|
private function buildDuration(array $data) |
285
|
|
|
{ |
286
|
|
|
return new Duration($data['text'], $data['value']); |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
/** |
290
|
|
|
* @param string[] $data |
291
|
|
|
* |
292
|
|
|
* @return EncodedPolyline |
293
|
|
|
*/ |
294
|
|
|
private function buildEncodedPolyline(array $data) |
295
|
|
|
{ |
296
|
|
|
return new EncodedPolyline($data['points']); |
297
|
|
|
} |
298
|
|
|
} |
299
|
|
|
|
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.