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 | libraries/adapter/html/html.php +636 -0 1.6.3 → 1.8.16 View file →
@@ -1,0 +1,636 @@
1 +<?php
2 +/**
3 + * @package VikWP - Libraries
4 + * @subpackage adapter.html
5 + * @author E4J s.r.l.
6 + * @copyright Copyright (C) 2023 E4J s.r.l. All Rights Reserved.
7 + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 + * @link https://vikwp.com
9 + */
10 +
11 +// No direct access
12 +defined('ABSPATH') or die('No script kiddies please!');
13 +
14 +/**
15 + * Utility class for all HTML drawing classes.
16 + *
17 + * @since 10.0
18 + */
19 +abstract class JHtml
20 +{
21 + /**
22 + * A list of callback functions.
23 + *
24 + * @var Callable[]
25 + */
26 + protected static $callbacks = array();
27 +
28 + /**
29 + * A list of loaded classes.
30 + *
31 + * @var array
32 + */
33 + protected static $loaded = array();
34 +
35 + /**
36 + * An array to hold included paths.
37 + *
38 + * @var array
39 + * @since 10.1.29
40 + */
41 + protected static $includePaths = array();
42 +
43 + /**
44 + * The base folder containing the classes to load.
45 + *
46 + * @var string
47 + */
48 + public static $base = '';
49 +
50 + /**
51 + * Option values related to the generation of HTML output.
52 + * Recognized options are:
53 + *
54 + * @property integer fmtDepth The current indent depth.
55 + * @property string fmtEol The end of line string, default is linefeed.
56 + * @property string fmtIndent The string to use for indentation, default is tab.
57 + *
58 + * @var array
59 + * @since 10.1.16
60 + */
61 + public static $formatOptions = array(
62 + 'format.depth' => 0,
63 + 'format.eol' => "\n",
64 + 'format.indent' => "\t",
65 + );
66 +
67 + /**
68 + * Helper method to call a function using a specific notation:
69 + * [prefix].[filename].[function]
70 + *
71 + * For example: JView.helper.doSomething will call JViewHelper::doSomething().
72 + * In case the prefix is missing, it will be used the default one: JHtml.
73 + * In case also the file is missing, the system will try to call a
74 + * function contained in the current class.
75 + *
76 + * @uses isRegistered()
77 + * @uses extract()
78 + * @uses loadFile()
79 + * @uses register()
80 + * @uses call()
81 + */
82 + public static function _($key)
83 + {
84 + // check if the key already owns a callback
85 + if (!static::isRegistered($key))
86 + {
87 + // extract the data from the key
88 + list($key, $prefix, $file, $func) = static::extract($key);
89 +
90 + // the classname begins with the specified prefix (JHtml if not given)
91 + $classname = ucwords($prefix);
92 +
93 + // check if the file is set
94 + if ($file)
95 + {
96 + // prepend the filename to the classname and load the file
97 + $classname .= ucwords($file);
98 +
99 + static::loadFile($file);
100 + }
101 +
102 + // once the file is loaded, we need to register the callback
103 + static::register($key, array($classname, $func));
104 + }
105 +
106 + // obtain the list of specified arguments
107 + $args = func_get_args();
108 + // remove the $key from the arguments list
109 + array_shift($args);
110 +
111 + // dispatch the callback
112 + return static::call($key, $args);
113 + }
114 +
115 + /**
116 + * Proxy for underscore method.
117 + * Needed to bypass the issue reported here:
118 + * @link https://meta.trac.wordpress.org/ticket/3601
119 + *
120 + * @since 10.1.32 Renamed from `u`.
121 + */
122 + public static function fetch($key)
123 + {
124 + return call_user_func_array(array('JHtml', '_'), func_get_args());
125 + }
126 +
127 + /**
128 + * Checks if there is a callback registered to the specified key.
129 + *
130 + * @param string $key The key to check for.
131 + *
132 + * @return boolean True if there is a callback, otherwise false.
133 + */
134 + public static function isRegistered($key)
135 + {
136 + return isset(static::$callbacks[$key]);
137 + }
138 +
139 + /**
140 + * Method used to extract the prefix, the file and the function to call
141 + * from a specified key (in dot notation).
142 + *
143 + * @param string $key The key describing the method to launch.
144 + *
145 + * @return array The array containing the prefix, the file and the function.
146 + */
147 + public static function extract($key)
148 + {
149 + // strip unexpected characters
150 + $key = preg_replace("/[^a-z0-9_.]+/i", '', $key);
151 +
152 + // check to see whether we need to load a helper file
153 + $parts = explode('.', $key);
154 +
155 + $prefix = count($parts) === 3 ? array_shift($parts) : 'JHtml';
156 + $file = count($parts) === 2 ? array_shift($parts) : '';
157 + $func = array_shift($parts);
158 +
159 + return array(strtolower($prefix . '.' . $file . '.' . $func), $prefix, $file, $func);
160 + }
161 +
162 + /**
163 + * Add a directory where JHtml should search for helpers.
164 + * You may either pass a string or an array of directories.
165 + *
166 + * @param string $path A path to search.
167 + *
168 + * @return array An array with directory elements.
169 + *
170 + * @since 10.1.29
171 + */
172 + public static function addIncludePath($path = '')
173 + {
174 + // loop through the path directories
175 + foreach ((array) $path as $dir)
176 + {
177 + if (!empty($dir) && !in_array($dir, static::$includePaths))
178 + {
179 + array_unshift(static::$includePaths, JPath::clean($dir));
180 + }
181 + }
182 +
183 + return static::$includePaths;
184 + }
185 +
186 + /**
187 + * Tries to load the given filename.
188 + *
189 + * @param string $file The file to load.
190 + *
191 + * @return void
192 + */
193 + public static function loadFile($file)
194 + {
195 + // search on default paths
196 + $base = empty(static::$base) ? dirname(__FILE__) . DIRECTORY_SEPARATOR . 'classes' : $base;
197 +
198 + // merge base path with include paths
199 + $paths = array_merge(array($base), static::addIncludePath());
200 +
201 + $found = false;
202 +
203 + /**
204 + * Since different plugins might include files with
205 + * the same name, it is needed to scan and load all
206 + * the files with the matching name.
207 + *
208 + * @since 10.1.30
209 + */
210 + foreach ($paths as $path)
211 + {
212 + // create path
213 + $path = JPath::clean($path . DIRECTORY_SEPARATOR . $file . '.php');
214 +
215 + // check whether we already loaded this file
216 + if (!isset(static::$loaded[$path]))
217 + {
218 + // make sure the file exists
219 + if (is_file($path))
220 + {
221 + // cache path as loaded
222 + static::$loaded[$path] = 1;
223 +
224 + // require the file
225 + $found = (bool) require_once $path;
226 + }
227 + }
228 + else
229 + {
230 + // already loaded
231 + $found = true;
232 + }
233 + }
234 +
235 + if (!$found)
236 + {
237 + // file not found, raise error
238 + throw new Exception("JHtml [" . $file . "] helper class not found.", 404);
239 + }
240 + }
241 +
242 + /**
243 + * Registers a callback for the given key.
244 + *
245 + * @param string The key used to trigger the callback.
246 + * @param Callable|array The callback function to run.
247 + */
248 + public static function register($key, $callback)
249 + {
250 + if (!is_callable($callback))
251 + {
252 + if (!is_array($callback))
253 + {
254 + $callback = array($callback);
255 + }
256 +
257 + throw new Exception('The callback [' . implode('::', $callback) . '()] is not callable.', 500);
258 + }
259 +
260 + static::$callbacks[$key] = $callback;
261 + }
262 +
263 + /**
264 + * Executes the callback assigned to the specified key.
265 + *
266 + * @param string $key The callback key.
267 + * @param array $args A list of arguments to pass.
268 + *
269 + * @param mixed The value returned by the callback.
270 + *
271 + * @uses isRegistered()
272 + */
273 + public static function call($key, array &$args = array())
274 + {
275 + if (!static::isRegistered($key))
276 + {
277 + return null;
278 + }
279 +
280 + return call_user_func_array(static::$callbacks[$key], $args);
281 + }
282 +
283 + /**
284 + * Includes the specified script URI in the document <head>.
285 + *
286 + * @param string $uri The script URI.
287 + * @param array $options Array of options. Example: array('version' => 'auto', 'conditional' => 'lt IE 9').
288 + * @param array $attribs Array of attributes. Example: array('id' => 'scriptid', 'async' => 'async', 'data-test' => 1).
289 + *
290 + * @return void
291 + */
292 + public static function script($uri, $options = array(), $attribs = array())
293 + {
294 + $document = JFactory::getDocument();
295 +
296 + // in case we don't have an array of options, create it
297 + if (!is_array($options))
298 + {
299 + $options = array();
300 + }
301 +
302 + // in case we don't have an array of attributes, create it
303 + if (!is_array($attribs))
304 + {
305 + $attribs = array();
306 + }
307 +
308 + // check if the script should be loaded as dependency
309 + if (preg_match("/jquery-ui[0-9.\-]*\.min\.js$/", $uri))
310 + {
311 + $attribs['id'] = 'jquery-ui-datepicker';
312 + // load datepicker jQuery UI add-on
313 + $document->addScript(null, $options, $attribs);
314 +
315 + $attribs['id'] = 'jquery-ui-dialog';
316 + // load dialog jQuery UI add-on
317 + $document->addScript(null, $options, $attribs);
318 +
319 + if (JFactory::getApplication()->isSite())
320 + {
321 + $attribs['id'] = 'jquery-ui-tooltip';
322 + // load tooltip jQuery UI add-on (site only)
323 + $document->addScript(null, $options, $attribs);
324 + }
325 + }
326 + else if (preg_match("/jquery[0-9.\-]*\.min\.js$/", $uri))
327 + {
328 + // do nothing, jQuery core is always loaded
329 + }
330 + else if (preg_match("/jquery-ui\.sortable\.min\.js$/", $uri))
331 + {
332 + $attribs['id'] = 'jquery-ui-sortable';
333 + // load jQuery UI Sortable add-on
334 + $document->addScript(null, $options, $attribs);
335 + }
336 + else if (preg_match("/jquery-ui\.draggable\.min\.js$/", $uri))
337 + {
338 + $attribs['id'] = 'jquery-ui-draggable';
339 + // load jQuery UI Draggable add-on
340 + $document->addScript(null, $options, $attribs);
341 + }
342 + else if (preg_match("/jquery-ui\.slider\.min\.js$/", $uri))
343 + {
344 + $attribs['id'] = 'jquery-ui-slider';
345 + // load jQuery UI Slider add-on
346 + $document->addScript(null, $options, $attribs);
347 + }
348 + else
349 + {
350 + if (empty($attribs['id']) && preg_match("/maps\.googleapis\.com/", $uri))
351 + {
352 + $attribs['id'] = 'gmaps';
353 + }
354 +
355 + if (empty($attribs['id']))
356 + {
357 + /**
358 + * Implemented lookup to avoid generating the same ID
359 + * for files with the same name but placed in different
360 + * positions for the plugin (e.g. site/admin).
361 + *
362 + * @since 10.1.30
363 + */
364 + static $lookup = array();
365 +
366 + // extract last folder and file name from URI
367 + if (preg_match("/([^\/\\\\]+)[\/\\\\]([^\/\\\\]+)\.js$/i", $uri, $match))
368 + {
369 + // make ID as unique as possible and strip unsupported chars
370 + $attribs['id'] = preg_replace("/[^a-z0-9_-]/i", '', $match[1] . '-' . $match[2]);
371 + }
372 + else
373 + {
374 + // use uniq ID otherwise
375 + $attribs['id'] = uniqid();
376 + }
377 +
378 + $cont = 1;
379 +
380 + // iterate as long as the ID has been already registered
381 + // and belongs to a different source URI
382 + do
383 + {
384 + // create temporary ID
385 + $tmp = $attribs['id'];
386 +
387 + if ($cont > 1)
388 + {
389 + // append counter from 2 on
390 + $tmp .= '-' . $cont;
391 + }
392 +
393 + // increase counter
394 + $cont++;
395 +
396 + } while (isset($lookup[$tmp]) && $lookup[$tmp] != $uri);
397 +
398 + // re-assign ID
399 + $attribs['id'] = $tmp;
400 +
401 + // register ID within the cache lookup
402 + $lookup[$attribs['id']] = $uri;
403 + }
404 +
405 + // load the custom script
406 + $document->addScript($uri, $options, $attribs);
407 + }
408 + }
409 +
410 + /**
411 + * Includes the specified stylesheet URI in the document <head>.
412 + *
413 + * @param string $uri The style URI.
414 + * @param array $options Array of options. Example: array('version' => 'auto', 'conditional' => 'lt IE 9').
415 + * @param array $attribs Array of attributes. Example: array('id' => 'scriptid', 'async' => 'async', 'data-test' => 1).
416 + *
417 + * @return void
418 + */
419 + public static function stylesheet($uri, $options = array(), $attribs = array())
420 + {
421 + if (empty($attribs['id']))
422 + {
423 + /**
424 + * Implemented lookup to avoid generating the same ID
425 + * for files with the same name but placed in different
426 + * positions for the plugin (e.g. site/admin).
427 + *
428 + * @since 10.1.30
429 + */
430 + static $lookup = array();
431 +
432 + // use file basename as ID if not specified
433 + $attribs['id'] = basename($uri);
434 +
435 + // normalize ID attribute
436 + $attribs['id'] = preg_replace("/[^a-zA-Z0-9\-_]+/", '-', $attribs['id']);
437 +
438 + $cont = 1;
439 +
440 + // iterate as long as the ID has been already registered
441 + // and belongs to a different source URI
442 + do
443 + {
444 + // create temporary ID
445 + $tmp = $attribs['id'];
446 +
447 + if ($cont > 1)
448 + {
449 + // append counter from 2 on
450 + $tmp .= '-' . $cont;
451 + }
452 +
453 + // increase counter
454 + $cont++;
455 +
456 + } while (isset($lookup[$tmp]) && $lookup[$tmp] != $uri);
457 +
458 + // re-assign ID
459 + $attribs['id'] = $tmp;
460 +
461 + // register ID within the cache lookup
462 + $lookup[$attribs['id']] = $uri;
463 + }
464 +
465 + /**
466 + * Added support for options and attributes.
467 + *
468 + * @since 10.1.27
469 + */
470 + JFactory::getDocument()->addStyleSheet($uri, $options, $attribs);
471 + }
472 +
473 + /**
474 + * Displays a calendar control field.
475 + *
476 + * @param mixed $value The date value.
477 + * @param string $name The name of the text field.
478 + * @param string $id The id of the text field.
479 + * @param string $format The date format.
480 + * @param mixed $attribs Additional HTML attributes.
481 + * The array can have the following keys:
482 + * readonly Sets the readonly parameter for the input tag.
483 + * disabled Sets the disabled parameter for the input tag.
484 + * autofocus Sets the autofocus parameter for the input tag.
485 + * autocomplete Sets the autocomplete parameter for the input tag.
486 + * filter Sets the filter for the input tag.
487 + *
488 + * @return string HTML markup for a calendar field.
489 + */
490 + public static function calendar($value, $name, $id, $format = 'Y-m-d', $attribs = array())
491 + {
492 + $class = isset($attribs['class']) ? $attribs['class'] : '';
493 + $showTime = isset($attribs['showTime']) ? $attribs['showTime'] : false;
494 +
495 + unset($attribs['name']);
496 + unset($attribs['id']);
497 + unset($attribs['value']);
498 + unset($attribs['class']);
499 + unset($attribs['showTime']);
500 +
501 + $str = '';
502 + foreach ($attribs as $k => $v)
503 + {
504 + if (!strlen($v) || $v === true)
505 + {
506 + $v = $k;
507 + }
508 +
509 + $str .= $k . '="' . str_replace('"', '&quot;', $v) . '" ';
510 + }
511 +
512 + // make sure the format is compatible with the jQuery UI Datepicker
513 + $format = str_replace('%', '', $format);
514 +
515 + /**
516 + * Add support for timestamp and JDate instances.
517 + *
518 + * @since 10.1.16
519 + */
520 + if (preg_match("/^\d+$/", (string) $value))
521 + {
522 + // fetch timestamp
523 + $value = date($format, $value);
524 + }
525 + else if ($value instanceof JDate)
526 + {
527 + /**
528 + * Format string from JDate.
529 + *
530 + * @since 10.1.35 Always adjust to local timezone.
531 + */
532 + $value = $value->format($format, $locale = true);
533 + }
534 +
535 + $data = array();
536 + $data['value'] = $value;
537 + $data['name'] = $name;
538 + $data['id'] = $id;
539 + $data['class'] = $class;
540 + $data['format'] = $format;
541 + $data['attr'] = $str;
542 + $data['showTime'] = $showTime;
543 +
544 + JFactory::getDocument()->addScriptDeclaration(
545 +<<<JAVASCRIPT
546 +jQuery(function() {
547 +
548 + var sel_format = "$format";
549 + var df_separator = sel_format[1];
550 +
551 + sel_format = sel_format.replace(new RegExp("\\\\"+df_separator, 'g'), "");
552 +
553 + if (sel_format.match(/^Ymd/)) {
554 + sel_format = "yy" + df_separator + "mm" + df_separator + "dd";
555 + } else if (sel_format.match(/^mdY/)) {
556 + sel_format = "mm" + df_separator + "dd" + df_separator + "yy";
557 + } else {
558 + sel_format = "dd" + df_separator + "mm" + df_separator + "yy";
559 + }
560 +
561 + jQuery('input[name="$name"]:input').datepicker({
562 + dateFormat: sel_format,
563 + });
564 +
565 + jQuery('input[name="$name"]:input').next('i').click(function() {
566 + jQuery('input[name="$name"]:input').focus();
567 + });
568 +});
569 +JAVASCRIPT
570 + );
571 +
572 + /**
573 + * Render calendar layout.
574 + * @note: this method should be registered by the plugin
575 + * in order to use a custom layout.
576 + */
577 + return static::fetch('renderCalendar', $data);
578 + }
579 +
580 + /**
581 + * Returns formatted date according to a given format and time zone.
582 + *
583 + * @param string $input String in a format accepted by date(), defaults to "now".
584 + * @param string $format The date format specification string (see {@link PHP_MANUAL#date}).
585 + * @param mixed $tz Time zone to be used for the date. Special cases: boolean true for global
586 + * setting, boolean false for server setting.
587 + *
588 + * @return string A date translated by the given format and time zone.
589 + */
590 + public static function date($input = 'now', $format = null, $tz = true)
591 + {
592 + // UTC date converted to user time zone.
593 + if ($tz === true)
594 + {
595 + // get a date object based on UTC
596 + $date = JFactory::getDate($input, 'UTC');
597 +
598 + // get global timezone setting
599 + $global_tz = JFactory::getApplication()->get('offset', 'UTC');
600 +
601 + // set the correct time zone based on the global configuration
602 + $date->setTimezone(new DateTimeZone($global_tz));
603 + }
604 + // no date conversion (server timezone)
605 + else if ($tz === null)
606 + {
607 + $date = JFactory::getDate($input);
608 + }
609 + // UTC date converted to given time zone.
610 + else
611 + {
612 + // get a date object based on UTC.
613 + $date = JFactory::getDate($input, 'UTC');
614 +
615 + // set the correct time zone based on the specified string
616 + $date->setTimezone(new DateTimeZone($tz));
617 + }
618 +
619 + // if no format is given use the default one
620 + if (!$format)
621 + {
622 + $format = 'Y-m-d H:i:s';
623 + }
624 + /**
625 + * Check whether the supplied format is a language definition.
626 + *
627 + * @since 10.1.35
628 + */
629 + else if (JFactory::getLanguage()->hasKey($format))
630 + {
631 + $format = JText::translate($format);
632 + }
633 +
634 + return $date->format($format, true);
635 + }
636 +}