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\Direction; |
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
|
|
|
use Ivory\GoogleMap\Service\Base\Fare; |
23
|
|
|
use Ivory\GoogleMap\Service\Base\Time; |
24
|
|
|
use Ivory\GoogleMap\Service\Direction\Request\DirectionRequestInterface; |
25
|
|
|
use Ivory\GoogleMap\Service\Direction\Response\DirectionGeocoded; |
26
|
|
|
use Ivory\GoogleMap\Service\Direction\Response\DirectionLeg; |
27
|
|
|
use Ivory\GoogleMap\Service\Direction\Response\DirectionResponse; |
28
|
|
|
use Ivory\GoogleMap\Service\Direction\Response\DirectionRoute; |
29
|
|
|
use Ivory\GoogleMap\Service\Direction\Response\DirectionStep; |
30
|
|
|
use Ivory\GoogleMap\Service\Direction\Response\Transit\DirectionTransitAgency; |
31
|
|
|
use Ivory\GoogleMap\Service\Direction\Response\Transit\DirectionTransitDetails; |
32
|
|
|
use Ivory\GoogleMap\Service\Direction\Response\Transit\DirectionTransitLine; |
33
|
|
|
use Ivory\GoogleMap\Service\Direction\Response\Transit\DirectionTransitStop; |
34
|
|
|
use Ivory\GoogleMap\Service\Direction\Response\Transit\DirectionTransitVehicle; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @author GeLo <[email protected]> |
38
|
|
|
*/ |
39
|
|
|
class DirectionService extends AbstractService |
40
|
|
|
{ |
41
|
|
|
/** |
42
|
|
|
* @param HttpClient $client |
43
|
|
|
* @param MessageFactory $messageFactory |
44
|
|
|
*/ |
45
|
|
|
public function __construct(HttpClient $client, MessageFactory $messageFactory) |
46
|
|
|
{ |
47
|
|
|
parent::__construct($client, $messageFactory, 'http://maps.googleapis.com/maps/api/directions'); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @param DirectionRequestInterface $request |
52
|
|
|
* |
53
|
|
|
* @return DirectionResponse |
54
|
|
|
*/ |
55
|
|
View Code Duplication |
public function route(DirectionRequestInterface $request) |
|
|
|
|
56
|
|
|
{ |
57
|
|
|
$response = $this->getClient()->sendRequest($this->createRequest($request->build())); |
58
|
|
|
$data = $this->parse((string) $response->getBody()); |
59
|
|
|
|
60
|
|
|
return $this->buildResponse($data); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @param string $data |
65
|
|
|
* |
66
|
|
|
* @return mixed[] |
67
|
|
|
*/ |
68
|
|
|
private function parse($data) |
69
|
|
|
{ |
70
|
|
|
if ($this->getFormat() === self::FORMAT_JSON) { |
71
|
|
|
return json_decode($data, true); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
return $this->getXmlParser()->parse($data, [ |
75
|
|
|
'leg' => 'legs', |
76
|
|
|
'route' => 'routes', |
77
|
|
|
'step' => 'steps', |
78
|
|
|
'waypoint_index' => 'waypoint_order', |
79
|
|
|
]); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @param mixed[] $data |
84
|
|
|
* |
85
|
|
|
* @return DirectionResponse |
86
|
|
|
*/ |
87
|
|
|
private function buildResponse(array $data) |
88
|
|
|
{ |
89
|
|
|
$response = new DirectionResponse(); |
90
|
|
|
$response->setStatus($data['status']); |
91
|
|
|
|
92
|
|
|
if (isset($data['routes'])) { |
93
|
|
|
$response->setRoutes($this->buildRoutes($data['routes'])); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
if (isset($data['geocoded_waypoints'])) { |
97
|
|
|
$response->setGeocodedWaypoints($this->buildGeocodedWaypoints($data['geocoded_waypoints'])); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
if (isset($data['available_travel_modes'])) { |
101
|
|
|
$response->setAvailableTravelModes($data['available_travel_modes']); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
return $response; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param mixed[] $data |
109
|
|
|
* |
110
|
|
|
* @return DirectionRoute[] |
111
|
|
|
*/ |
112
|
|
|
private function buildRoutes(array $data) |
113
|
|
|
{ |
114
|
|
|
$routes = []; |
115
|
|
|
|
116
|
|
|
foreach ($data as $route) { |
117
|
|
|
$routes[] = $this->buildRoute($route); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
return $routes; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* @param mixed[] $data |
125
|
|
|
* |
126
|
|
|
* @return DirectionRoute |
127
|
|
|
*/ |
128
|
|
|
private function buildRoute(array $data) |
129
|
|
|
{ |
130
|
|
|
$route = new DirectionRoute(); |
131
|
|
|
$route->setBound($this->buildBound($data['bounds'])); |
132
|
|
|
$route->setLegs($this->buildLegs($data['legs'])); |
133
|
|
|
$route->setOverviewPolyline($this->buildEncodedPolyline($data['overview_polyline'])); |
134
|
|
|
|
135
|
|
|
if (isset($data['copyrights'])) { |
136
|
|
|
$route->setCopyrights($data['copyrights']); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
if (isset($data['summary'])) { |
140
|
|
|
$route->setSummary($data['summary']); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
if (isset($data['fare'])) { |
144
|
|
|
$route->setFare($this->buildFare($data['fare'])); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
if (isset($data['warnings'])) { |
148
|
|
|
$route->setWarnings($data['warnings']); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
if (isset($data['waypoint_order'])) { |
152
|
|
|
$route->setWaypointOrders($data['waypoint_order']); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
return $route; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* @param mixed[] $data |
160
|
|
|
* |
161
|
|
|
* @return DirectionGeocoded[] |
162
|
|
|
*/ |
163
|
|
|
private function buildGeocodedWaypoints(array $data) |
164
|
|
|
{ |
165
|
|
|
$waypoints = []; |
166
|
|
|
|
167
|
|
|
foreach ($data as $waypoint) { |
168
|
|
|
$waypoints[] = $this->buildGeocodedWaypoint($waypoint); |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
return $waypoints; |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* @param mixed[] $data |
176
|
|
|
* |
177
|
|
|
* @return DirectionGeocoded |
178
|
|
|
*/ |
179
|
|
|
private function buildGeocodedWaypoint(array $data) |
180
|
|
|
{ |
181
|
|
|
$geocodedWaypoint = new DirectionGeocoded(); |
182
|
|
|
$geocodedWaypoint->setStatus($data['geocoder_status']); |
183
|
|
|
$geocodedWaypoint->setTypes($data['types']); |
184
|
|
|
|
185
|
|
|
if (isset($data['place_id'])) { |
186
|
|
|
$geocodedWaypoint->setPlaceId($data['place_id']); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
if (isset($data['partial_match'])) { |
190
|
|
|
$geocodedWaypoint->setPartialMatch($data['partial_match']); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
return $geocodedWaypoint; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* @param mixed[] $data |
198
|
|
|
* |
199
|
|
|
* @return DirectionLeg[] |
200
|
|
|
*/ |
201
|
|
|
private function buildLegs(array $data) |
202
|
|
|
{ |
203
|
|
|
$legs = []; |
204
|
|
|
|
205
|
|
|
foreach ($data as $leg) { |
206
|
|
|
$legs[] = $this->buildLeg($leg); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
return $legs; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* @param mixed[] $data |
214
|
|
|
* |
215
|
|
|
* @return DirectionLeg |
216
|
|
|
*/ |
217
|
|
|
private function buildLeg(array $data) |
218
|
|
|
{ |
219
|
|
|
$leg = new DirectionLeg(); |
220
|
|
|
$leg->setDistance($this->buildDistance($data['distance'])); |
221
|
|
|
$leg->setDuration($this->buildDuration($data['duration'])); |
222
|
|
|
$leg->setStartLocation($this->buildCoordinate($data['start_location'])); |
223
|
|
|
$leg->setEndLocation($this->buildCoordinate($data['end_location'])); |
224
|
|
|
$leg->setStartAddress($data['start_address']); |
225
|
|
|
$leg->setEndAddress($data['end_address']); |
226
|
|
|
$leg->setSteps($this->buildSteps($data['steps'])); |
227
|
|
|
|
228
|
|
|
if (isset($data['departure_time'])) { |
229
|
|
|
$leg->setDepartureTime($this->buildTime($data['departure_time'])); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
if (isset($data['arrival_time'])) { |
233
|
|
|
$leg->setArrivalTime($this->buildTime($data['arrival_time'])); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
if (isset($data['via_waypoint'])) { |
237
|
|
|
$leg->setViaWaypoints($data['via_waypoint']); |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
if (isset($data['duration_in_traffic'])) { |
241
|
|
|
$leg->setDurationInTraffic($this->buildDuration($data['duration_in_traffic'])); |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
return $leg; |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* @param mixed[] $data |
249
|
|
|
* |
250
|
|
|
* @return DirectionStep[] |
251
|
|
|
*/ |
252
|
|
|
private function buildSteps(array $data) |
253
|
|
|
{ |
254
|
|
|
$steps = []; |
255
|
|
|
|
256
|
|
|
foreach ($data as $step) { |
257
|
|
|
$steps[] = $this->buildStep($step); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
return $steps; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
/** |
264
|
|
|
* @param mixed[] $data |
265
|
|
|
* |
266
|
|
|
* @return DirectionStep |
267
|
|
|
*/ |
268
|
|
|
private function buildStep(array $data) |
269
|
|
|
{ |
270
|
|
|
$step = new DirectionStep(); |
271
|
|
|
$step->setDistance($this->buildDistance($data['distance'])); |
272
|
|
|
$step->setDuration($this->buildDuration($data['duration'])); |
273
|
|
|
$step->setEndLocation($this->buildCoordinate($data['end_location'])); |
274
|
|
|
$step->setEncodedPolyline($this->buildEncodedPolyline($data['polyline'])); |
275
|
|
|
$step->setStartLocation($this->buildCoordinate($data['start_location'])); |
276
|
|
|
$step->setInstructions($data['html_instructions']); |
277
|
|
|
$step->setTravelMode($data['travel_mode']); |
278
|
|
|
|
279
|
|
|
if (isset($data['transit_details'])) { |
280
|
|
|
$step->setTransitDetails($this->buildTransitDetails($data['transit_details'])); |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
return $step; |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* @param mixed[] $data |
288
|
|
|
* |
289
|
|
|
* @return DirectionTransitDetails |
290
|
|
|
*/ |
291
|
|
|
private function buildTransitDetails(array $data) |
292
|
|
|
{ |
293
|
|
|
$transitDetails = new DirectionTransitDetails(); |
294
|
|
|
$transitDetails->setDepartureStop($this->buildTransitStop($data['departure_stop'])); |
295
|
|
|
$transitDetails->setArrivalStop($this->buildTransitStop($data['arrival_stop'])); |
296
|
|
|
$transitDetails->setDepartureTime($this->buildTime($data['departure_time'])); |
297
|
|
|
$transitDetails->setArrivalTime($this->buildTime($data['arrival_time'])); |
298
|
|
|
$transitDetails->setLine($this->buildTransitLine($data['line'])); |
299
|
|
|
$transitDetails->setHeadSign($data['headsign']); |
300
|
|
|
$transitDetails->setNumStops($data['num_stops']); |
301
|
|
|
|
302
|
|
|
if (isset($data['headway'])) { |
303
|
|
|
$transitDetails->setHeadWay($data['headway']); |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
return $transitDetails; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
/** |
310
|
|
|
* @param mixed[] $data |
311
|
|
|
* |
312
|
|
|
* @return DirectionTransitLine |
313
|
|
|
*/ |
314
|
|
|
private function buildTransitLine(array $data) |
315
|
|
|
{ |
316
|
|
|
$transitLine = new DirectionTransitLine(); |
317
|
|
|
$transitLine->setName($data['name']); |
318
|
|
|
$transitLine->setShortName($data['short_name']); |
319
|
|
|
$transitLine->setVehicle($this->buildTransitVehicle($data['vehicle'])); |
320
|
|
|
$transitLine->setAgencies($this->buildTransitAgencies($data['agencies'])); |
321
|
|
|
|
322
|
|
|
if (isset($data['color'])) { |
323
|
|
|
$transitLine->setColor($data['color']); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
if (isset($data['url'])) { |
327
|
|
|
$transitLine->setUrl($data['url']); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
if (isset($data['icon'])) { |
331
|
|
|
$transitLine->setIcon($data['icon']); |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
if (isset($data['text_color'])) { |
335
|
|
|
$transitLine->setTextColor($data['text_color']); |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
return $transitLine; |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
/** |
342
|
|
|
* @param mixed[] $data |
343
|
|
|
* |
344
|
|
|
* @return DirectionTransitAgency[] |
345
|
|
|
*/ |
346
|
|
|
private function buildTransitAgencies(array $data) |
347
|
|
|
{ |
348
|
|
|
$agencies = []; |
349
|
|
|
|
350
|
|
|
foreach ($data as $agency) { |
351
|
|
|
$agencies[] = $this->buildTransitAgency($agency); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
return $agencies; |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
/** |
358
|
|
|
* @param mixed[] $data |
359
|
|
|
* |
360
|
|
|
* @return DirectionTransitAgency |
361
|
|
|
*/ |
362
|
|
|
private function buildTransitAgency(array $data) |
363
|
|
|
{ |
364
|
|
|
$transitAgency = new DirectionTransitAgency(); |
365
|
|
|
$transitAgency->setName($data['name']); |
366
|
|
|
$transitAgency->setPhone($data['phone']); |
367
|
|
|
$transitAgency->setUrl($data['url']); |
368
|
|
|
|
369
|
|
|
return $transitAgency; |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
/** |
373
|
|
|
* @param mixed[] $data |
374
|
|
|
* |
375
|
|
|
* @return DirectionTransitStop |
376
|
|
|
*/ |
377
|
|
|
private function buildTransitStop(array $data) |
378
|
|
|
{ |
379
|
|
|
$transitStop = new DirectionTransitStop(); |
380
|
|
|
$transitStop->setName($data['name']); |
381
|
|
|
$transitStop->setLocation($this->buildCoordinate($data['location'])); |
382
|
|
|
|
383
|
|
|
return $transitStop; |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
/** |
387
|
|
|
* @param mixed[] $data |
388
|
|
|
* |
389
|
|
|
* @return DirectionTransitVehicle |
390
|
|
|
*/ |
391
|
|
|
private function buildTransitVehicle(array $data) |
392
|
|
|
{ |
393
|
|
|
$transitVehicle = new DirectionTransitVehicle(); |
394
|
|
|
$transitVehicle->setName($data['name']); |
395
|
|
|
$transitVehicle->setIcon($data['icon']); |
396
|
|
|
$transitVehicle->setType($data['type']); |
397
|
|
|
|
398
|
|
|
return $transitVehicle; |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
/** |
402
|
|
|
* @param mixed[] $data |
403
|
|
|
* |
404
|
|
|
* @return Bound |
405
|
|
|
*/ |
406
|
|
|
private function buildBound(array $data) |
407
|
|
|
{ |
408
|
|
|
return new Bound( |
409
|
|
|
$this->buildCoordinate($data['southwest']), |
410
|
|
|
$this->buildCoordinate($data['northeast']) |
411
|
|
|
); |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
/** |
415
|
|
|
* @param mixed[] $data |
416
|
|
|
* |
417
|
|
|
* @return Coordinate |
418
|
|
|
*/ |
419
|
|
|
private function buildCoordinate(array $data) |
420
|
|
|
{ |
421
|
|
|
return new Coordinate($data['lat'], $data['lng']); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
/** |
425
|
|
|
* @param mixed[] $data |
426
|
|
|
* |
427
|
|
|
* @return Distance |
428
|
|
|
*/ |
429
|
|
|
private function buildDistance(array $data) |
430
|
|
|
{ |
431
|
|
|
return new Distance($data['value'], $data['text']); |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
/** |
435
|
|
|
* @param mixed[] $data |
436
|
|
|
* |
437
|
|
|
* @return Duration |
438
|
|
|
*/ |
439
|
|
|
private function buildDuration(array $data) |
440
|
|
|
{ |
441
|
|
|
return new Duration($data['value'], $data['text']); |
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
/** |
445
|
|
|
* @param string[] $data |
446
|
|
|
* |
447
|
|
|
* @return EncodedPolyline |
448
|
|
|
*/ |
449
|
|
|
private function buildEncodedPolyline(array $data) |
450
|
|
|
{ |
451
|
|
|
return new EncodedPolyline($data['points']); |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
/** |
455
|
|
|
* @param mixed[] $data |
456
|
|
|
* |
457
|
|
|
* @return Fare |
458
|
|
|
*/ |
459
|
|
|
private function buildFare(array $data) |
460
|
|
|
{ |
461
|
|
|
return new Fare($data['value'], $data['currency'], $data['text']); |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
/** |
465
|
|
|
* @param mixed[] $data |
466
|
|
|
* |
467
|
|
|
* @return Time |
468
|
|
|
*/ |
469
|
|
|
private function buildTime(array $data) |
470
|
|
|
{ |
471
|
|
|
return new Time( |
472
|
|
|
new \DateTime('@'.$data['value'], new \DateTimeZone($data['time_zone'])), |
473
|
|
|
$data['time_zone'], |
474
|
|
|
$data['text'] |
475
|
|
|
); |
476
|
|
|
} |
477
|
|
|
} |
478
|
|
|
|
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.