Completed
Push — master ( 6e41f1...beeb83 )
by Jeroen
02:59
created

Geolocation::getCoordinates()   B

Complexity

Conditions 7
Paths 64

Size

Total Lines 53
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 53
rs 7.5251
cc 7
eloc 27
nc 64
nop 5

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace JeroenDesloovere\Geolocation;
4
5
use JeroenDesloovere\Geolocation\Result\Address;
6
use JeroenDesloovere\Geolocation\Result\Coordinates;
7
8
/**
9
 * Geolocation
10
 *
11
 * Get latitude/longitude or address using Google Maps API
12
 *
13
 * @author Jeroen Desloovere <[email protected]>
14
 */
15
class Geolocation
16
{
17
    // API URL
18
    const API_URL = 'maps.googleapis.com/maps/api/geocode/json';
19
20
    private $api_key;
21
    private $https;
22
23
    public function __construct($api_key = null, $https = false)
24
    {
25
        $this->https = $https;
26
27
        if ($api_key) {
28
            $this->api_key = $api_key;
29
            $this->https = true;
30
        }
31
    }
32
33
    /**
34
     * Do call
35
     *
36
     * @param  array $parameters
37
     * @return mixed
38
     * @throws Exception
39
     */
40
    protected function doCall($parameters = array())
41
    {
42
        // check if curl is available
43
        if (!function_exists('curl_init')) {
44
            throw Exception::CurlNotInstalled();
45
        }
46
47
        // define url
48
        $url = ($this->https ? 'https://' : 'http://') . self::API_URL . '?';
49
50
        // add every parameter to the url
51
        foreach ($parameters as $key => $value) {
52
            $url .= $key . '=' . urlencode($value) . '&';
53
        }
54
55
        // trim last &
56
        $url = trim($url, '&');
57
58
        if ($this->api_key) {
59
            $url .= '&key=' . $this->api_key;
60
        }
61
62
        // init curl
63
        $curl = curl_init();
64
65
        // set options
66
        curl_setopt($curl, CURLOPT_URL, $url);
67
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
68
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
69
        if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
70
            curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
71
        }
72
73
        // execute
74
        $response = curl_exec($curl);
75
76
        // fetch errors
77
        $errorNumber = curl_errno($curl);
78
        $errorMessage = curl_error($curl);
79
80
        // close curl
81
        curl_close($curl);
82
83
        // we have errors
84
        if ($errorNumber != '') {
85
            throw new Exception($errorMessage);
86
        }
87
88
        // redefine response as json decoded
89
        $response = json_decode($response);
90
91
        // API returns with an error
92
        if (isset($response->error_message)) {
93
            throw new Exception($response->error_message);
94
        }
95
96
        // return the content
97
        return $response->results;
98
    }
99
100
    /**
101
     * Get address using latitude/longitude
102
     *
103
     * @param  float $latitude
104
     * @param  float $longitude
105
     * @return Address
106
     * @throws Exception
107
     */
108
    public function getAddress($latitude, $longitude): Address
109
    {
110
        $addressSuggestions = $this->getAddresses($latitude, $longitude);
111
112
        if (count($addressSuggestions) == 0) {
113
            throw Exception::noAddressFoundForCoordinates($latitude, $longitude);
114
        }
115
116
        return $addressSuggestions[0];
117
    }
118
119
    /**
120
     * Get possible addresses using latitude/longitude
121
     *
122
     * @param  float $latitude
123
     * @param  float $longitude
124
     * @return array
125
     * @throws Exception
126
     */
127
    public function getAddresses($latitude, $longitude)
128
    {
129
        // init results
130
        $addresses = array();
131
132
        // define result
133
        $addressSuggestions = $this->doCall(array(
134
            'latlng' => $latitude . ',' . $longitude,
135
            'sensor' => 'false'
136
        ));
137
138
        // loop addresses
139
        foreach ($addressSuggestions as $key => $addressSuggestion) {
140
            $addresses[$key] = Address::createFromGoogleResult($addressSuggestion);
141
        }
142
143
        return $addresses;
144
    }
145
146
    /**
147
     * Get coordinates latitude/longitude
148
     *
149
     * @param  null|string $street
150
     * @param  null|string $streetNumber
151
     * @param  null|string $city
152
     * @param  null|string $zip
153
     * @param  null|string $country
154
     * @return Coordinates
155
     * @throws Exception
156
     */
157
    public function getCoordinates(
158
        ?string $street = null,
159
        ?string $streetNumber = null,
160
        ?string $city = null,
161
        ?string $zip = null,
162
        ?string $country = null
163
    ): Coordinates {
164
        // init item
165
        $item = array();
166
167
        // add street
168
        if (!empty($street)) {
169
            $item[] = $street;
170
        }
171
172
        // add street number
173
        if (!empty($streetNumber)) {
174
            $item[] = $streetNumber;
175
        }
176
177
        // add city
178
        if (!empty($city)) {
179
            $item[] = $city;
180
        }
181
182
        // add zip
183
        if (!empty($zip)) {
184
            $item[] = $zip;
185
        }
186
187
        // add country
188
        if (!empty($country)) {
189
            $item[] = $country;
190
        }
191
192
        // define value
193
        $address = implode(' ', $item);
194
195
        // define result
196
        $results = $this->doCall(array(
197
            'address' => $address,
198
            'sensor' => 'false'
199
        ));
200
201
        if (!array_key_exists(0, $results)) {
202
            throw Exception::noCoordinatesFoundforAddress([$street, $streetNumber, $city, $zip, $country]);
203
        }
204
205
        return new Coordinates(
206
            $results[0]->geometry->location->lat,
207
            $results[0]->geometry->location->lng
208
        );
209
    }
210
}
211