GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( bcefff...98364d )
by Eric
03:01
created

DirectionService   F

Complexity

Total Complexity 51

Size/Duplication

Total Lines 439
Duplicated Lines 1.59 %

Coupling/Cohesion

Components 1
Dependencies 22

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 51
c 1
b 0
f 1
lcom 1
cbo 22
dl 7
loc 439
rs 3.1761

25 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A route() 7 7 1
A parse() 0 13 2
A buildResponse() 0 19 4
A buildRoutes() 0 10 2
B buildRoute() 0 29 6
A buildGeocodedWaypoints() 0 10 2
A buildGeocodedWaypoint() 0 16 3
A buildLegs() 0 10 2
B buildLeg() 0 29 5
A buildSteps() 0 10 2
A buildStep() 0 17 2
A buildTransitDetails() 0 17 2
B buildTransitLine() 0 26 5
A buildTransitAgencies() 0 10 2
A buildTransitAgency() 0 9 1
A buildTransitStop() 0 8 1
A buildTransitVehicle() 0 9 1
A buildBound() 0 7 1
A buildCoordinate() 0 4 1
A buildDistance() 0 4 1
A buildDuration() 0 4 1
A buildEncodedPolyline() 0 4 1
A buildFare() 0 4 1
A buildTime() 0 8 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like DirectionService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DirectionService, and based on these observations, apply Extract Interface, too.

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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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