PluginProbe
Leaflet Map / trunk
Leaflet Map vtrunk
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.leaflet-map.php

class.leaflet-map.php in Leaflet Map trunk, at class.leaflet-map.php

532 lines 15.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Leaflet Map Class File
4 *
5 * @category Admin
6 * @author Benjamin J DeLong <ben@bozdoz.com>
7 */
8
9 // Exit if accessed directly
10 if (!defined('ABSPATH')) {
11 exit;
12 }
13
14 /**
15 * Leaflet Map Class
16 */
17 class Leaflet_Map
18 {
19
20 /**
21 * Leaflet version
22 *
23 * @var string major minor patch version
24 */
25 public static $leaflet_version = '1.9.4';
26
27 /**
28 * Files to include upon init
29 *
30 * @var array $_shortcodes
31 */
32 private $_shortcodes = array(
33 'leaflet-geojson' => array(
34 'file' => 'class.geojson-shortcode.php',
35 'class' => 'Leaflet_Geojson_Shortcode'
36 ),
37 'leaflet-image' => array(
38 'file' => 'class.image-shortcode.php',
39 'class' => 'Leaflet_Image_Shortcode'
40 ),
41 'leaflet-kml' => array(
42 'file' => 'class.kml-shortcode.php',
43 'class' => 'Leaflet_Kml_Shortcode'
44 ),
45 'leaflet-gpx' => array(
46 'file' => 'class.gpx-shortcode.php',
47 'class' => 'Leaflet_Gpx_Shortcode'
48 ),
49 'leaflet-wms' => array(
50 'file' => 'class.wms-shortcode.php',
51 'class' => 'Leaflet_Wms_Shortcode'
52 ),
53 'leaflet-line' => array(
54 'file' => 'class.line-shortcode.php',
55 'class' => 'Leaflet_Line_Shortcode'
56 ),
57 'leaflet-polygon' => array(
58 'file' => 'class.polygon-shortcode.php',
59 'class' => 'Leaflet_Polygon_Shortcode'
60 ),
61 'leaflet-circle' => array(
62 'file' => 'class.circle-shortcode.php',
63 'class' => 'Leaflet_Circle_Shortcode'
64 ),
65 'leaflet-map' => array(
66 'file' => 'class.map-shortcode.php',
67 'class' => 'Leaflet_Map_Shortcode'
68 ),
69 'leaflet-marker' => array(
70 'file' => 'class.marker-shortcode.php',
71 'class' => 'Leaflet_Marker_Shortcode'
72 ),
73 'leaflet-scale' => array(
74 'file' => 'class.scale-shortcode.php',
75 'class' => 'Leaflet_Scale_Shortcode'
76 ),
77 'leaflet-image-overlay' => array(
78 'file' => 'class.image-overlay-shortcode.php',
79 'class' => 'Leaflet_Image_Overlay_Shortcode'
80 ),
81 'leaflet-video-overlay' => array(
82 'file' => 'class.video-overlay-shortcode.php',
83 'class' => 'Leaflet_Video_Overlay_Shortcode'
84 ),
85 );
86
87 /**
88 * Singleton Instance of Leaflet Map
89 *
90 * @var Leaflet_Map
91 **/
92 private static $instance = null;
93
94 /**
95 * Singleton init Function
96 *
97 * @static
98 */
99 public static function init() {
100 if ( !self::$instance ) {
101 self::$instance = new self;
102 }
103
104 return self::$instance;
105 }
106
107 /**
108 * Leaflet_Map Constructor
109 */
110 private function __construct() {
111 $this->init_hooks();
112 $this->add_shortcodes();
113
114 // loaded
115 do_action('leaflet_map_loaded');
116 }
117
118 /**
119 * Add actions and filters
120 */
121 private function init_hooks()
122 {
123
124 // Leaflet_Map_Plugin_Settings
125 include_once LEAFLET_MAP__PLUGIN_DIR . 'class.plugin-settings.php';
126
127 // Leaflet_Map_Admin
128 include_once LEAFLET_MAP__PLUGIN_DIR . 'class.admin.php';
129
130 // init admin
131 Leaflet_Map_Admin::init();
132
133 add_action( 'plugins_loaded', array('Leaflet_Map', 'load_text_domain' ));
134
135 add_action( 'wp_enqueue_scripts', array('Leaflet_Map', 'enqueue_and_register') );
136
137 $settings = self::settings();
138
139 if ($settings->get('shortcode_in_excerpt')) {
140 // allows maps in excerpts
141 add_filter('the_excerpt', 'do_shortcode');
142 }
143 }
144
145 /**
146 * Includes and adds shortcodes
147 */
148 private function add_shortcodes()
149 {
150 // shortcodes
151 $shortcode_dir = LEAFLET_MAP__PLUGIN_DIR . 'shortcodes/';
152
153 foreach ($this->_shortcodes as $shortcode => $details) {
154 include_once $shortcode_dir . $details['file'];
155 add_shortcode($shortcode, array($details['class'], 'shortcode'));
156 }
157 }
158
159 /**
160 * Triggered when user uninstalls/removes plugin
161 */
162 public static function uninstall()
163 {
164 // remove settings in db
165 // it needs to be included again because __construct
166 // won't need to execute
167 $settings = self::settings();
168 $settings->reset();
169
170 // remove geocoder locations in db
171 include_once LEAFLET_MAP__PLUGIN_DIR . 'class.geocoder.php';
172 Leaflet_Geocoder::remove_caches();
173 }
174
175 /**
176 * Loads Translations
177 */
178 public static function load_text_domain()
179 {
180 load_plugin_textdomain( 'leaflet-map', false, dirname( plugin_basename( LEAFLET_MAP__PLUGIN_FILE ) ) . '/languages/' );
181 }
182
183 /**
184 * Enqueue and register styles and scripts (called in __construct)
185 */
186 public static function enqueue_and_register()
187 {
188 /* defaults from db */
189 $settings = self::settings();
190
191 $js_url = $settings->get('js_url');
192 $css_url = $settings->get('css_url');
193
194 wp_register_style('leaflet_stylesheet', $css_url, Array(), null, false);
195 wp_register_script('leaflet_js', $js_url, Array(), null, true);
196
197 // new required MapQuest javascript file
198 $tiling_service = $settings->get('default_tiling_service');
199
200 if ($tiling_service == 'mapquest') {
201 $mapquest_js_url = 'https://www.mapquestapi.com/sdk/leaflet/v2.2/mq-map.js?key=%s';
202 $mq_appkey = $settings->get('mapquest_appkey');
203 $mapquest_js_url = sprintf($mapquest_js_url, $mq_appkey);
204
205 wp_register_script('leaflet_mapquest_plugin', $mapquest_js_url, Array('leaflet_js'), '2.0', true);
206 }
207
208 // optional ajax geojson plugin
209 wp_register_script('tmcw_togeojson', $settings->get('togeojson_url'), Array('jquery'), LEAFLET_MAP__PLUGIN_VERSION, false);
210
211 if (defined('WP_DEBUG') && WP_DEBUG) {
212 $minified = '';
213 } else {
214 $minified = '.min';
215 }
216
217 wp_register_script('leaflet_ajax_geojson_js', plugins_url(sprintf('scripts/leaflet-ajax-geojson%s.js', $minified), __FILE__), Array('tmcw_togeojson', 'leaflet_js'), LEAFLET_MAP__PLUGIN_VERSION, false);
218
219 wp_register_script('leaflet_svg_icon_js', plugins_url(sprintf('scripts/leaflet-svg-icon%s.js', $minified), __FILE__), Array('leaflet_js'), LEAFLET_MAP__PLUGIN_VERSION, false);
220
221 /* run a construct function in the document head for subsequent functions to use (it is lightweight) */
222 wp_register_script('wp_leaflet_map', plugins_url(sprintf('scripts/construct-leaflet-map%s.js', $minified), __FILE__), Array('leaflet_js'), LEAFLET_MAP__PLUGIN_VERSION, false);
223 }
224
225 /**
226 * Filter for removing nulls from array
227 *
228 * @param array $arr
229 *
230 * @return array with nulls removed
231 */
232 public function filter_null($arr)
233 {
234 if (!function_exists('remove_null')) {
235 function remove_null ($var) {
236 return $var !== null;
237 }
238 }
239
240 return array_filter($arr, 'remove_null');
241 }
242
243 /**
244 * Filter for removing empty strings from array
245 *
246 * @param array $arr
247 *
248 * @return array with empty strings removed
249 */
250 public function filter_empty_string($arr)
251 {
252 if (!function_exists('remove_empty_string')) {
253 function remove_empty_string ($var) {
254 return $var !== "";
255 }
256 }
257
258 return array_filter($arr, 'remove_empty_string');
259 }
260
261 /**
262 * Sanitize any given validations, but concatenate with the remaining keys from $arr
263 */
264 public function sanitize_inclusive($arr, $validations) {
265 return array_merge(
266 $arr,
267 $this->sanitize_exclusive($arr, $validations)
268 );
269 }
270
271 /**
272 * Sanitize and return ONLY given validations
273 */
274 public function sanitize_exclusive($arr, $validations) {
275 // remove nulls
276 $arr = $this->filter_null($arr);
277
278 // sanitize output
279 $args = array_intersect_key($validations, $arr);
280 return filter_var_array($arr, $args);
281 }
282
283 /**
284 * Sanitize JSON
285 *
286 * Takes options for filtering/correcting inputs for use in JavaScript
287 *
288 * @param array $arr user-input array
289 * @param array $args array with key-value definitions on how to convert values
290 * @return array corrected for JavaScript
291 */
292 public function json_sanitize($arr, $args)
293 {
294 $arr = $this->sanitize_exclusive($arr, $args);
295
296 $output = json_encode($arr);
297
298 // always return object; not array
299 if ($output === '[]') {
300 $output = '{}';
301 }
302
303 return $output;
304 }
305
306 /**
307 * Get Style JSON for map shapes/geojson (svg or canvas)
308 *
309 * Takes atts for creating shapes on the map
310 *
311 * @param array $atts user-input array
312 *
313 * @return array corrected for JavaScript
314 */
315 public function get_style_json($atts)
316 {
317 if ($atts) {
318 extract($atts, EXTR_SKIP);
319 }
320
321 // from http://leafletjs.com/reference-1.0.3.html#path
322 $style = array(
323 'stroke' => isset($stroke) ? $stroke : null,
324 'color' => isset($color) ? $color : null,
325 'weight' => isset($weight) ? $weight : null,
326 'opacity' => isset($opacity) ? $opacity : null,
327 'lineCap' => isset($linecap) ? $linecap : null,
328 'lineJoin' => isset($linejoin) ? $linejoin : null,
329 'dashArray' => isset($dasharray) ? $dasharray : null,
330 'dashOffset' => isset($dashoffset) ? $dashoffset : null,
331 'fill' => isset($fill) ? $fill : null,
332 'fillColor' => isset($fillcolor) ? $fillcolor : null,
333 'fillOpacity' => isset($fillopacity) ? $fillopacity : null,
334 'fillRule' => isset($fillrule) ? $fillrule : null,
335 'className' => isset($classname) ? $classname : null,
336 'radius' => isset($radius) ? $radius : null
337 );
338
339 $args = array(
340 'stroke' => FILTER_VALIDATE_BOOLEAN,
341 'color' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
342 'weight' => FILTER_VALIDATE_FLOAT,
343 'opacity' => FILTER_VALIDATE_FLOAT,
344 'lineCap' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
345 'lineJoin' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
346 'dashArray' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
347 'dashOffset' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
348 'fill' => FILTER_VALIDATE_BOOLEAN,
349 'fillColor' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
350 'fillOpacity' => FILTER_VALIDATE_FLOAT,
351 'fillRule' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
352 'className' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
353 'radius' => FILTER_VALIDATE_FLOAT
354 );
355
356 return $this->json_sanitize($style, $args);
357 }
358
359 /**
360 * Add Popups to Shapes
361 *
362 * used by leaflet-marker, leaflet-line and leaflet-circle
363 *
364 * @param array $atts user-input array
365 * @param string $content text to display
366 * @param string $shape JavaScript variable for shape
367 *
368 * @return null
369 */
370 public function add_popup_to_shape($atts, $content, $shape)
371 {
372 if (!empty($atts)) {
373 // don't overwrite existing variables
374 extract($atts, EXTR_SKIP);
375 }
376
377 $message = empty($message) ?
378 (empty($content) ? '' : $content) : $message;
379
380 if (empty($message)) {
381 return;
382 }
383
384 // save variable for filter
385 $original = $message;
386
387 // execute shortcodes if present:
388 // e.g. [leaflet-marker][some-shortcode][/leaflet-marker]
389 $message = do_shortcode($message);
390
391 // save variable for filter
392 $shortcoded = $message;
393
394 $message = str_replace(array("\r\n", "\n", "\r"), '<br>', $message);
395 $message = wp_kses_post( $message );
396 $message = esc_html( $message );
397
398 $message = "window.WPLeafletMapPlugin.unescape('{$message}')";
399
400 // use with: add_filter('leaflet_map_popup_message', 'example_callback', 10, 3);
401 // function takes default message, message after do_shortcode, and original/raw
402 $message = apply_filters('leaflet_map_popup_message', $message, $shortcoded, $original);
403
404 echo "{$shape}.bindPopup({$message})";
405
406 $visible = empty($visible)
407 ? false
408 : filter_var($visible, FILTER_VALIDATE_BOOLEAN);
409
410 if ($visible) {
411 echo ".openPopup()";
412 }
413 echo ";";
414 }
415
416 /**
417 * Get settings from Leaflet_Map_Plugin_Settings
418 * @return Leaflet_Map_Plugin_Settings
419 */
420 public static function settings () {
421 include_once LEAFLET_MAP__PLUGIN_DIR . 'class.plugin-settings.php';
422 return Leaflet_Map_Plugin_Settings::init();
423 }
424
425 /**
426 * Parses liquid tags from a string
427 *
428 * @param string $str
429 *
430 * @return array|null
431 */
432 public function liquid ($str) {
433 if (!is_string($str)) {
434 return null;
435 }
436 $templateRegex = "/\{ *(.*?) *\}/";
437 preg_match_all($templateRegex, $str, $matches);
438
439 if (!$matches[1]) {
440 return null;
441 }
442
443 $str = $matches[1][0];
444
445 $tags = explode(' | ', $str);
446
447 $original = array_shift($tags);
448
449 if (!$tags) {
450 return null;
451 }
452
453 $output = array();
454
455 foreach ($tags as $tag) {
456 $tagParts = explode(': ', $tag);
457 $tagName = array_shift($tagParts);
458 $tagValue = implode(': ', $tagParts) || true;
459
460 $output[$tagName] = $tagValue;
461 }
462
463 // preserve the original
464 $output['original'] = $original;
465
466 return $output;
467 }
468
469 /**
470 * Renders a json-like string, removing quotes for values
471 *
472 * allows JavaScript variables to be added directly
473 *
474 * @return string
475 */
476 public function rawDict ($arr) {
477 $obj = '{';
478
479 foreach ($arr as $key=>$val) {
480 // removes any JS function calls
481 $safe_val = preg_replace('/[^a-zA-Z0-9_$.!]/', '', $val);
482 $obj .= "\"$key\": $safe_val,";
483 }
484
485 $obj .= '}';
486
487 return $obj;
488 }
489
490 /**
491 * Filter all floats to remove commas, force decimals, and validate float
492 * see: https://wordpress.org/support/topic/all-maps-are-gone/page/3/#post-14625548
493 */
494 public function filter_float ($flt) {
495 // make sure the value actually is a float
496 $out = filter_var($flt, FILTER_VALIDATE_FLOAT);
497
498 // some locales seem to force commas
499 $out = str_replace(',', '.', $out);
500
501 return $out;
502 }
503
504 /**
505 * Bounds are given as "50, -114; 52, -112"
506 * Converted to 2d-array: [[50, -114], [52, -112]]
507 */
508 public function convert_bounds_str_to_arr ($bounds) {
509 if (isset($bounds)) {
510 try {
511 // explode by semi-colons and commas
512 $arr = preg_split("[;|,]", $bounds);
513
514 return array(
515 array(
516 $this->filter_float($arr[0]),
517 $this->filter_float($arr[1])
518 ),
519 array(
520 $this->filter_float($arr[2]),
521 $this->filter_float($arr[3])
522 )
523 );
524 } catch (Exception $e) {
525 return null;
526 }
527 }
528
529 return null;
530 }
531 }
532