Completed
Push — master ( 20655c...87b69d )
by Jeroen
02:06
created

Geolocation::getAddresses()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
nop 2
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) $url .= $key . '=' . urlencode($value) . '&';
52
53
        // trim last &
54
        $url = trim($url, '&');
55
56
        if ($this->api_key) {
57
            $url .= '&key=' . $this->api_key;
58
        }
59
60
        // init curl
61
        $curl = curl_init();
62
63
        // set options
64
        curl_setopt($curl, CURLOPT_URL, $url);
65
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
66
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
67
        if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
68
69
        // execute
70
        $response = curl_exec($curl);
71
72
        // fetch errors
73
        $errorNumber = curl_errno($curl);
74
        $errorMessage = curl_error($curl);
75
76
        // close curl
77
        curl_close($curl);
78
79
        // we have errors
80
        if ($errorNumber != '') throw new Exception($errorMessage);
81
82
        // redefine response as json decoded
83
        $response = json_decode($response);
84
85
        // API returns with an error
86
        if (isset($response->error_message)) {
87
            throw new Exception($response->error_message);
88
        }
89
90
        // return the content
91
        return $response->results;
92
    }
93
94
    /**
95
     * Get address using latitude/longitude
96
     *
97
     * @param  float $latitude
98
     * @param  float $longitude
99
     * @return Address
100
     * @throws Exception
101
     */
102
    public function getAddress($latitude, $longitude): Address
103
    {
104
        $addressSuggestions = $this->getAddresses($latitude, $longitude);
105
106
        if (count($addressSuggestions) == 0) {
107
            throw Exception::noAddressFoundForCoordinates($latitude, $longitude);
108
        }
109
110
        return $addressSuggestions[0];
111
    }
112
113
    /**
114
     * Get possible addresses using latitude/longitude
115
     *
116
     * @param  float $latitude
117
     * @param  float $longitude
118
     * @return array
119
     * @throws Exception
120
     */
121
    public function getAddresses($latitude, $longitude)
122
    {
123
        // init results
124
        $addresses = array();
125
126
        // define result
127
        $addressSuggestions = $this->doCall(array(
128
            'latlng' => $latitude . ',' . $longitude,
129
            'sensor' => 'false'
130
        ));
131
132
        // loop addresses
133
        foreach ($addressSuggestions as $key => $addressSuggestion) {
134
            $addresses[$key] = Address::createFromGoogleResult($addressSuggestion);
135
        }
136
137
        return $addresses;
138
    }
139
140
    /**
141
     * Get coordinates latitude/longitude
142
     *
143
     * @param  null|string $street
144
     * @param  null|string $streetNumber
145
     * @param  null|string $city
146
     * @param  null|string $zip
147
     * @param  null|string $country
148
     * @return Coordinates
149
     * @throws Exception
150
     */
151
    public function getCoordinates(
152
        ?string $street = null,
153
        ?string $streetNumber = null,
154
        ?string $city = null,
155
        ?string $zip = null,
156
        ?string $country = null
157
    ): Coordinates {
158
        // init item
159
        $item = array();
160
161
        // add street
162
        if (!empty($street)) $item[] = $street;
163
164
        // add street number
165
        if (!empty($streetNumber)) $item[] = $streetNumber;
166
167
        // add city
168
        if (!empty($city)) $item[] = $city;
169
170
        // add zip
171
        if (!empty($zip)) $item[] = $zip;
172
173
        // add country
174
        if (!empty($country)) $item[] = $country;
175
176
        // define value
177
        $address = implode(' ', $item);
178
179
        // define result
180
        $results = $this->doCall(array(
181
            'address' => $address,
182
            'sensor' => 'false'
183
        ));
184
185
        if (!array_key_exists(0, $results)) {
186
            throw Exception::noCoordinatesFoundforAddress([$street, $streetNumber, $city, $zip, $country]);
187
        }
188
189
        return new Coordinates(
190
            $results[0]->geometry->location->lat,
191
            $results[0]->geometry->location->lng
192
        );
193
    }
194
}
195