PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
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 1.7.3 All 36 releases
vikbooking / libraries / adapter / html / html.php

html.php in VikBooking Hotel Booking Engine & PMS trunk, at libraries/adapter/html/html.php

637 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 }
637