PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
← All changes | admin/helpers/geocoding.php +741 -0 1.6.2 → 1.8.16 View file →
@@ -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 +}