| @@ -1,0 +1,741 @@ | ||
| 1 | +<?php | |
| 2 | +/** | |
| 3 | + * @package VikBooking | |
| 4 | + * @subpackage com_vikbooking | |
| 5 | + * @author Alessio Gaggii - e4j - Extensionsforjoomla.com | |
| 6 | + * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved. | |
| 7 | + * @license GNU General Public License version 2 or later; see LICENSE | |
| 8 | + * @link https://vikwp.com | |
| 9 | + */ | |
| 10 | + | |
| 11 | +defined('ABSPATH') or die('No script kiddies please!'); | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * Helper class for the geocoding functions. | |
| 15 | + * | |
| 16 | + * @since 1.4.0 | |
| 17 | + */ | |
| 18 | +class VikBookingHelperGeocoding | |
| 19 | +{ | |
| 20 | + /** | |
| 21 | + * The singleton instance of the class. | |
| 22 | + * | |
| 23 | + * @var VikBookingHelperGeocoding | |
| 24 | + */ | |
| 25 | + protected static $instance = null; | |
| 26 | + | |
| 27 | + /** | |
| 28 | + * The Google Maps API Key. | |
| 29 | + * | |
| 30 | + * @var string | |
| 31 | + */ | |
| 32 | + protected $gmaps_apikey = null; | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * The current room geo-params. | |
| 36 | + * | |
| 37 | + * @var mixed | |
| 38 | + */ | |
| 39 | + protected $room_geoparams = null; | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * The current room params. | |
| 43 | + * | |
| 44 | + * @var mixed | |
| 45 | + */ | |
| 46 | + protected $room_params = null; | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * Class constructor is protected. | |
| 50 | + * | |
| 51 | + * @see getInstance() | |
| 52 | + */ | |
| 53 | + protected function __construct() | |
| 54 | + { | |
| 55 | + // load the Google Maps API Key from the configuration settings | |
| 56 | + $this->setGoogleMapsKey(VikBooking::getGoogleMapsKey()); | |
| 57 | + } | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * Returns the global object, either | |
| 61 | + * a new instance or the existing instance | |
| 62 | + * if the class was already instantiated. | |
| 63 | + * | |
| 64 | + * @return self A new instance of the class. | |
| 65 | + */ | |
| 66 | + public static function getInstance() | |
| 67 | + { | |
| 68 | + if (is_null(static::$instance)) { | |
| 69 | + static::$instance = new static(); | |
| 70 | + } | |
| 71 | + | |
| 72 | + return static::$instance; | |
| 73 | + } | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * Sets the Google Maps API Key. | |
| 77 | + * | |
| 78 | + * @param string the Google Maps API Key to set | |
| 79 | + * | |
| 80 | + * @return self | |
| 81 | + */ | |
| 82 | + public function setGoogleMapsKey($apikey = null) | |
| 83 | + { | |
| 84 | + $this->gmaps_apikey = $apikey; | |
| 85 | + | |
| 86 | + return $this; | |
| 87 | + } | |
| 88 | + | |
| 89 | + /** | |
| 90 | + * Gets the current Google Maps API Key. | |
| 91 | + * | |
| 92 | + * @return mixed string or false if empty. | |
| 93 | + */ | |
| 94 | + public function getGoogleMapsKey() | |
| 95 | + { | |
| 96 | + if (empty($this->gmaps_apikey)) { | |
| 97 | + return false; | |
| 98 | + } | |
| 99 | + | |
| 100 | + return $this->gmaps_apikey; | |
| 101 | + } | |
| 102 | + | |
| 103 | + /** | |
| 104 | + * Checks whether the Google Maps can be used. | |
| 105 | + * | |
| 106 | + * @return bool true or false | |
| 107 | + */ | |
| 108 | + public function isSupported() | |
| 109 | + { | |
| 110 | + return (!empty($this->gmaps_apikey)); | |
| 111 | + } | |
| 112 | + | |
| 113 | + /** | |
| 114 | + * Loads the necessary assets to the document for Google Maps. | |
| 115 | + * | |
| 116 | + * @param mixed string or array values values to append to the URL. | |
| 117 | + * | |
| 118 | + * @return self | |
| 119 | + * | |
| 120 | + * @since 1.18.3 (J) - 1.8.3 (WP) loaded file gmaps-utils.js. | |
| 121 | + */ | |
| 122 | + public function loadAssets($params = null) | |
| 123 | + { | |
| 124 | + static $loaded = null; | |
| 125 | + | |
| 126 | + if (empty($this->gmaps_apikey) || $loaded) { | |
| 127 | + return $this; | |
| 128 | + } | |
| 129 | + | |
| 130 | + // turn flag on | |
| 131 | + $loaded = true; | |
| 132 | + | |
| 133 | + // values like &callback=initMap could be passed as argument | |
| 134 | + $qstring = ''; | |
| 135 | + | |
| 136 | + if (!empty($params)) { | |
| 137 | + if (is_string($params)) { | |
| 138 | + $qstring = (substr($params, 0, 1) != '&' ? '&' : '') . $params; | |
| 139 | + } elseif (!is_scalar($params)) { | |
| 140 | + $qstring = '&' . http_build_query($params); | |
| 141 | + } | |
| 142 | + } | |
| 143 | + | |
| 144 | + $document = JFactory::getDocument(); | |
| 145 | + | |
| 146 | + // load the Google Maps Utils file within VikBooking | |
| 147 | + $document->addScript(VBO_SITE_URI . 'resources/gmaps-utils.js', ['version' => VIKBOOKING_SOFTWARE_VERSION]); | |
| 148 | + | |
| 149 | + // load Google Maps API JS | |
| 150 | + $document->addScript('https://maps.googleapis.com/maps/api/js?key=' . $this->gmaps_apikey . $qstring); | |
| 151 | + | |
| 152 | + return $this; | |
| 153 | + } | |
| 154 | + | |
| 155 | + /** | |
| 156 | + * Gets the room parameters (one or all) related to the geocoding. | |
| 157 | + * Class variables are using to cache parameters into the buffer. | |
| 158 | + * | |
| 159 | + * @param mixed $rparams string to be decoded or array/object params. | |
| 160 | + * @param string $key the optional param key to get. | |
| 161 | + * @param mixed $def the default room param value to return. | |
| 162 | + * | |
| 163 | + * @return mixed object with all params or empty object, requested param otherwise. | |
| 164 | + */ | |
| 165 | + public function getRoomGeoParams($rparams, $key = null, $def = null) | |
| 166 | + { | |
| 167 | + $geoparams = new stdClass; | |
| 168 | + | |
| 169 | + if (empty($rparams)) { | |
| 170 | + return !empty($key) ? $def : $geoparams; | |
| 171 | + } | |
| 172 | + | |
| 173 | + if ($this->room_geoparams === null || $this->room_params != $rparams || $key === null) { | |
| 174 | + if (is_string($rparams)) { | |
| 175 | + $rparams_obj = json_decode($rparams); | |
| 176 | + if (!is_object($rparams_obj) || !isset($rparams_obj->geo)) { | |
| 177 | + return !empty($key) ? $def : $geoparams; | |
| 178 | + } | |
| 179 | + $geoparams = $rparams_obj->geo; | |
| 180 | + } elseif (is_array($rparams)) { | |
| 181 | + // rooms parameters already decoded, convert it to object | |
| 182 | + $geoparams = json_decode(json_encode($rparams)); | |
| 183 | + } elseif (is_object($rparams)) { | |
| 184 | + // rooms parameters already decoded | |
| 185 | + $geoparams = $rparams; | |
| 186 | + } | |
| 187 | + | |
| 188 | + if (is_object($geoparams) && isset($geoparams->geo)) { | |
| 189 | + $geoparams = $geoparams->geo; | |
| 190 | + } | |
| 191 | + | |
| 192 | + // update global vars | |
| 193 | + $this->room_params = $rparams; | |
| 194 | + $this->room_geoparams = $geoparams; | |
| 195 | + } | |
| 196 | + | |
| 197 | + if (($key == 'units_pos' || $key === null) && is_object($this->room_geoparams) && isset($this->room_geoparams->units_pos)) { | |
| 198 | + $units_pos = $this->room_geoparams->units_pos; | |
| 199 | + // make sure to adjust some properties of type float (number) so that they are not strings | |
| 200 | + foreach ($units_pos as $k => $unit) { | |
| 201 | + if (isset($unit->lat)) { | |
| 202 | + $units_pos->{$k}->lat = (float)$unit->lat; | |
| 203 | + } | |
| 204 | + if (isset($unit->lng)) { | |
| 205 | + $units_pos->{$k}->lng = (float)$unit->lng; | |
| 206 | + } | |
| 207 | + if (isset($unit->icon)) { | |
| 208 | + foreach ($unit->icon as $icon_prop => $icon_val) { | |
| 209 | + if ($icon_prop == 'fillOpacity') { | |
| 210 | + $units_pos->{$k}->icon->{$icon_prop} = (float)$icon_val; | |
| 211 | + } | |
| 212 | + if ($icon_prop == 'scale') { | |
| 213 | + $units_pos->{$k}->icon->{$icon_prop} = (float)$icon_val; | |
| 214 | + } | |
| 215 | + if ($icon_prop == 'strokeWeight') { | |
| 216 | + $units_pos->{$k}->icon->{$icon_prop} = (float)$icon_val; | |
| 217 | + } | |
| 218 | + if ($icon_prop == 'anchor' && isset($icon_val->x) && isset($icon_val->y)) { | |
| 219 | + // anchor point object is composed of coordinates with numbers | |
| 220 | + $units_pos->{$k}->icon->{$icon_prop}->x = (float)$icon_val->x; | |
| 221 | + $units_pos->{$k}->icon->{$icon_prop}->y = (float)$icon_val->y; | |
| 222 | + } | |
| 223 | + if (($icon_prop == 'size' || $icon_prop == 'scaledSize') && isset($icon_val->width) && isset($icon_val->height)) { | |
| 224 | + // size and scaledSize object is composed of size width and height numbers | |
| 225 | + $units_pos->{$k}->icon->{$icon_prop}->width = (int)$icon_val->width; | |
| 226 | + $units_pos->{$k}->icon->{$icon_prop}->height = (int)$icon_val->height; | |
| 227 | + } | |
| 228 | + } | |
| 229 | + } | |
| 230 | + } | |
| 231 | + $this->room_geoparams->units_pos = $units_pos; | |
| 232 | + } | |
| 233 | + | |
| 234 | + if (!empty($key)) { | |
| 235 | + return is_object($this->room_geoparams) && isset($this->room_geoparams->{$key}) ? $this->room_geoparams->{$key} : $def; | |
| 236 | + } | |
| 237 | + | |
| 238 | + return $geoparams; | |
| 239 | + } | |
| 240 | + | |
| 241 | + /** | |
| 242 | + * Gets the list of default marker symbols (SVG icons) for Google Maps. | |
| 243 | + * | |
| 244 | + * @return array list of default marker symbols. | |
| 245 | + */ | |
| 246 | + public function getDefaultMarkerSymbols() | |
| 247 | + { | |
| 248 | + $symbols = array(); | |
| 249 | + $group = 'default'; | |
| 250 | + $color = '#000000'; | |
| 251 | + $opacity = 1; | |
| 252 | + | |
| 253 | + $symbol = new stdClass; | |
| 254 | + $symbol->id = 'hotel'; | |
| 255 | + $symbol->name = 'Hotel'; | |
| 256 | + $symbol->group = $group; | |
| 257 | + $symbol->fill = $color; | |
| 258 | + $symbol->opacity = $opacity; | |
| 259 | + $symbol->width = 48.4; | |
| 260 | + $symbol->height = 43; | |
| 261 | + $symbol->path = 'M47,5.4c0.7,0,1.3-0.6,1.3-1.3V1.3C48.4,0.6,47.8,0,47,0H1.3C0.6,0,0,0.6,0,1.3V4c0,0.7,0.6,1.3,1.3,1.3h1.3v32.2H1.3 C0.6,37.6,0,38.2,0,39v2.7C0,42.4,0.6,43,1.3,43h20.2v-6.7c0-0.7,0.6-1.3,1.3-1.3h2.7c0.7,0,1.3,0.6,1.3,1.3V43H47 c0.7,0,1.3-0.6,1.3-1.3V39c0-0.7-0.6-1.3-1.3-1.3h-1.3V5.4H47z M21.5,9.1c0-0.5,0.5-1.1,1.1-1.1h3.2c0.5,0,1.1,0.5,1.1,1.1v3.2 c0,0.5-0.5,1.1-1.1,1.1h-3.2c-0.5,0-1.1-0.5-1.1-1.1L21.5,9.1L21.5,9.1z M21.5,17.2c0-0.5,0.5-1.1,1.1-1.1h3.2 c0.5,0,1.1,0.5,1.1,1.1v3.2c0,0.5-0.5,1.1-1.1,1.1h-3.2c-0.5,0-1.1-0.5-1.1-1.1L21.5,17.2L21.5,17.2z M10.8,9.1 c0-0.5,0.5-1.1,1.1-1.1h3.2c0.5,0,1.1,0.5,1.1,1.1v3.2c0,0.5-0.5,1.1-1.1,1.1h-3.2c-0.5,0-1.1-0.5-1.1-1.1L10.8,9.1L10.8,9.1z M15.1,21.5h-3.2c-0.5,0-1.1-0.5-1.1-1.1v-3.2c0-0.5,0.5-1.1,1.1-1.1H15c0.5,0,1.1,0.5,1.1,1.1v3.2C16.1,21,15.6,21.5,15.1,21.5 L15.1,21.5z M16.1,32.2c0-4.5,3.6-8.1,8.1-8.1s8.1,3.6,8.1,8.1H16.1z M37.6,20.4c0,0.5-0.5,1.1-1.1,1.1h-3.2c-0.5,0-1.1-0.5-1.1-1.1 v-3.2c0-0.5,0.5-1.1,1.1-1.1h3.2c0.5,0,1.1,0.5,1.1,1.1V20.4L37.6,20.4z M37.6,12.4c0,0.5-0.5,1.1-1.1,1.1h-3.2 c-0.5,0-1.1-0.5-1.1-1.1V9.1c0-0.5,0.5-1.1,1.1-1.1h3.2c0.5,0,1.1,0.5,1.1,1.1V12.4z'; | |
| 262 | + array_push($symbols, $symbol); | |
| 263 | + | |
| 264 | + $symbol = new stdClass; | |
| 265 | + $symbol->id = 'home'; | |
| 266 | + $symbol->name = 'Home'; | |
| 267 | + $symbol->group = $group; | |
| 268 | + $symbol->fill = $color; | |
| 269 | + $symbol->opacity = $opacity; | |
| 270 | + $symbol->width = 56.8; | |
| 271 | + $symbol->height = 43; | |
| 272 | + $symbol->path = 'M27.7,11.2L10,25.8v15.7c0,0.8,0.7,1.5,1.5,1.5l10.8,0c0.8,0,1.5-0.7,1.5-1.5v-9.2c0-0.8,0.7-1.5,1.5-1.5h6.1 c0.8,0,1.5,0.7,1.5,1.5v9.2c0,0.8,0.7,1.5,1.5,1.5c0,0,0,0,0,0l10.8,0c0.8,0,1.5-0.7,1.5-1.5V25.7L29.1,11.2 C28.7,10.8,28.1,10.8,27.7,11.2L27.7,11.2z M55.6,21.1l-8-6.6V1.2c0-0.6-0.5-1.2-1.2-1.2h-5.4c-0.6,0-1.2,0.5-1.2,1.2v7l-8.6-7.1 c-1.7-1.4-4.2-1.4-5.9,0l-24.3,20c-0.5,0.4-0.6,1.1-0.2,1.6c0,0,0,0,0,0l2.4,3c0.4,0.5,1.1,0.6,1.6,0.2c0,0,0,0,0,0L27.7,7.2 c0.4-0.3,1-0.3,1.5,0l22.6,18.6c0.5,0.4,1.2,0.3,1.6-0.2c0,0,0,0,0,0l2.4-3C56.2,22.2,56.1,21.5,55.6,21.1 C55.6,21.1,55.6,21.1,55.6,21.1L55.6,21.1z'; | |
| 273 | + array_push($symbols, $symbol); | |
| 274 | + | |
| 275 | + $symbol = new stdClass; | |
| 276 | + $symbol->id = 'city'; | |
| 277 | + $symbol->name = 'City'; | |
| 278 | + $symbol->group = $group; | |
| 279 | + $symbol->fill = $color; | |
| 280 | + $symbol->opacity = $opacity; | |
| 281 | + $symbol->width = 53.8; | |
| 282 | + $symbol->height = 43; | |
| 283 | + $symbol->path = 'M51.7,16.1H40.3V2c0-1.1-0.9-2-2-2H26.2c-1.1,0-2,0.9-2,2v6h-5.4V1.3c0-0.7-0.6-1.3-1.3-1.3h-1.3c-0.7,0-1.3,0.6-1.3,1.3 v6.7H9.4V1.3C9.4,0.6,8.8,0,8.1,0H6.7C6,0,5.4,0.6,5.4,1.3v6.7H2c-1.1,0-2,0.9-2,2v30.2C0,41.8,1.2,43,2.7,43h48.4 c1.5,0,2.7-1.2,2.7-2.7V18.1C53.8,17,52.8,16.1,51.7,16.1z M10.8,33.9c0,0.6-0.5,1-1,1H6.4c-0.6,0-1-0.5-1-1v-3.4c0-0.6,0.5-1,1-1 h3.4c0.6,0,1,0.5,1,1V33.9z M10.8,25.9c0,0.6-0.5,1-1,1H6.4c-0.6,0-1-0.5-1-1v-3.4c0-0.6,0.5-1,1-1h3.4c0.6,0,1,0.5,1,1V25.9z M10.8,17.8c0,0.6-0.5,1-1,1H6.4c-0.6,0-1-0.5-1-1v-3.4c0-0.6,0.5-1,1-1h3.4c0.6,0,1,0.5,1,1V17.8z M21.5,33.9c0,0.6-0.5,1-1,1h-3.4 c-0.6,0-1-0.5-1-1v-3.4c0-0.6,0.5-1,1-1h3.4c0.6,0,1,0.5,1,1V33.9z M21.5,25.9c0,0.6-0.5,1-1,1h-3.4c-0.6,0-1-0.5-1-1v-3.4 c0-0.6,0.5-1,1-1h3.4c0.6,0,1,0.5,1,1V25.9z M21.5,17.8c0,0.6-0.5,1-1,1h-3.4c-0.6,0-1-0.5-1-1v-3.4c0-0.6,0.5-1,1-1h3.4 c0.6,0,1,0.5,1,1V17.8z M34.9,25.9c0,0.6-0.5,1-1,1h-3.4c-0.6,0-1-0.5-1-1v-3.4c0-0.6,0.5-1,1-1h3.4c0.6,0,1,0.5,1,1V25.9z M34.9,17.8c0,0.6-0.5,1-1,1h-3.4c-0.6,0-1-0.5-1-1v-3.4c0-0.6,0.5-1,1-1h3.4c0.6,0,1,0.5,1,1V17.8z M34.9,9.7c0,0.6-0.5,1-1,1h-3.4 c-0.6,0-1-0.5-1-1V6.4c0-0.6,0.5-1,1-1h3.4c0.6,0,1,0.5,1,1V9.7z M48.4,33.9c0,0.6-0.5,1-1,1H44c-0.6,0-1-0.5-1-1v-3.4 c0-0.6,0.5-1,1-1h3.4c0.6,0,1,0.5,1,1V33.9z M48.4,25.9c0,0.6-0.5,1-1,1H44c-0.6,0-1-0.5-1-1v-3.4c0-0.6,0.5-1,1-1h3.4 c0.6,0,1,0.5,1,1V25.9z'; | |
| 284 | + array_push($symbols, $symbol); | |
| 285 | + | |
| 286 | + $symbol = new stdClass; | |
| 287 | + $symbol->id = 'campground'; | |
| 288 | + $symbol->name = 'Campground'; | |
| 289 | + $symbol->group = $group; | |
| 290 | + $symbol->fill = $color; | |
| 291 | + $symbol->opacity = $opacity; | |
| 292 | + $symbol->width = 53.7; | |
| 293 | + $symbol->height = 43; | |
| 294 | + $symbol->path = 'M52.4,37.6h-2.1L30.2,9.9l4.5-6.2c0.4-0.6,0.3-1.4-0.3-1.9l-2.2-1.6c-0.6-0.4-1.4-0.3-1.9,0.3l-3.5,4.8l-3.5-4.8 C23,0,22.1-0.2,21.5,0.3l-2.2,1.6c-0.6,0.4-0.7,1.3-0.3,1.9l4.5,6.2L3.4,37.6H1.3C0.6,37.6,0,38.2,0,39v2.7C0,42.4,0.6,43,1.3,43 h51.1c0.7,0,1.3-0.6,1.3-1.3V39C53.7,38.2,53.1,37.6,52.4,37.6z M26.9,24.2l9.8,13.4H17.1L26.9,24.2z'; | |
| 295 | + array_push($symbols, $symbol); | |
| 296 | + | |
| 297 | + $symbol = new stdClass; | |
| 298 | + $symbol->id = 'trailer'; | |
| 299 | + $symbol->name = 'Trailer'; | |
| 300 | + $symbol->group = $group; | |
| 301 | + $symbol->fill = $color; | |
| 302 | + $symbol->opacity = $opacity; | |
| 303 | + $symbol->width = 66.2; | |
| 304 | + $symbol->height = 43; | |
| 305 | + $symbol->path = 'M64.5,26.5h-8.3V1.7c0-0.9-0.7-1.7-1.7-1.7H1.7C0.7,0,0,0.7,0,1.7v29.8c0,0.9,0.7,1.7,1.7,1.7h5.1c0.8-5.6,5.6-9.9,11.4-9.9 s10.6,4.3,11.4,9.9h34.9c0.9,0,1.7-0.7,1.7-1.7v-3.3C66.2,27.2,65.4,26.5,64.5,26.5z M9.9,18.6c-1.2,0.6-2.3,1.3-3.3,2.1V7.4 C6.6,7,7,6.6,7.4,6.6h1.7c0.5,0,0.8,0.4,0.8,0.8V18.6z M19.8,16.7c-0.5-0.1-1.1-0.1-1.7-0.1c-0.6,0-1.1,0.1-1.7,0.1V7.4 c0-0.5,0.4-0.8,0.8-0.8H19c0.5,0,0.8,0.4,0.8,0.8V16.7z M29.8,20.7c-1-0.8-2.1-1.5-3.3-2.1V7.4c0-0.5,0.4-0.8,0.8-0.8h1.7 c0.5,0,0.8,0.4,0.8,0.8V20.7z M39.7,26.5h-3.3v-19c0-0.5,0.4-0.8,0.8-0.8h1.7c0.5,0,0.8,0.4,0.8,0.8V26.5z M49.6,26.5h-3.3v-19 c0-0.5,0.4-0.8,0.8-0.8h1.7c0.5,0,0.8,0.4,0.8,0.8V26.5z M18.2,26.5c-4.6,0-8.3,3.7-8.3,8.3s3.7,8.3,8.3,8.3s8.3-3.7,8.3-8.3 S22.8,26.5,18.2,26.5z M18.2,38c-1.8,0-3.3-1.5-3.3-3.3s1.5-3.3,3.3-3.3s3.3,1.5,3.3,3.3S20,38,18.2,38z'; | |
| 306 | + array_push($symbols, $symbol); | |
| 307 | + | |
| 308 | + return $symbols; | |
| 309 | + } | |
| 310 | + | |
| 311 | + /** | |
| 312 | + * Gets the list of marker symbols for Google Maps. | |
| 313 | + * | |
| 314 | + * @param string $group optionally filter the symbols by group | |
| 315 | + * | |
| 316 | + * @return array list of marker symbols. | |
| 317 | + */ | |
| 318 | + public function getMarkerSymbols($group = null) | |
| 319 | + { | |
| 320 | + $dbo = JFactory::getDbo(); | |
| 321 | + $symbols = array(); | |
| 322 | + | |
| 323 | + $q = "SELECT `param`, `setting` FROM `#__vikbooking_config` WHERE `param` LIKE 'marker_symbols_%' ORDER BY `param` ASC;"; | |
| 324 | + $dbo->setQuery($q); | |
| 325 | + $dbo->execute(); | |
| 326 | + if ($dbo->getNumRows()) { | |
| 327 | + $all_symbols = $dbo->loadAssocList(); | |
| 328 | + foreach ($all_symbols as $symbols_data) { | |
| 329 | + $list = json_decode($symbols_data['setting']); | |
| 330 | + if (!is_array($list) || !count($list)) { | |
| 331 | + continue; | |
| 332 | + } | |
| 333 | + $symbols = array_merge($symbols, $list); | |
| 334 | + } | |
| 335 | + } else { | |
| 336 | + $default_symbols = $this->getDefaultMarkerSymbols(); | |
| 337 | + $q = "INSERT INTO `#__vikbooking_config` (`param`,`setting`) VALUES ('marker_symbols_default', " . $dbo->quote(json_encode($default_symbols)) . ");"; | |
| 338 | + $dbo->setQuery($q); | |
| 339 | + $dbo->execute(); | |
| 340 | + | |
| 341 | + return $default_symbols; | |
| 342 | + } | |
| 343 | + | |
| 344 | + $symbols = count($symbols) ? $symbols : $this->getDefaultMarkerSymbols(); | |
| 345 | + | |
| 346 | + if (!empty($group)) { | |
| 347 | + // filter symbol objects by group | |
| 348 | + $group = strtolower($group); | |
| 349 | + foreach ($symbols as $k => $symbol) { | |
| 350 | + if (!isset($symbol->group)) { | |
| 351 | + // filtering is impossible | |
| 352 | + continue; | |
| 353 | + } | |
| 354 | + if ($symbol->group != $group) { | |
| 355 | + unset($symbols[$k]); | |
| 356 | + } | |
| 357 | + } | |
| 358 | + // reset keys | |
| 359 | + $symbols = array_values($symbols); | |
| 360 | + } | |
| 361 | + | |
| 362 | + return $symbols; | |
| 363 | + } | |
| 364 | + | |
| 365 | + /** | |
| 366 | + * Gets one marker symbol for Google Maps. | |
| 367 | + * | |
| 368 | + * @param string $id the symbol identifier | |
| 369 | + * @param string $group optionally filter the symbols by group | |
| 370 | + * | |
| 371 | + * @return mixed marker symbol object or null. | |
| 372 | + */ | |
| 373 | + public function getMarkerSymbol($id, $group = null) | |
| 374 | + { | |
| 375 | + if (empty($id)) { | |
| 376 | + return null; | |
| 377 | + } | |
| 378 | + | |
| 379 | + $symbols = $this->getMarkerSymbols($group); | |
| 380 | + foreach ($symbols as $symbol) { | |
| 381 | + if (isset($symbol->id) && $symbol->id == $id) { | |
| 382 | + // symbol found | |
| 383 | + return $symbol; | |
| 384 | + } | |
| 385 | + } | |
| 386 | + | |
| 387 | + // symbol not found | |
| 388 | + return null; | |
| 389 | + } | |
| 390 | + | |
| 391 | + /** | |
| 392 | + * AJAX method called by the main controller when adding | |
| 393 | + * or updating a new or existing SVG symbol icon. | |
| 394 | + * | |
| 395 | + * @return mixed | |
| 396 | + * | |
| 397 | + * @throws Exception | |
| 398 | + */ | |
| 399 | + public function storeSvgSymbol() | |
| 400 | + { | |
| 401 | + $symbol = VikRequest::getVar('symbol', array(), 'request', 'array'); | |
| 402 | + if (!is_array($symbol) || empty($symbol['id'])) { | |
| 403 | + throw new Exception("Symbol ID not found", 404); | |
| 404 | + } | |
| 405 | + | |
| 406 | + if (empty($symbol['name'])) { | |
| 407 | + throw new Exception("Symbol name is empty", 500); | |
| 408 | + } | |
| 409 | + | |
| 410 | + if (empty($symbol['path'])) { | |
| 411 | + throw new Exception("Symbol path is empty", 500); | |
| 412 | + } | |
| 413 | + | |
| 414 | + // sanitize values | |
| 415 | + $symbol['group'] = !empty($symbol['group']) ? strtolower($symbol['group']) : 'default'; | |
| 416 | + if (isset($symbol['opacity'])) { | |
| 417 | + // this must be a float, not a string | |
| 418 | + $symbol['opacity'] = floatval($symbol['opacity']); | |
| 419 | + } | |
| 420 | + | |
| 421 | + $current_symbol = $this->getMarkerSymbol($symbol['id']); | |
| 422 | + $addnew = false; | |
| 423 | + if (is_object($current_symbol)) { | |
| 424 | + // force symbol group because ID exists | |
| 425 | + $symbol['group'] = $current_symbol->group; | |
| 426 | + // update existing marker symbol | |
| 427 | + foreach ($current_symbol as $prop => $val) { | |
| 428 | + if (isset($symbol[$prop])) { | |
| 429 | + // overwrite existing property taken from the new icon | |
| 430 | + $current_symbol->{$prop} = $symbol[$prop]; | |
| 431 | + } | |
| 432 | + } | |
| 433 | + } else { | |
| 434 | + // create new marker symbol | |
| 435 | + $addnew = true; | |
| 436 | + $current_symbol = (object)$symbol; | |
| 437 | + } | |
| 438 | + | |
| 439 | + $dbo = JFactory::getDbo(); | |
| 440 | + | |
| 441 | + $group_symbols = array(); | |
| 442 | + $update = false; | |
| 443 | + $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`=" . $dbo->quote('marker_symbols_' . $symbol['group']) . ";"; | |
| 444 | + $dbo->setQuery($q); | |
| 445 | + $dbo->execute(); | |
| 446 | + if ($dbo->getNumRows()) { | |
| 447 | + $update = true; | |
| 448 | + $group_symbols = json_decode($dbo->loadResult()); | |
| 449 | + $group_symbols = !is_array($group_symbols) ? array() : $group_symbols; | |
| 450 | + } | |
| 451 | + | |
| 452 | + if ($addnew) { | |
| 453 | + // push new symbol | |
| 454 | + array_push($group_symbols, $current_symbol); | |
| 455 | + } else { | |
| 456 | + // find current symbol | |
| 457 | + $found = false; | |
| 458 | + foreach ($group_symbols as $k => $s) { | |
| 459 | + if ($s->id == $symbol['id']) { | |
| 460 | + // replace existing symbol | |
| 461 | + $found = true; | |
| 462 | + $group_symbols[$k] = $current_symbol; | |
| 463 | + break; | |
| 464 | + } | |
| 465 | + } | |
| 466 | + if (!$found) { | |
| 467 | + // push new symbol as it was not found | |
| 468 | + array_push($group_symbols, $current_symbol); | |
| 469 | + } | |
| 470 | + } | |
| 471 | + | |
| 472 | + // update values in db | |
| 473 | + if ($update) { | |
| 474 | + $q = "UPDATE `#__vikbooking_config` SET `setting`=" . $dbo->quote(json_encode($group_symbols)) . " WHERE `param`=" . $dbo->quote('marker_symbols_' . $symbol['group']) . ";"; | |
| 475 | + } else { | |
| 476 | + $q = "INSERT INTO `#__vikbooking_config` (`param`,`setting`) VALUES (" . $dbo->quote('marker_symbols_' . $symbol['group']) . ", " . $dbo->quote(json_encode($group_symbols)) . ");"; | |
| 477 | + } | |
| 478 | + $dbo->setQuery($q); | |
| 479 | + $dbo->execute(); | |
| 480 | + | |
| 481 | + // return the new symbol object just stored | |
| 482 | + return $current_symbol; | |
| 483 | + } | |
| 484 | + | |
| 485 | + /** | |
| 486 | + * AJAX method called by the main controller when needing | |
| 487 | + * to delete an existing SVG symbol icon. | |
| 488 | + * | |
| 489 | + * @return mixed | |
| 490 | + * | |
| 491 | + * @throws Exception | |
| 492 | + */ | |
| 493 | + public function deleteSvgSymbol() | |
| 494 | + { | |
| 495 | + $symbol_id = VikRequest::getString('symbol_id', '', 'request'); | |
| 496 | + if (empty($symbol_id)) { | |
| 497 | + throw new Exception("Symbol ID is empty", 404); | |
| 498 | + } | |
| 499 | + | |
| 500 | + $current_symbol = $this->getMarkerSymbol($symbol_id); | |
| 501 | + if (!is_object($current_symbol)) { | |
| 502 | + throw new Exception("Symbol ID not found", 404); | |
| 503 | + } | |
| 504 | + | |
| 505 | + $dbo = JFactory::getDbo(); | |
| 506 | + $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`=" . $dbo->quote('marker_symbols_' . $current_symbol->group) . ";"; | |
| 507 | + $dbo->setQuery($q); | |
| 508 | + $dbo->execute(); | |
| 509 | + if (!$dbo->getNumRows()) { | |
| 510 | + throw new Exception("Symbol Group not found", 404); | |
| 511 | + } | |
| 512 | + $records = json_decode($dbo->loadResult()); | |
| 513 | + if (!is_array($records) || !count($records)) { | |
| 514 | + throw new Exception("Symbol Group has got no symbols", 404); | |
| 515 | + } | |
| 516 | + | |
| 517 | + $found = false; | |
| 518 | + foreach ($records as $k => $v) { | |
| 519 | + if ($v->id == $symbol_id) { | |
| 520 | + $found = true; | |
| 521 | + unset($records[$k]); | |
| 522 | + break; | |
| 523 | + } | |
| 524 | + } | |
| 525 | + | |
| 526 | + if (!$found) { | |
| 527 | + throw new Exception("Symbol ID not found in all symbols of this group", 404); | |
| 528 | + } | |
| 529 | + | |
| 530 | + // reset keys | |
| 531 | + $records = array_values($records); | |
| 532 | + | |
| 533 | + // update db | |
| 534 | + $q = "UPDATE `#__vikbooking_config` SET `setting`=" . $dbo->quote(json_encode($records)) . " WHERE `param`=" . $dbo->quote('marker_symbols_' . $current_symbol->group) . ";"; | |
| 535 | + $dbo->setQuery($q); | |
| 536 | + $dbo->execute(); | |
| 537 | + | |
| 538 | + return $symbol_id; | |
| 539 | + } | |
| 540 | + | |
| 541 | + /** | |
| 542 | + * AJAX method called by the main controller when starting to work | |
| 543 | + * on the geo coding information for one specific room. | |
| 544 | + * | |
| 545 | + * @return int a simple result integer code identifier. | |
| 546 | + * | |
| 547 | + * @throws Exception | |
| 548 | + */ | |
| 549 | + public function initRoomGeoTransient() | |
| 550 | + { | |
| 551 | + $dbo = JFactory::getDbo(); | |
| 552 | + $room_id = VikRequest::getInt('room_id', 0, 'request'); | |
| 553 | + | |
| 554 | + $param = "geocoding_transient_room_" . $room_id; | |
| 555 | + $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`=" . $dbo->quote($param) . ";"; | |
| 556 | + $dbo->setQuery($q); | |
| 557 | + $dbo->execute(); | |
| 558 | + if ($dbo->getNumRows()) { | |
| 559 | + // make the temporary record empty | |
| 560 | + $q = "UPDATE `#__vikbooking_config` SET `setting`='' WHERE `param`=" . $dbo->quote($param) . ";"; | |
| 561 | + $dbo->setQuery($q); | |
| 562 | + $dbo->execute(); | |
| 563 | + | |
| 564 | + return 2; | |
| 565 | + } | |
| 566 | + | |
| 567 | + return 1; | |
| 568 | + } | |
| 569 | + | |
| 570 | + /** | |
| 571 | + * AJAX method called by the main controller when updating | |
| 572 | + * the geo coding information for one specific room. | |
| 573 | + * | |
| 574 | + * @return object the geo params stored. | |
| 575 | + * | |
| 576 | + * @throws Exception | |
| 577 | + */ | |
| 578 | + public function updateRoomGeoTransient() | |
| 579 | + { | |
| 580 | + $dbo = JFactory::getDbo(); | |
| 581 | + | |
| 582 | + $room_id = VikRequest::getInt('room_id', 0, 'request'); | |
| 583 | + $geo_enabled = VikRequest::getInt('geo_enabled', 0, 'request'); | |
| 584 | + $geo_address = VikRequest::getString('geo_address', '', 'request'); | |
| 585 | + $geo_latitude = VikRequest::getFloat('geo_latitude', 0, 'request'); | |
| 586 | + $geo_longitude = VikRequest::getFloat('geo_longitude', 0, 'request'); | |
| 587 | + $geo_zoom = VikRequest::getInt('geo_zoom', 1, 'request'); | |
| 588 | + $geo_mtype = VikRequest::getString('geo_mtype', '', 'request'); | |
| 589 | + $geo_height = VikRequest::getInt('geo_height', 100, 'request'); | |
| 590 | + $geo_markers_multi = VikRequest::getInt('geo_markers_multi', 0, 'request'); | |
| 591 | + $geo_marker_lat = VikRequest::getFloat('geo_marker_lat', 0, 'request'); | |
| 592 | + $geo_marker_lng = VikRequest::getFloat('geo_marker_lng', 0, 'request'); | |
| 593 | + $geo_marker_hide = VikRequest::getInt('geo_marker_hide', 0, 'request'); | |
| 594 | + $geo_units_pos = VikRequest::getVar('geo_units_pos', array(), 'request', 'array'); | |
| 595 | + $geo_goverlay = VikRequest::getInt('geo_goverlay', 0, 'request'); | |
| 596 | + $geo_overlay_img = VikRequest::getString('geo_overlay_img', '', 'request'); | |
| 597 | + $geo_overlay_south = VikRequest::getFloat('geo_overlay_south', 0, 'request'); | |
| 598 | + $geo_overlay_west = VikRequest::getFloat('geo_overlay_west', 0, 'request'); | |
| 599 | + $geo_overlay_north = VikRequest::getFloat('geo_overlay_north', 0, 'request'); | |
| 600 | + $geo_overlay_east = VikRequest::getFloat('geo_overlay_east', 0, 'request'); | |
| 601 | + | |
| 602 | + // prepare geo params object | |
| 603 | + $geo_params = new stdClass; | |
| 604 | + /** | |
| 605 | + * Property "enabled" must ALWAYS be the first one | |
| 606 | + * | |
| 607 | + * @see getImportableConfigRooms() | |
| 608 | + */ | |
| 609 | + $geo_params->enabled = $geo_enabled; | |
| 610 | + // | |
| 611 | + $geo_params->address = $geo_address; | |
| 612 | + $geo_params->latitude = $geo_latitude; | |
| 613 | + $geo_params->longitude = $geo_longitude; | |
| 614 | + $geo_params->zoom = $geo_zoom; | |
| 615 | + $geo_params->mtype = $geo_mtype; | |
| 616 | + $geo_params->height = $geo_height; | |
| 617 | + $geo_params->markers_multi = $geo_markers_multi; | |
| 618 | + $geo_params->marker_lat = $geo_marker_lat; | |
| 619 | + $geo_params->marker_lng = $geo_marker_lng; | |
| 620 | + $geo_params->marker_hide = $geo_marker_hide; | |
| 621 | + $geo_params->units_pos = $geo_units_pos; | |
| 622 | + $geo_params->goverlay = $geo_goverlay; | |
| 623 | + $geo_params->overlay_img = $geo_overlay_img; | |
| 624 | + $geo_params->overlay_south = $geo_overlay_south; | |
| 625 | + $geo_params->overlay_west = $geo_overlay_west; | |
| 626 | + $geo_params->overlay_north = $geo_overlay_north; | |
| 627 | + $geo_params->overlay_east = $geo_overlay_east; | |
| 628 | + | |
| 629 | + // check transient record | |
| 630 | + $param = "geocoding_transient_room_" . $room_id; | |
| 631 | + $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`=" . $dbo->quote($param) . ";"; | |
| 632 | + $dbo->setQuery($q); | |
| 633 | + $dbo->execute(); | |
| 634 | + if ($dbo->getNumRows()) { | |
| 635 | + $q = "UPDATE `#__vikbooking_config` SET `setting`=" . $dbo->quote(json_encode($geo_params)) . " WHERE `param`=" . $dbo->quote($param) . ";"; | |
| 636 | + } else { | |
| 637 | + $q = "INSERT INTO `#__vikbooking_config` (`param`,`setting`) VALUES (" . $dbo->quote($param) . ", " . $dbo->quote(json_encode($geo_params)) . ");"; | |
| 638 | + } | |
| 639 | + // update transient record with new geo params | |
| 640 | + $dbo->setQuery($q); | |
| 641 | + $dbo->execute(); | |
| 642 | + | |
| 643 | + return $geo_params; | |
| 644 | + } | |
| 645 | + | |
| 646 | + /** | |
| 647 | + * Retrieves the last transient for the given room ID (or new room). This | |
| 648 | + * way the room geo params are ready to be stored by the main controller. | |
| 649 | + * | |
| 650 | + * @param int $room_id the room ID (0 for new). | |
| 651 | + * | |
| 652 | + * @return mixed geo params object or false. | |
| 653 | + */ | |
| 654 | + public function getRoomGeoTransient($room_id) | |
| 655 | + { | |
| 656 | + $dbo = JFactory::getDbo(); | |
| 657 | + $param = "geocoding_transient_room_" . (int)$room_id; | |
| 658 | + | |
| 659 | + $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`=" . $dbo->quote($param) . ";"; | |
| 660 | + $dbo->setQuery($q); | |
| 661 | + $dbo->execute(); | |
| 662 | + if (!$dbo->getNumRows()) { | |
| 663 | + $geo_enabled = VikRequest::getInt('geo_enabled', 0, 'request'); | |
| 664 | + if ($geo_enabled) { | |
| 665 | + VikError::raiseWarning('', 'no records found ' . $param); | |
| 666 | + } | |
| 667 | + return false; | |
| 668 | + } | |
| 669 | + $geo_params = json_decode($dbo->loadResult()); | |
| 670 | + | |
| 671 | + return is_object($geo_params) ? $geo_params : false; | |
| 672 | + } | |
| 673 | + | |
| 674 | + /** | |
| 675 | + * Returns a list of room-types with a complete geocoding information that could be imported. | |
| 676 | + * This facilitates the setup of the geographic information for a new room-type. | |
| 677 | + * | |
| 678 | + * @param int $exclude_id the current room to exclude, 0 for new. | |
| 679 | + * | |
| 680 | + * @return array list of room-types with an importable geo configuration. | |
| 681 | + */ | |
| 682 | + public function getImportableConfigRooms($exclude_id = 0) | |
| 683 | + { | |
| 684 | + $importable = array(); | |
| 685 | + | |
| 686 | + $dbo = JFactory::getDbo(); | |
| 687 | + $clauses = array(); | |
| 688 | + | |
| 689 | + if ($exclude_id > 0) { | |
| 690 | + array_push($clauses, '`id` != ' . $exclude_id); | |
| 691 | + } | |
| 692 | + | |
| 693 | + // fetch all rooms with the geo information enabled | |
| 694 | + array_push($clauses, '`params` LIKE ' . $dbo->quote('%"geo":{"enabled":1%')); | |
| 695 | + | |
| 696 | + $q = "SELECT `id`, `name` FROM `#__vikbooking_rooms` WHERE " . implode(' AND ', $clauses) . " ORDER BY `name` ASC;"; | |
| 697 | + $dbo->setQuery($q); | |
| 698 | + $dbo->execute(); | |
| 699 | + if ($dbo->getNumRows()) { | |
| 700 | + $importable = $dbo->loadAssocList(); | |
| 701 | + } | |
| 702 | + | |
| 703 | + return $importable; | |
| 704 | + } | |
| 705 | + | |
| 706 | + /** | |
| 707 | + * AJAX method called by the main controller when requesting | |
| 708 | + * to import the geo coding information for one specific room. | |
| 709 | + * | |
| 710 | + * @return object the geo params of the room requested. | |
| 711 | + * | |
| 712 | + * @throws Exception | |
| 713 | + */ | |
| 714 | + public function importRoomGeoConfig() | |
| 715 | + { | |
| 716 | + $dbo = JFactory::getDbo(); | |
| 717 | + | |
| 718 | + $room_id = VikRequest::getInt('room_id', 0, 'request'); | |
| 719 | + | |
| 720 | + $q = "SELECT `id`, `name`, `params` FROM `#__vikbooking_rooms` WHERE id={$room_id};"; | |
| 721 | + $dbo->setQuery($q); | |
| 722 | + $dbo->execute(); | |
| 723 | + if (!$dbo->getNumRows()) { | |
| 724 | + throw new Exception("Room not found for importing geo config", 404); | |
| 725 | + } | |
| 726 | + $room = $dbo->loadAssoc(); | |
| 727 | + $rparams = json_decode($room['params']); | |
| 728 | + if (!is_object($rparams)) { | |
| 729 | + throw new Exception("Unable to decode room params", 500); | |
| 730 | + } | |
| 731 | + | |
| 732 | + // get all geo params | |
| 733 | + $geo_params = $this->getRoomGeoParams($rparams); | |
| 734 | + | |
| 735 | + if (!is_object($geo_params)) { | |
| 736 | + throw new Exception("Unable to get room geo params", 500); | |
| 737 | + } | |
| 738 | + | |
| 739 | + return $geo_params; | |
| 740 | + } | |
| 741 | +} | |