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 — directions-duration-in-traffic ( daa8b3 )
by Eric
03:25 queued 13s
created

GeocoderProvider::buildBound()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 7
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
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\Geocoder;
13
14
use Geocoder\Provider\LocaleAwareProvider;
15
use Geocoder\Provider\LocaleTrait;
16
use Http\Client\HttpClient;
17
use Http\Message\MessageFactory;
18
use Ivory\GoogleMap\Base\Bound;
19
use Ivory\GoogleMap\Base\Coordinate;
20
use Ivory\GoogleMap\Service\AbstractService;
21
22
/**
23
 * @author GeLo <[email protected]>
24
 */
25
class GeocoderProvider extends AbstractService implements LocaleAwareProvider
26
{
27
    use LocaleTrait;
28
29
    /**
30
     * @var int|null
31
     */
32
    private $limit;
33
34
    /**
35
     * @param HttpClient     $client
36
     * @param MessageFactory $messageFactory
37
     */
38
    public function __construct(HttpClient $client, MessageFactory $messageFactory)
39
    {
40
        parent::__construct($client, $messageFactory, 'http://maps.googleapis.com/maps/api/geocode');
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function getLimit()
47
    {
48
        return $this->limit;
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public function limit($limit)
55
    {
56
        $this->limit = $limit;
57
58
        return $this;
59
    }
60
61
    /**
62
     * @param GeocoderRequest|string $request
63
     *
64
     * @return GeocoderResponse
65
     */
66
    public function geocode($request)
67
    {
68
        if (!$request instanceof GeocoderRequest) {
69
            $request = new GeocoderRequest($request);
70
        }
71
72
        if ($this->locale !== null && !$request->hasLanguage()) {
73
            $request->setLanguage($this->locale);
74
        }
75
76
        $response = $this->getClient()->sendRequest($this->createRequest($request->buildQuery()));
77
        $data = $this->parse((string) $response->getBody());
78
79
        return $this->buildResponse($data);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->buildResponse($data); (Ivory\GoogleMap\Service\Geocoder\GeocoderResponse) is incompatible with the return type declared by the interface Geocoder\Geocoder::geocode of type Geocoder\Model\AddressCollection.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
80
    }
81
82
    /**
83
     * @param float $latitude
84
     * @param float $longitude
85
     *
86
     * @return GeocoderResponse
87
     */
88
    public function reverse($latitude, $longitude)
89
    {
90
        return $this->geocode(new Coordinate($latitude, $longitude));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->geocode(ne...latitude, $longitude)); (Ivory\GoogleMap\Service\Geocoder\GeocoderResponse) is incompatible with the return type declared by the interface Geocoder\Geocoder::reverse of type Geocoder\Model\AddressCollection.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
Documentation introduced by
new \Ivory\GoogleMap\Bas...($latitude, $longitude) is of type object<Ivory\GoogleMap\Base\Coordinate>, but the function expects a object<Ivory\GoogleMap\S...GeocoderRequest>|string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96
    public function getName()
97
    {
98
        return 'ivory_google_map';
99
    }
100
101
    /**
102
     * @param string $data
103
     *
104
     * @return mixed[]
105
     */
106
    private function parse($data)
107
    {
108
        if ($this->getFormat() === self::FORMAT_JSON) {
109
            return json_decode($data, true);
110
        }
111
112
        return $this->getXmlParser()->parse($data, [
113
            'address_component' => 'address_components',
114
            'type'              => 'types',
115
            'result'            => 'results',
116
        ]);
117
    }
118
119
    /**
120
     * @param mixed[] $data
121
     *
122
     * @return GeocoderResponse
123
     */
124
    private function buildResponse(array $data)
125
    {
126
        $results = [];
127
        foreach ($data['results'] as $index => $response) {
128
            $results[] = $this->buildResult($response);
129
130
            if ($this->limit !== null && ++$index >= $this->limit) {
131
                break;
132
            }
133
        }
134
135
        $response = new GeocoderResponse();
136
        $response->setStatus($data['status']);
137
        $response->setResults($results);
138
139
        return $response;
140
    }
141
142
    /**
143
     * @param mixed[] $data
144
     *
145
     * @return GeocoderResult
146
     */
147
    private function buildResult(array $data)
148
    {
149
        $result = new GeocoderResult();
150
        $result->setPlaceId($data['place_id']);
151
        $result->setAddressComponents($this->buildAddressComponents($data['address_components']));
152
        $result->setFormattedAddress($data['formatted_address']);
153
        $result->setGeometry($this->buildGeometry($data['geometry']));
154
        $result->setTypes(isset($data['types']) ? $data['types'] : []);
155
        $result->setPartialMatch(isset($data['partial_match']) ? $data['partial_match'] : null);
156
157
        return $result;
158
    }
159
160
    /**
161
     * @param mixed[] $data
162
     *
163
     * @return GeocoderAddressComponent[]
164
     */
165
    private function buildAddressComponents(array $data)
166
    {
167
        $addressComponents = [];
168
169
        foreach ($data as $item) {
170
            $addressComponents[] = $this->buildAddressComponent($item);
171
        }
172
173
        return $addressComponents;
174
    }
175
176
    /**
177
     * @param mixed[] $data
178
     *
179
     * @return GeocoderAddressComponent
180
     */
181
    private function buildAddressComponent(array $data)
182
    {
183
        $addressComponent = new GeocoderAddressComponent();
184
        $addressComponent->setLongName($data['long_name']);
185
        $addressComponent->setShortName($data['short_name']);
186
        $addressComponent->setTypes($data['types']);
187
188
        return $addressComponent;
189
    }
190
191
    /**
192
     * @param mixed[] $data
193
     *
194
     * @return GeocoderGeometry
195
     */
196
    private function buildGeometry(array $data)
197
    {
198
        $geometry = new GeocoderGeometry();
199
        $geometry->setBound(isset($data['bounds']) ? $this->buildBound($data['bounds']) : null);
200
        $geometry->setLocation($this->buildCoordinate($data['location']));
201
        $geometry->setLocationType($data['location_type']);
202
        $geometry->setViewport($this->buildBound($data['viewport']));
203
204
205
        return $geometry;
206
    }
207
208
    /**
209
     * @param mixed[] $data
210
     *
211
     * @return Bound
212
     */
213
    private function buildBound(array $data)
214
    {
215
        return new Bound(
216
            $this->buildCoordinate($data['southwest']),
217
            $this->buildCoordinate($data['northeast'])
218
        );
219
    }
220
221
    /**
222
     * @param mixed[] $data
223
     *
224
     * @return Coordinate
225
     */
226
    private function buildCoordinate(array $data)
227
    {
228
        return new Coordinate($data['lat'], $data['lng']);
229
    }
230
}
231