PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.6
VikBooking Hotel Booking Engine & PMS v1.6.6
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
vikbooking / libraries / adapter / application / document.php

document.php in VikBooking Hotel Booking Engine & PMS 1.6.6, at libraries/adapter/application/document.php

605 lines 15.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.application
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 * Document class, provides an easy interface to parse and display a document
16 * using the Joomla standard functions.
17 *
18 * @since 10.0
19 */
20 class JDocument
21 {
22 /**
23 * An array to cache the meta data set using this class.
24 *
25 * @var array
26 */
27 protected $data = [];
28
29 /**
30 * A list containing all the style declarations loaded.
31 *
32 * @var array
33 */
34 protected $styleDeclarations = [];
35
36 /**
37 * Array of scripts options.
38 *
39 * @var array
40 * @since 10.1.14
41 */
42 protected $scriptOptions = [];
43
44 /**
45 * Array of scripts declarations to be
46 * appended after the body.
47 *
48 * @var array
49 * @since 10.1.29
50 */
51 protected $ajaxScripts = [];
52
53 /**
54 * Sets a meta tag in the front-end only.
55 *
56 * @param string $name Name of the meta HTML tag.
57 * @param mixed $content Value of the meta HTML tag as array or string.
58 * @param string $attribute Attribute to use in the meta HTML tag.
59 *
60 * @return self This object to support chaining.
61 *
62 * @uses attachToHead()
63 */
64 public function setMetaData($name, $content, $attribute = 'name')
65 {
66 $attribute = empty($attribute) || !is_string($attribute) ? 'name' : $attribute;
67
68 if (is_scalar($content))
69 {
70 $content = array($content);
71 }
72
73 $this->attachToHead(function() use ($name, $content, $attribute)
74 {
75 foreach ($content as $cont)
76 {
77 echo "<meta {$attribute}=\"{$name}\" content=\"" . esc_attr($cont) . "\" />\n";
78 }
79 }, true);
80
81 $this->data[$name] = $content;
82
83 return $this;
84 }
85
86 /**
87 * Gets a meta tag.
88 * Since Wordpress doesn't own a system to handle meta data,
89 * we can only return a cached version of the data set using this class.
90 *
91 * @param string $name Name of the meta HTML tag.
92 *
93 * @return string
94 */
95 public function getMetaData($name)
96 {
97 if (isset($this->data[$name]))
98 {
99 return $this->data[$name];
100 }
101
102 return '';
103 }
104
105 /**
106 * Sets the title of the document in the front-end only.
107 *
108 * @param string $title The title to be set.
109 *
110 * @return self This object to support chaining.
111 *
112 * @link https://developer.wordpress.org/reference/hooks/wp_title/ (Wordpress < 4.4)
113 * @link https://developer.wordpress.org/reference/functions/wp_get_document_title/ (Wordpress 4.4+)
114 */
115 public function setTitle($title)
116 {
117 /**
118 * We should use the hook 'pre_get_document_title' (available from WP >= v4.4),
119 * instead of 'wp_title', or the title won't actually be set.
120 *
121 * @since 10.1.23
122 */
123 add_filter('pre_get_document_title', function() use ($title)
124 {
125 return $title;
126 });
127
128 return $this;
129 }
130
131 /**
132 * Return the title of the document.
133 *
134 * @return string
135 *
136 * @link https://developer.wordpress.org/reference/hooks/wp_title/ (Wordpress < 4.4)
137 * @link https://developer.wordpress.org/reference/functions/wp_get_document_title/ (Wordpress 4.4+)
138 */
139 public function getTitle()
140 {
141 global $wp_version;
142
143 if (version_compare($wp_version, '4.4', '>='))
144 {
145 return wp_get_document_title();
146 }
147
148 return wp_title('&raquo;', false);
149 }
150
151 /**
152 * Sets the description of the document.
153 *
154 * @param string $desc The description to be set.
155 *
156 * @return self This object to support chaining.
157 *
158 * @uses setMetaData()
159 */
160 public function setDescription($desc)
161 {
162 return $this->setMetaData('description', (string) $desc);
163 }
164
165 /**
166 * Return the description of the document.
167 *
168 * @return string
169 *
170 * @uses getMetaData()
171 */
172 public function getDescription()
173 {
174 return $this->getMetaData('description');
175 }
176
177 /**
178 * Adds a linked script to the page.
179 *
180 * @param string $url URL to the linked script.
181 * @param array $options Array of options. Example: array('version' => 'auto', 'conditional' => 'lt IE 9')
182 * @param array $attribs Array of attributes. Example: array('id' => 'scriptid', 'async' => 'async', 'data-test' => 1)
183 *
184 * @return self This object to support chaining.
185 *
186 * @link https://developer.wordpress.org/reference/functions/wp_register_script/
187 */
188 public function addScript($url, $options = [], $attribs = [])
189 {
190 // check if the script should be loaded using WP native libs
191 $version = array_key_exists('version', $options) ? $options['version'] : null;
192 $footer = array_key_exists('footer', $options) ? (bool) $options['footer'] : false;
193 $id = empty($attribs['id']) ? md5($url) : $attribs['id'];
194
195 /**
196 * Use filter to approve/deny the loading of the given script.
197 *
198 * @param boolean $load The recursive filtered value (default 'true').
199 * @param string $url The resource URL.
200 * @param string $id The script ID attribute.
201 * @param string $version The script version, if specified.
202 * @param boolean $footer True whether the script is going to be loaded in the footer.
203 *
204 * @return boolean True to load the resource, false to ignore it.
205 *
206 * @since 10.1.25
207 */
208 $load = apply_filters('vik_before_include_script', true, $url, $id, $version, $footer);
209
210 if ($load)
211 {
212 // make sure this is not an AJAX call
213 if (!wp_doing_ajax())
214 {
215 // if the headers have been sent, the script must be registered in the footer.
216 if (headers_sent())
217 {
218 $footer = true;
219 }
220
221 // the default array of dependencies
222 $deps = [
223 'jquery-core',
224 'jquery-ui-core',
225 ];
226
227 /**
228 * Added support to custom dependencies.
229 *
230 * @since 10.1.38
231 */
232 if (!empty($options['dependencies']))
233 {
234 // join default dependencies with the given ones
235 $deps = array_merge($deps, (array) $options['dependencies']);
236 // get rid of duplicates
237 $deps = array_values(array_unique($deps));
238 }
239
240 // loads scripts always after jQuery Core (included by Wordpress)
241 wp_register_script($id, $url, $deps, $version, $footer);
242 wp_enqueue_script($id);
243 }
244 // since the footer is already printed, we need to each our script directly
245 else if ($url)
246 {
247 if ($version)
248 {
249 $url .= '?ver=' . $version;
250 }
251
252 echo '<script type="text/javascript" src="' . $url . '"></script>';
253 }
254 }
255
256 return $this;
257 }
258
259 /**
260 * Adds a script to the page.
261 *
262 * @param string $content Script snippet.
263 * @param string $type Scripting mime (defaults to 'text/javascript').
264 *
265 * @return self This object to support chaining.
266 *
267 * @uses attachToHead()
268 */
269 public function addScriptDeclaration($content, $type = 'text/javascript')
270 {
271 /**
272 * Always use the script declaration without checking
273 * if it has been already loaded.
274 *
275 * @since 10.1.17
276 */
277 $this->attachToHead(function() use ($content, $type)
278 {
279 /**
280 * Use "joomla-options new" class in case we are attaching a JSON string.
281 * The "new" word means that the options has to be loaded.
282 *
283 * @since 10.1.14
284 */
285 $class = $type == 'application/json' ? ' class="joomla-options new"' : '';
286
287 echo "<script type=\"{$type}\"{$class}>\n{$content}\n</script>\n";
288 });
289
290 return $this;
291 }
292
293 /**
294 * Adds a linked stylesheet to the page.
295 *
296 * @param string $url URL to the linked style sheet.
297 * @param array $options Array of options. Example: array('version' => 'auto', 'conditional' => 'lt IE 9')
298 * @param array $attribs Array of attributes. Example: array('id' => 'stylesheet', 'data-test' => 1)
299 *
300 * @return self This object to support chaining.
301 *
302 * @link https://codex.wordpress.org/Function_Reference/wp_register_style
303 */
304 public function addStyleSheet($url, $options = [], $attribs = [])
305 {
306 $version = array_key_exists('version', $options) ? $options['version'] : null;
307 $media = array_key_exists('media', $options) ? (string) $options['media'] : 'all';
308 $id = empty($attribs['id']) ? md5($url) : $attribs['id'];
309
310 /**
311 * Use filter to approve/deny the loading of the given stylesheet.
312 *
313 * @param boolean $load The recursive filtered value (default 'true').
314 * @param string $url The resource URL.
315 * @param string $id The stylesheet ID attribute.
316 * @param string $version The stylesheet version, if specified.
317 *
318 * @return boolean True to load the resource, false to ignore it.
319 *
320 * @since 10.1.25
321 */
322 $load = apply_filters('vik_before_include_style', true, $url, $id, $version);
323
324 if ($load)
325 {
326 // attach the style to the <head> only if the headers haven't been sent
327 // and if we are not doing an AJAX call
328 if (!headers_sent() && !wp_doing_ajax())
329 {
330 $deps = [];
331
332 /**
333 * Added support to custom dependencies.
334 *
335 * @since 10.1.38
336 */
337 if (!empty($options['dependencies']))
338 {
339 // join default dependencies with the given ones
340 $deps = array_merge($deps, (array) $options['dependencies']);
341 // get rid of duplicates
342 $deps = array_values(array_unique($deps));
343 }
344
345 wp_register_style($id, $url, $deps, $version, $media);
346 wp_enqueue_style($id);
347 }
348 // otherwise print the style in the document <body>
349 else
350 {
351 if ($version)
352 {
353 $url .= '?ver=' . $version;
354 }
355
356 echo '<link rel="stylesheet" id="' . $id . '" href="' . $url . '" type="text/css" media="' . $media . '">';
357 }
358 }
359
360 return $this;
361 }
362
363 /**
364 * Adds a stylesheet declaration to the page.
365 *
366 * @param string $content Style declaration.
367 * @param string $type Type of stylesheet (defaults to 'text/css').
368 *
369 * @return self This object to support chaining.
370 *
371 * @uses attachToHead()
372 */
373 public function addStyleDeclaration($content, $type = 'text/css')
374 {
375 if (!in_array($content, $this->styleDeclarations))
376 {
377 $this->attachToHead(function() use ($content, $type)
378 {
379 echo "<style type=\"{$type}\">\n{$content}\n</style>\n";
380 });
381
382 $this->styleDeclarations[] = $content;
383 }
384
385 return $this;
386 }
387
388 /**
389 * Internal method execute a callback within the <head> tags.
390 * The callback will be attached to the wp_head or admin_head hooks
391 * depending on the section we are currently using.
392 *
393 * @param mixed $callback The callback or the function name to attach.
394 * @param boolean $frontOnly True to attach the method only in the front-end.
395 *
396 * @return void
397 *
398 * @link https://codex.wordpress.org/Plugin_API/Action_Reference/wp_head
399 * @link https://codex.wordpress.org/Plugin_API/Action_Reference/admin_head
400 * @link https://developer.wordpress.org/reference/hooks/wp_print_footer_scripts/
401 * @link https://developer.wordpress.org/reference/hooks/admin_print_footer_scripts/
402 */
403 protected function attachToHead($callback, $frontOnly = false)
404 {
405 $app = JFactory::getApplication();
406
407 // make sure we are in the front-end or the back-end is allowed
408 if ($app->isSite() || !$frontOnly)
409 {
410 // make sure we are not doing an AJAX call
411 if (!wp_doing_ajax())
412 {
413 $head_hook = $app->isAdmin() ? 'admin_head' : 'wp_head';
414
415 // make sure that the head hook that we are using haven't been called yet,
416 // otherwise our script will never be executed
417 if (!headers_sent() && !did_action($head_hook))
418 {
419 // admin_head hook for the back-end <head>
420 // wp_head hook for the front-end <head>
421 add_action($head_hook, $callback);
422 }
423 else
424 {
425 // admin_print_footer_scripts hook for the back-end <footer>
426 // wp_footer wp_print_footer_scripts for the front-end <footer>
427 add_action($app->isAdmin() ? 'admin_print_footer_scripts' : 'wp_print_footer_scripts', $callback);
428
429 /**
430 * NOTE: do not use 'wp_footer' hook because it prints the script declarations
431 * always before the <script> tags, causing errors for missing resources.
432 */
433 }
434 }
435 // we need to invoke our callback directly
436 else
437 {
438 // push scripts within the AJAX callbacks
439 $this->ajaxScripts[] = $callback;
440 }
441 }
442 }
443
444 /**
445 * Returns the AJAX scripts that should be included after
446 * the body in order to properly access all the needed elements.
447 *
448 * @return string
449 *
450 * @since 10.1.29
451 */
452 public function getAjaxScripts()
453 {
454 // start buffering
455 ob_start();
456
457 // iterate registered scripts
458 foreach ($this->ajaxScripts as $callback)
459 {
460 // invoke the callback to print the script
461 call_user_func($callback);
462 }
463
464 // catch buffer
465 $js = ob_get_contents();
466 // clear buffer
467 ob_end_clean();
468
469 // empty list
470 $this->ajaxScripts = [];
471
472 return $js;
473 }
474
475 /**
476 * Add options for script.
477 *
478 * @param string $key Name in Storage.
479 * @param mixed $options Scrip options as array or string.
480 * @param boolean $merge Whether merge with existing (true) or replace (false).
481 *
482 * @return self This object to support chaining.
483 *
484 * @since 10.1.14
485 */
486 public function addScriptOptions($key, $options, $merge = true)
487 {
488 if (empty($this->scriptOptions[$key]))
489 {
490 $this->scriptOptions[$key] = [];
491 }
492
493 if ($merge && is_array($options))
494 {
495 $this->scriptOptions[$key] = array_replace_recursive($this->scriptOptions[$key], $options);
496 }
497 else
498 {
499 $this->scriptOptions[$key] = $options;
500 }
501
502 return $this;
503 }
504
505 /**
506 * Get script(s) options.
507 *
508 * @param string $key Name in Storage.
509 *
510 * @return array Options for given $key, or all script options.
511 *
512 * @since 10.1.14
513 */
514 public function getScriptOptions($key = null)
515 {
516 if ($key)
517 {
518 return (empty($this->scriptOptions[$key])) ? [] : $this->scriptOptions[$key];
519 }
520 else
521 {
522 return $this->scriptOptions;
523 }
524 }
525
526 /**
527 * Returns the document charset encoding.
528 *
529 * @return string
530 *
531 * @since 10.1.20
532 */
533 public function getCharset()
534 {
535 $output = get_option('blog_charset');
536
537 if (!$output)
538 {
539 $output = 'UTF-8';
540 }
541
542 return $output;
543 }
544
545 /**
546 * Returns the document language.
547 *
548 * @return string
549 *
550 * @since 10.1.20
551 */
552 public function getLanguage()
553 {
554 return strtolower(JFactory::getLanguage()->getTag());
555 }
556
557 /**
558 * Returns the document direction declaration.
559 *
560 * @return string
561 *
562 * @since 10.1.20
563 */
564 public function getDirection()
565 {
566 if (function_exists('is_rtl'))
567 {
568 $output = is_rtl() ? 'rtl' : 'ltr';
569 }
570 else
571 {
572 $output = 'ltr';
573 }
574
575 return $output;
576 }
577
578 /**
579 * Adds `<link>` tags to the head of the document.
580 *
581 * $relType defaults to 'rel' as it is the most common relation type used
582 * ('rev' refers to reverse relation, 'rel' indicates normal, forward relation).
583 * Typical tag: `<link href="index.php" rel="Start">`.
584 *
585 * @param string $href The link that is being related.
586 * @param string $relation Relation of link.
587 * @param string $relType Relation type attribute. Either rel or rev (default: 'rel').
588 * @param array $attribs Associative array of remaining attributes.
589 *
590 * @return self This object to support chaining.
591 *
592 * @since 10.1.48
593 */
594 public function addHeadLink(string $href, string $relation, string $relType = 'rel', array $attribs = [])
595 {
596 $this->attachToHead(function() use ($href, $relation, $relType, $attribs)
597 {
598 JLoader::import('adapter.utilities.array');
599 echo "<link href=\"{$href}\" {$relType}=\"$relation\" " . ArrayHelper::toString($attribs) . " />\n";
600 });
601
602 return $this;
603 }
604 }
605