PluginProbe
Leaflet Map / 3.4.4
Leaflet Map v3.4.4
3.4.7 3.4.6 trunk 2.10.0 2.10.1 2.11.0 2.11.1 2.11.2 2.11.3 2.11.4 2.11.5 2.12.0 2.13.0 2.14.0 2.15.0 2.16.0 2.16.1 2.16.2 2.17.0 2.17.1 2.17.2 2.17.3 2.18.0 2.19.0 2.19.1 All 49 releases
leaflet-map / class.geocoder.php

class.geocoder.php in Leaflet Map 3.4.4, at class.geocoder.php

284 lines 8.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Geocoder
4 *
5 * calls the specific geocoder function (chosen in admin or default: google_geocode)
6 *
7 */
8
9 class Leaflet_Geocoder {
10 /**
11 * Geocoder should return this on error/not found
12 * @var array $not_found
13 */
14 private $not_found = array('lat' => 0, 'lng' => 0);
15 /**
16 * Latitude
17 * @var float $lat
18 */
19 public $lat = 0;
20 /**
21 * Longitude
22 * @var float $lng
23 */
24 public $lng = 0;
25
26 /**
27 * new Geocoder from address
28 *
29 * handles url encoding and caching
30 *
31 * @param string $address the requested address to look up
32 * @return NOTHING
33 */
34 public function __construct ($address) {
35 $settings = Leaflet_Map_Plugin_Settings::init();
36 // trim all quotes (even smart) from address
37 $address = trim($address, '\'"”');
38 $address = urlencode( $address );
39
40 $geocoder = $settings->get('geocoder');
41
42 $cached_address = 'leaflet_' . $geocoder . '_' . $address;
43
44 /* retrieve cached geocoded location */
45 $found_cache = get_option( $cached_address );
46
47 if ( $this->is_valid_cached_location( $found_cache ) ) {
48 $location = $found_cache;
49 } else {
50 if ( false !== $found_cache ) {
51 $this->remove_cache_key( $cached_address );
52 }
53
54 // try geocoding
55 $geocoding_method = $geocoder . '_geocode';
56
57 try {
58 $location = (Object) $this->$geocoding_method( $address );
59
60 if ( ! $this->is_valid_cached_location( $location ) ) {
61 throw new Exception('Invalid geocoder response');
62 }
63
64 /* add location */
65 add_option($cached_address, $location);
66
67 /* add option key to locations for clean up purposes */
68 $locations = get_option('leaflet_geocoded_locations', array());
69 if ( ! in_array( $cached_address, $locations, true ) ) {
70 array_push($locations, $cached_address);
71 update_option('leaflet_geocoded_locations', $locations);
72 }
73 } catch (Exception $e) {
74 // failed
75 $location = $this->not_found;
76 }
77 }
78
79 if (isset($location->lat) && isset($location->lng)) {
80 $this->lat = $location->lat;
81 $this->lng = $location->lng;
82 }
83 }
84
85 /**
86 * Removes location caches
87 */
88 public static function remove_caches () {
89 $addresses = get_option('leaflet_geocoded_locations', array());
90 foreach ($addresses as $address) {
91 delete_option($address);
92 }
93 delete_option('leaflet_geocoded_locations');
94 }
95
96 /**
97 * Determines whether a cached geocode entry is valid.
98 *
99 * @param mixed $location Cached location value from WordPress options.
100 * @return bool
101 */
102 private function is_valid_cached_location( $location ) {
103 if ( ! is_object( $location ) ) {
104 return false;
105 }
106
107 if ( ! isset( $location->lat ) || ! isset( $location->lng ) ) {
108 return false;
109 }
110
111 return filter_var( $location->lat, FILTER_VALIDATE_FLOAT ) !== false
112 && filter_var( $location->lng, FILTER_VALIDATE_FLOAT ) !== false;
113 }
114
115 /**
116 * Removes a single geocode cache entry and its registry reference.
117 *
118 * @param string $cached_address Option key for the cached geocode.
119 * @return void
120 */
121 private function remove_cache_key( $cached_address ) {
122 delete_option( $cached_address );
123
124 $addresses = get_option( 'leaflet_geocoded_locations', array() );
125 $addresses = array_values(
126 array_filter(
127 $addresses,
128 function ( $address ) use ( $cached_address ) {
129 return $address !== $cached_address;
130 }
131 )
132 );
133
134 if ( empty( $addresses ) ) {
135 delete_option( 'leaflet_geocoded_locations' );
136 } else {
137 update_option( 'leaflet_geocoded_locations', $addresses );
138 }
139 }
140
141 /**
142 * Used by geocoders to make requests via curl or file_get_contents
143 *
144 * includes a try/catch
145 *
146 * @param string $url the urlencoded request url
147 * @return varies object from API or null (failed)
148 */
149 private function get_url( $url ) {
150 $referer = get_site_url();
151
152 if (in_array('curl', get_loaded_extensions())) {
153 /* try curl */
154 $ch = curl_init();
155
156 curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
157 curl_setopt($ch, CURLOPT_HEADER, 0);
158 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
159 curl_setopt($ch, CURLOPT_REFERER, $referer);
160 curl_setopt($ch, CURLOPT_URL, $url);
161 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
162
163 $data = curl_exec($ch);
164 curl_close($ch);
165
166 return $data;
167 } else if (ini_get('allow_url_fopen')) {
168 /* try file get contents */
169
170 $opts = array(
171 'http' => array(
172 'header' => array("Referer: $referer\r\n")
173 )
174 );
175 $context = stream_context_create($opts);
176
177 return file_get_contents($url, false, $context);
178 }
179
180 $error_msg = 'Could not get url: ' . $url;
181 throw new Exception( $error_msg );
182 }
183
184 /**
185 * Google geocoder (https://developers.google.com/maps/documentation/geocoding/start)
186 *
187 * @param string $address the urlencoded address to look up
188 * @return varies object from API or null (failed)
189 */
190
191 private function google_geocode ( $address ) {
192 // Leaflet_Map_Plugin_Settings
193 $settings = Leaflet_Map_Plugin_Settings::init();
194 $key = $settings->get('google_appkey');
195
196 $geocode_url = 'https://maps.googleapis.com/maps/api/geocode/json?address=%s&key=%s';
197 $geocode_url = sprintf($geocode_url, $address, $key);
198
199 $json = $this->get_url($geocode_url);
200 $json = json_decode($json);
201
202 /* found location */
203 if ($json->status == 'OK') {
204
205 $location = $json->results[0]->geometry->location;
206
207 return (Object) $location;
208 }
209
210 throw new Exception('No Address Found');
211 }
212
213 /**
214 * OpenStreetMap geocoder Nominatim (https://nominatim.openstreetmap.org/)
215 *
216 * @param string $address The URL-encoded address to look up.
217 * @return object Object containing lat and lng properties.
218 * @throws Exception When the request fails or no valid coordinates are returned.
219 */
220 private function osm_geocode( $address ) {
221 $request_url = sprintf(
222 'https://nominatim.openstreetmap.org/search?format=jsonv2&limit=1&q=%s',
223 $address
224 );
225
226 $accept_language = str_replace( '_', '-', get_locale() );
227
228 $settings = Leaflet_Map_Plugin_Settings::init();
229 $contact_email = $settings->get( 'nominatim_contact_email' );
230
231 if ( empty( $contact_email ) ) {
232 $contact_email = get_bloginfo( 'admin_email' );
233 }
234
235 $contact_email = apply_filters( 'leaflet_map_nominatim_contact_email', $contact_email );
236
237 $agent = 'Nominatim query for ' . get_bloginfo( 'url' ) . '; contact ' . $contact_email;
238
239 $response = wp_remote_get(
240 $request_url,
241 array(
242 'user-agent' => $agent,
243 'headers' => array(
244 'Accept-Language' => $accept_language,
245 ),
246 )
247 );
248
249 if ( ! is_wp_error( $response ) && isset( $response['body'] ) ) {
250 $json = json_decode( $response['body'] );
251
252 if ( isset( $json[0]->lat ) && isset( $json[0]->lon ) ) {
253 return (object) array(
254 'lat' => $json[0]->lat,
255 'lng' => $json[0]->lon,
256 );
257 }
258 }
259
260 throw new Exception('No Address Found');
261 }
262
263 /**
264 * TODO: does this still work?
265 * Danish Addresses Web Application
266 * (https://dawa.aws.dk)
267 *
268 * @param string $address the urlencoded address to look up
269 * @return varies object from API or null (failed)
270 */
271 private function dawa_geocode ( $address ) {
272 $geocode_url = 'https://dawa.aws.dk/adresser?format=json&q=';
273 $geocode_url .= $address;
274 $json = $this->get_url($geocode_url);
275 $json = json_decode($json);
276
277 /* found location */
278 return (Object) array(
279 'lat' => $json[0]->adgangsadresse->adgangspunkt->koordinater[1],
280 'lng' => $json[0]->adgangsadresse->adgangspunkt->koordinater[0]
281 );
282 }
283 }
284