PageRenderTime 65ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/wp-flexible-map/class.FlxMapPlugin.php

https://gitlab.com/lobsterhands/OctaveHigherEast
PHP | 490 lines | 305 code | 84 blank | 101 comment | 110 complexity | 02f8317656ba3cf1113f44371a205439 MD5 | raw file
  1. <?php
  2. /**
  3. * class for managing the plugin
  4. */
  5. class FlxMapPlugin {
  6. public $urlBase; // string: base URL path to files in plugin
  7. protected $locale;
  8. /**
  9. * static method for getting the instance of this singleton object
  10. *
  11. * @return FlxMapPlugin
  12. */
  13. public static function getInstance() {
  14. static $instance = null;
  15. if (is_null($instance)) {
  16. $instance = new self();
  17. }
  18. return $instance;
  19. }
  20. /**
  21. * hook the plug-in's initialise event to handle all post-activation initialisation
  22. */
  23. private function __construct() {
  24. // record plugin URL base
  25. $this->urlBase = plugin_dir_url(__FILE__);
  26. add_action('init', array($this, 'actionInit'));
  27. if (is_admin()) {
  28. // kick off the admin handling
  29. require FLXMAP_PLUGIN_ROOT . 'class.FlxMapAdmin.php';
  30. new FlxMapAdmin($this);
  31. }
  32. else {
  33. // non-admin actions and filters for this plugin
  34. add_action('wp_enqueue_scripts', array($this, 'actionEnqueueScripts'));
  35. add_filter('clean_url', array($this, 'filterCleanURL'), 11);
  36. // custom actions and filters for this plugin
  37. add_filter('flexmap_getmap', array($this, 'getMap'), 10, 1);
  38. }
  39. if (!is_admin() || (defined('DOING_AJAX') && DOING_AJAX)) {
  40. // add shortcodes
  41. add_shortcode(FLXMAP_PLUGIN_TAG_MAP, array($this, 'shortcodeMap'));
  42. }
  43. }
  44. /**
  45. * initialise the plugin, called on init action
  46. */
  47. public function actionInit() {
  48. // start off required locales with this website's WP locale
  49. $this->locale = get_locale();
  50. }
  51. /**
  52. * hack: add charset='utf-8' to i18n scripts
  53. * @param string $url
  54. * @return string
  55. */
  56. public function filterCleanURL($url) {
  57. if (stripos($url, $this->urlBase . 'i18n/') !== false) {
  58. return "$url' charset='utf-8";
  59. }
  60. return $url;
  61. }
  62. /**
  63. * set the reqired locales so that appropriate scripts will be loaded
  64. * @param array $locales a list of locale names
  65. */
  66. public function setLocales($locales) {
  67. foreach ($locales as $locale) {
  68. $this->enqueueLocale(strtr($locale, '_', '-'));
  69. }
  70. }
  71. /**
  72. * register and enqueue any scripts and styles we require
  73. */
  74. public function actionEnqueueScripts() {
  75. // allow others to override the Google Maps API URL
  76. $protocol = is_ssl() ? 'https' : 'http';
  77. $args = apply_filters('flexmap_google_maps_api_args', array('v' => '3.15', 'sensor' => 'false'));
  78. $apiURL = apply_filters('flexmap_google_maps_api_url', add_query_arg($args, "$protocol://maps.google.com/maps/api/js"));
  79. if (!empty($apiURL)) {
  80. wp_register_script('google-maps', $apiURL, false, null, true);
  81. }
  82. $min = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
  83. wp_register_script('flxmap', "{$this->urlBase}flexible-map$min.js", array('google-maps'), FLXMAP_PLUGIN_VERSION, true);
  84. // theme writers: you can remove this stylesheet by calling wp_dequeue_script('flxmap');
  85. wp_enqueue_style('flxmap', $this->urlBase . 'styles.css', false, FLXMAP_PLUGIN_VERSION);
  86. }
  87. /**
  88. * enqueue an i18n script
  89. * @param string $locale
  90. */
  91. protected function enqueueLocale($locale) {
  92. // check for specific locale first, e.g. 'zh-CN', then for generic locale, e.g. 'zh'
  93. foreach (array($locale, substr($locale, 0, 2)) as $locale) {
  94. if (file_exists(FLXMAP_PLUGIN_ROOT . "i18n/$locale.js")) {
  95. wp_enqueue_script('flxmap-' . $locale, $this->urlBase . "i18n/$locale.js", array('flxmap'), FLXMAP_PLUGIN_VERSION, true);
  96. break;
  97. }
  98. }
  99. }
  100. /**
  101. * handle shortcode for map display
  102. *
  103. * @param array shortcode attributes as supplied by the WP shortcode API
  104. * @return string output to substitute for the shortcode
  105. */
  106. public function shortcodeMap($attrs) {
  107. return $this->getMap($attrs);
  108. }
  109. /**
  110. * get HTML and script for map
  111. *
  112. * @param array shortcode attributes as supplied by the WP shortcode API
  113. * @return string HTML and script for the map
  114. */
  115. public function getMap($attrs) {
  116. $html = '';
  117. // allow others to change the shortcode attributes used
  118. $attrs = apply_filters('flexmap_shortcode_attrs', $attrs);
  119. if (!empty($attrs['src']) || !empty($attrs['center']) || !empty($attrs['address'])) {
  120. $this->loadScripts = true;
  121. if (empty($attrs['id'])) {
  122. $ID = uniqid();
  123. $divID = 'flxmap-' . $ID;
  124. }
  125. else {
  126. $ID = $attrs['id'];
  127. $divID = esc_attr($ID);
  128. }
  129. $varID = 'flxmap_' . preg_replace('/[^a-z0-9_$]/i', '_', $ID);
  130. // build the inline styles for the div
  131. $styles = array();
  132. $styles['width'] = isset($attrs['width']) ? self::getUnits($attrs['width']) : '400px';
  133. $styles['height'] = isset($attrs['height']) ? self::getUnits($attrs['height']) : '400px';
  134. $styles = apply_filters('flexmap_shortcode_styles', $styles, $attrs);
  135. if (empty($styles)) {
  136. $inlinestyles = '';
  137. }
  138. else {
  139. $inlinestyles = 'style="';
  140. foreach ($styles as $style => $value) {
  141. $inlinestyles .= $style . ':' . $value . ';';
  142. }
  143. $inlinestyles .= '"';
  144. }
  145. // test for any conditions that show directions (thus requiring the directions div)
  146. $directions = false;
  147. $divDirectionsID = $divDirectionsID = '';
  148. if (isset($attrs['directions']) && !self::isNo($attrs['directions'])) {
  149. $directions = true;
  150. if (!self::isYes($attrs['directions'])) {
  151. $divDirectionsID = self::str2js($attrs['directions']);
  152. }
  153. }
  154. if (isset($attrs['showdirections']) && self::isYes($attrs['showdirections'])) {
  155. $directions = true;
  156. }
  157. if (isset($attrs['directionsfrom'])) {
  158. $directions = true;
  159. }
  160. // build the directions div, if required
  161. $divDirections = '';
  162. if ($directions && empty($divDirectionsID)) {
  163. $divDirectionsID = "$divID-dir";
  164. $divDirections = "\n<div id='$divDirectionsID' class='flxmap-directions'></div>";
  165. }
  166. $html = <<<HTML
  167. <div id="$divID" class='flxmap-container' data-flxmap='$varID' $inlinestyles></div>$divDirections
  168. HTML;
  169. $script = " var f = new FlexibleMap();\n";
  170. if (isset($attrs['hidemaptype']) && self::isYes($attrs['hidemaptype'])) {
  171. $script .= " f.mapTypeControl = false;\n";
  172. }
  173. if (isset($attrs['hidescale']) && self::isNo($attrs['hidescale'])) {
  174. $script .= " f.scaleControl = true;\n";
  175. }
  176. if (isset($attrs['hidepanning']) && self::isNo($attrs['hidepanning'])) {
  177. $script .= " f.panControl = true;\n";
  178. }
  179. if (isset($attrs['hidezooming']) && self::isYes($attrs['hidezooming'])) {
  180. $script .= " f.zoomControl = false;\n";
  181. }
  182. if (!empty($attrs['zoomstyle'])) {
  183. $script .= " f.zoomControlStyle = \"{$this->str2js($attrs['zoomstyle'])}\";\n";
  184. }
  185. if (isset($attrs['hidestreetview']) && self::isNo($attrs['hidestreetview'])) {
  186. $script .= " f.streetViewControl = true;\n";
  187. }
  188. if (isset($attrs['showinfo']) && self::isNo($attrs['showinfo'])) {
  189. $script .= " f.markerShowInfo = false;\n";
  190. }
  191. if (isset($attrs['scrollwheel']) && self::isYes($attrs['scrollwheel'])) {
  192. $script .= " f.scrollwheel = true;\n";
  193. }
  194. if (isset($attrs['draggable']) && self::isNo($attrs['draggable'])) {
  195. $script .= " f.draggable = false;\n";
  196. }
  197. if (isset($attrs['dblclickzoom']) && self::isNo($attrs['dblclickzoom'])) {
  198. $script .= " f.dblclickZoom = false;\n";
  199. }
  200. if (isset($attrs['directions'])) {
  201. if (self::isNo($attrs['directions'])) {
  202. $script .= " f.markerDirections = false;\n";
  203. }
  204. else {
  205. $script .= " f.markerDirections = true;\n";
  206. }
  207. }
  208. if ($directions) {
  209. $script .= " f.markerDirectionsDiv = \"$divDirectionsID\";\n";
  210. }
  211. if (isset($attrs['showdirections']) && self::isYes($attrs['showdirections'])) {
  212. $script .= " f.markerDirectionsShow = true;\n";
  213. }
  214. if (isset($attrs['directionsfrom'])) {
  215. $script .= " f.markerDirectionsDefault = \"{$this->str2js($attrs['directionsfrom'])}\";\n";
  216. }
  217. if (isset($attrs['directions']) && self::isNo($attrs['directions'])) {
  218. $script .= " f.markerDirectionsInfo = false;\n";
  219. }
  220. if (isset($attrs['dirdraggable']) && self::isYes($attrs['dirdraggable'])) {
  221. $script .= " f.dirDraggable = true;\n";
  222. }
  223. if (isset($attrs['dirnomarkers']) && self::isYes($attrs['dirnomarkers'])) {
  224. $script .= " f.dirSuppressMarkers = true;\n";
  225. }
  226. if (isset($attrs['dirshowsteps']) && self::isNo($attrs['dirshowsteps'])) {
  227. $script .= " f.dirShowSteps = false;\n";
  228. }
  229. if (isset($attrs['dirshowssearch']) && self::isNo($attrs['dirshowssearch'])) {
  230. $script .= " f.dirShowSearch = false;\n";
  231. }
  232. if (isset($attrs['maptype'])) {
  233. $script .= " f.mapTypeId = \"{$this->str2js($attrs['maptype'])}\";\n";
  234. }
  235. if (isset($attrs['region'])) {
  236. $script .= " f.region = \"{$this->str2js($attrs['region'])}\";\n";
  237. }
  238. if (isset($attrs['locale'])) {
  239. $script .= " f.setlocale(\"{$this->str2js($attrs['locale'])}\");\n";
  240. $this->enqueueLocale($attrs['locale']);
  241. }
  242. else if ($this->locale != '' || $this->locale != 'en-US') {
  243. $locale = self::str2js(str_replace('_', '-', $this->locale));
  244. $script .= " f.setlocale(\"$locale\");\n";
  245. $this->enqueueLocale($locale);
  246. }
  247. // add map based on coordinates, with optional marker coordinates
  248. if (isset($attrs['center']) && self::isCoordinates($attrs['center'])) {
  249. $marker = self::str2js($attrs['center']);
  250. if (isset($attrs['marker']) && self::isCoordinates($attrs['marker']))
  251. $marker = self::str2js($attrs['marker']);
  252. if (isset($attrs['zoom']))
  253. $script .= " f.zoom = " . preg_replace('/\D/', '', $attrs['zoom']) . ";\n";
  254. if (!empty($attrs['title']))
  255. $script .= " f.markerTitle = \"{$this->unhtml($attrs['title'])}\";\n";
  256. if (!empty($attrs['description']))
  257. $script .= " f.markerDescription = \"{$this->unhtml($attrs['description'])}\";\n";
  258. if (!empty($attrs['html']))
  259. $script .= " f.markerHTML = \"{$this->str2js($attrs['html'])}\";\n";
  260. if (!empty($attrs['address']))
  261. $script .= " f.markerAddress = \"{$this->unhtml($attrs['address'])}\";\n";
  262. if (!empty($attrs['link'])) {
  263. $link = self::str2js($attrs['link']);
  264. $script .= " f.markerLink = \"$link\";\n";
  265. }
  266. if (!empty($attrs['icon'])) {
  267. $icon = self::str2js($attrs['icon']);
  268. $script .= " f.markerIcon = \"$icon\";\n";
  269. }
  270. $script .= " f.showMarker(\"$divID\", [{$attrs['center']}], [{$marker}]);\n";
  271. }
  272. // add map based on address query
  273. else if (isset($attrs['address'])) {
  274. if (isset($attrs['zoom']))
  275. $script .= " f.zoom = " . preg_replace('/\D/', '', $attrs['zoom']) . ";\n";
  276. if (!empty($attrs['title']))
  277. $script .= " f.markerTitle = \"{$this->unhtml($attrs['title'])}\";\n";
  278. if (!empty($attrs['description']))
  279. $script .= " f.markerDescription = \"{$this->unhtml($attrs['description'])}\";\n";
  280. if (!empty($attrs['html']))
  281. $script .= " f.markerHTML = \"{$this->str2js($attrs['html'])}\";\n";
  282. if (!empty($attrs['link'])) {
  283. $link = self::str2js($attrs['link']);
  284. $script .= " f.markerLink = \"$link\";\n";
  285. }
  286. if (!empty($attrs['icon'])) {
  287. $icon = self::str2js($attrs['icon']);
  288. $script .= " f.markerIcon = \"$icon\";\n";
  289. }
  290. $script .= " f.showAddress(\"$divID\", \"{$this->unhtml($attrs['address'])}\");\n";
  291. }
  292. // add map based on KML file
  293. else if (isset($attrs['src'])) {
  294. if (isset($attrs['targetfix']) && self::isNo($attrs['targetfix'])) {
  295. $script .= " f.targetFix = false;\n";
  296. }
  297. if (isset($attrs['kmlcache']) && preg_match('/^(?:none|\d+\s*minutes?|\d+\s*hours?|\d+\s*days?)$/', $attrs['kmlcache'])) {
  298. $script .= " f.kmlcache = \"{$attrs['kmlcache']}\";\n";
  299. }
  300. $kmlfile = self::str2js($attrs['src']);
  301. $script .= " f.showKML(\"$divID\", \"$kmlfile\"";
  302. if (isset($attrs['zoom']))
  303. $script .= ', ' . preg_replace('/\D/', '', $attrs['zoom']);
  304. $script .= ");\n";
  305. }
  306. // allow others to change the generated script
  307. $script = apply_filters('flexmap_shortcode_script', $script, $attrs);
  308. if ((defined('DOING_AJAX') && DOING_AJAX) || (isset($attrs['isajax']) && self::isYes($attrs['isajax']))) {
  309. // wrap it up for AJAX load, no event trigger
  310. $html .= <<<HTML
  311. <script>
  312. /* <![CDATA[ */
  313. var $varID = (function() {
  314. $script return f;
  315. })();
  316. /* ]]> */
  317. </script>
  318. HTML;
  319. }
  320. else {
  321. // wrap it up for standard page load, with "content ready" trigger
  322. $html .= <<<HTML
  323. <script>
  324. /* <![CDATA[ */
  325. (function(w, fn) {
  326. if (w.addEventListener) w.addEventListener("DOMContentLoaded", fn, false);
  327. else if (w.attachEvent) w.attachEvent("onload", fn);
  328. })(window, function() {
  329. $script window.$varID = f;
  330. });
  331. /* ]]> */
  332. </script>
  333. HTML;
  334. }
  335. }
  336. // allow others to change the generated html
  337. $html = apply_filters('flexmap_shortcode_html', $html, $attrs);
  338. // enqueue scripts
  339. wp_enqueue_script('flxmap');
  340. if ($this->locale != '' && $this->locale != 'en_US') {
  341. $this->enqueueLocale($this->locale);
  342. }
  343. return $html;
  344. }
  345. /**
  346. * get valid CSS units from string, or default to 400px if invalid
  347. * @param string $units
  348. * @return string
  349. */
  350. protected static function getUnits($units) {
  351. $units = trim($units);
  352. // check for valid CSS units
  353. if (!preg_match('/^auto$|^[+-]?[0-9]+\\.?(?:[0-9]+)?(?:px|em|ex|ch|%|in|cm|mm|pt|pc|rem|vh|vw|vmin|vmax)$/', $units)) {
  354. // not valid, so check to see if it's only digits
  355. if (preg_match('/\D/', $units)) {
  356. // not digits, so set to default
  357. $units = '400px';
  358. }
  359. else {
  360. // found only digits, so append px
  361. $units .= 'px';
  362. }
  363. }
  364. return $units;
  365. }
  366. /**
  367. * test string to see if contents equate to yes/true
  368. * @param string $text
  369. * @return boolean
  370. */
  371. public static function isYes($text) {
  372. return preg_match('/^(?:y|yes|true|1)$/i', $text);
  373. }
  374. /**
  375. * test string to see if contents equate to no/false
  376. * @param string $text
  377. * @return boolean
  378. */
  379. public static function isNo($text) {
  380. return preg_match('/^(?:n|no|false|0)$/i', $text);
  381. }
  382. /**
  383. * test string to see if contents are map coordinates (latitude,longitude)
  384. * @param string $text
  385. * @return boolean
  386. */
  387. public static function isCoordinates($text) {
  388. return preg_match('/^-?\\d+(?:\\.\\d+),-?\\d+(?:\\.\\d+)$/', $text);
  389. }
  390. /**
  391. * decode HTML-encoded text and encode for JavaScript string
  392. * @param string $text
  393. * @return string
  394. */
  395. protected static function unhtml($text) {
  396. return self::str2js(html_entity_decode($text, ENT_QUOTES, get_option('blog_charset')));
  397. }
  398. /**
  399. * encode for JavaScript string
  400. * @param string $text
  401. * @return string
  402. */
  403. protected static function str2js($text) {
  404. return addcslashes($text, "\\/\'\"&\n\r<>");
  405. }
  406. }