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 / wordpress / application.php

application.php in VikBooking Hotel Booking Engine & PMS trunk, at libraries/wordpress/application.php

892 lines 25.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking - Libraries
4 * @subpackage wordpress
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2018 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 // do nothing if the class already exists
15 if (!class_exists('VikApplication'))
16 {
17 VikBookingLoader::import('wordpress.version');
18
19 /**
20 * Helper class to adapt the application to the requirements
21 * of the installed Wordpress version.
22 *
23 * @since 1.0
24 */
25 class VikApplication
26 {
27 /**
28 * The instance to handle the singleton.
29 *
30 * @var self
31 */
32 protected static $instance = null;
33
34 /**
35 * Class constructor.
36 *
37 * @param integer $id The identifier of the wordpress version (@unused).
38 */
39 public function __construct($id = null)
40 {
41
42 }
43
44 /**
45 * Used to keep a single instance of the object.
46 *
47 * @return self The class singleton.
48 */
49 public static function getInstance()
50 {
51 if (static::$instance === null)
52 {
53 static::$instance = new static();
54 }
55
56 return static::$instance;
57 }
58
59 /**
60 * Backward compatibility for admin list <table> class.
61 *
62 * @return string The class selector to use.
63 */
64 public function getAdminTableClass()
65 {
66 return 'wp-list-table widefat fixed striped';
67 }
68
69 /**
70 * Backward compatibility for admin list <table> head opening.
71 *
72 * @return string The <thead> tag to use.
73 */
74 public function openTableHead()
75 {
76 return '<thead>';
77 }
78
79 /**
80 * Backward compatibility for admin list <table> head closing.
81 *
82 * @return string The </thead> tag to use.
83 */
84 public function closeTableHead()
85 {
86 return '</thead>';
87 }
88
89 /**
90 * Backward compatibility for admin list <th> class.
91 *
92 * @param string $h_align The additional class to use for horizontal alignment.
93 * Accepted rules should be: left, center or right.
94 *
95 * @return string The class selector to use.
96 */
97 public function getAdminThClass($h_align = 'center')
98 {
99 return 'manage-column ' . $h_align;
100 }
101
102 /**
103 * Backward compatibility for admin list checkAll JS event.
104 *
105 * @param integer $count The total count of rows in the table.
106 *
107 * @return string The check all checkbox input to use.
108 */
109 public function getAdminToggle($count)
110 {
111 return '<input type="checkbox" onclick="Joomla.checkAll(this)" value="" name="checkall-toggle" />';
112 }
113
114 /**
115 * Backward compatibility for admin list isChecked JS event.
116 *
117 * @return string The JS function to use.
118 */
119 public function checkboxOnClick()
120 {
121 return 'Joomla.isChecked(this.checked);';
122 }
123
124 /**
125 * Includes a script framework.
126 *
127 * @param string $fw The framework name.
128 *
129 * @return void
130 */
131 public function loadFramework($fw)
132 {
133 JHtml::fetch($fw);
134 }
135
136 /**
137 * Includes a script URI.
138 *
139 * @param string $uri The script URI.
140 *
141 * @return void
142 */
143 public function addScript($uri)
144 {
145 JHtml::fetch('script', $uri);
146 }
147
148 /**
149 * Helper method to send e-mails.
150 *
151 * @param string $from_address The e-mail address of the sender.
152 * @param string $from_name The name of the sender.
153 * @param string $to The e-mail address of the receiver.
154 * @param string $reply_address The reply to e-mail address.
155 * @param string $subject The subject of the e-mail.
156 * @param string $hmess The body of the e-mail (HTML is supported).
157 * @param array $attachments The list of the attachments to include.
158 * @param boolean $is_html True to support HTML body, otherwise false for plain text.
159 * @param string $encoding The encoding to use.
160 *
161 * @return boolean True if the e-mail was sent successfully, otherwise false.
162 */
163 public function sendMail($from_address, $from_name, $to, $reply_address, $subject, $hmess, $attachments = null, $is_html = true, $encoding = 'base64')
164 {
165 // $subject = '=?UTF-8?B?' . base64_encode($subject) . '?=';
166
167 if ($is_html)
168 {
169 $hmess = "<html>\n<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"></head>\n<body>{$hmess}</body>\n</html>";
170 }
171
172 $mailer = JFactory::getMailer();
173 $sender = array($from_address, $from_name);
174 $mailer->setSender($sender);
175 $mailer->addRecipient($to);
176 $mailer->addReplyTo($reply_address);
177 $mailer->setSubject($subject);
178 $mailer->setBody($hmess);
179 $mailer->isHTML($is_html);
180 $mailer->Encoding = $encoding;
181
182 if ($attachments !== null)
183 {
184 if (!is_array($attachments))
185 {
186 $attachments = array($attachments);
187 }
188
189 foreach ($attachments as $attach)
190 {
191 if (!empty($attach) && file_exists($attach))
192 {
193 $mailer->addAttachment($attach);
194 }
195 }
196 }
197
198 return $mailer->Send();
199 }
200
201 /**
202 * Backward compatibility for punycode conversion.
203 *
204 * @param string $mail The e-mail to convert in punycode.
205 *
206 * @return string The punycode conversion of the e-mail.
207 */
208 public function emailToPunycode($email = '')
209 {
210 return $email;
211 }
212
213 /**
214 * Helper method to build a tiny YES/NO radio button.
215 *
216 * @param string $name The name of the input.
217 * @param object $elem_1 The first input object.
218 * @param object $elem_2 The second input object.
219 * @param boolean wrapped True if the input is wrapped in a control class, otherwise false..
220 *
221 * @return string The html to display.
222 */
223 public function radioYesNo($name, $elem_1, $elem_2, $wrapped = true, $layout = null)
224 {
225 /**
226 * @todo
227 */
228
229 return '';
230 }
231
232 /**
233 * Backward compatibility for fieldset opening.
234 *
235 * @param string $legend The title of the fieldset.
236 * @param string $class The class attribute for the fieldset.
237 * @param string $id The ID attribute for the fieldset.
238 *
239 * @return string The html to display.
240 */
241 public function openFieldset($legend, $class = '', $id = '')
242 {
243 $data = array();
244 $data['name'] = $legend;
245 $data['class'] = $class;
246 $data['id'] = $id;
247
248 return JHtml::fetch('layoutfile', 'html.form.fieldset.open')->render($data);
249 }
250
251 /**
252 * Backward compatibility for fieldset closing.
253 *
254 * @return string The html to display.
255 */
256 public function closeFieldset()
257 {
258 return JHtml::fetch('layoutfile', 'html.form.fieldset.close')->render();
259 }
260
261 /**
262 * Backward compatibility for empty fieldset opening.
263 *
264 * @param string $class An additional class to use for the fieldset.
265 * @param string $id The ID attribute for the fieldset.
266 *
267 * @return string The html to display.
268 */
269 public function openEmptyFieldset($class = '', $id = '')
270 {
271 return $this->openFieldset('', $class, $id);
272 }
273
274 /**
275 * Backward compatibility for empty fieldset opening.
276 *
277 * @return string The html to display.
278 */
279 public function closeEmptyFieldset()
280 {
281 return $this->closeFieldset();
282 }
283
284 /**
285 * Backward compatibility for control opening.
286 *
287 * @param string $label The label of the control field.
288 * @param string $class The class of the control field.
289 * @param array $attr The additional attributes to add.
290 *
291 * @return string The html to display.
292 */
293 public function openControl($label, $class = '', $attr = array())
294 {
295 $data = array();
296
297 foreach ($attr as $k => $v)
298 {
299 $data[$k] = $v;
300 }
301
302 $data['label'] = $label;
303 $data['class'] = $class;
304
305 return JHtml::fetch('layoutfile', 'html.form.control.open')->render($data);
306 }
307
308 /**
309 * Backward compatibility for control closing.
310 *
311 * @return string The html to display.
312 */
313 public function closeControl()
314 {
315 return JHtml::fetch('layoutfile', 'html.form.control.close')->render();
316 }
317
318 /**
319 * Returns the codemirror editor in 3.x, otherwise a simple textarea.
320 *
321 * @param string $name The name of the textarea.
322 * @param string $value The value of the textarea.
323 *
324 * @return string The html to display.
325 */
326 public function getCodeMirror($name, $value)
327 {
328 return '<textarea name="' . $name . '" style="width: 100%;height: 520px;">' . $value . '</textarea>';
329 }
330
331 /**
332 * Backward compatibility for Bootstrap tabset opening.
333 *
334 * @param string $group The group of the tabset.
335 * @param string $attr The attributes to use.
336 *
337 * @return string The html to display.
338 */
339 public function bootStartTabSet($group, $attr = array())
340 {
341 /**
342 * @todo
343 */
344
345 return '';
346 }
347
348 /**
349 * Backward compatibility for Bootstrap tabset closing.
350 *
351 * @return string The html to display.
352 */
353 public function bootEndTabSet()
354 {
355 /**
356 * @todo
357 */
358
359 return '';
360 }
361
362 /**
363 * Backward compatibility for Bootstrap add tab.
364 *
365 * @param string $group The tabset parent group.
366 * @param string $id The id of the tab.
367 * @param string $label The title of the tab.
368 *
369 * @return string The html to display.
370 */
371 public function bootAddTab($group, $id, $label)
372 {
373 /**
374 * @todo
375 */
376
377 return '';
378 }
379
380 /**
381 * Backward compatibility for Bootstrap end tab.
382 *
383 * @return string The html to display.
384 */
385 public function bootEndTab()
386 {
387 /**
388 * @todo
389 */
390
391 return '';
392 }
393
394 /**
395 * Backward compatibility for Bootstrap open modal JS event.
396 *
397 * @param string $onclose The javascript function to call on close event.
398 *
399 * @return string The javascript function.
400 */
401 public function bootOpenModalJS($onclose = '')
402 {
403 /**
404 * @todo
405 */
406
407 return '';
408 }
409
410 /**
411 * Backward compatibility for Bootstrap dismiss modal JS event.
412 *
413 * @param string $selector The selector to identify the modal box.
414 *
415 * @return string The javascript function.
416 */
417 public function bootDismissModalJS($selector)
418 {
419 /**
420 * @todo
421 */
422
423 return '';
424 }
425
426 /**
427 * Returns the HTML used to render a Bootstrap modal.
428 *
429 * @param string $id The modal ID.
430 * @param string $title The modal title.
431 * @param string $body The modal body (if static HTML).
432 * @param mixed $options An array of attributes or the inline style string.
433 *
434 * @return string The modal HTML.
435 */
436 public function getJModalHtml($id, $title, $body = '', $options = null)
437 {
438 if (is_array($options))
439 {
440 $width = isset($options['width']) ? abs($options['width']) : 90;
441 $height = isset($options['height']) ? abs($options['height']) : 80;
442 $left = isset($options['left']) ? abs($options['left']) : $width / 2;
443
444 $style = "width:$width%;height:$height%;margin-left:-$left%;";
445
446 if (isset($options['top']))
447 {
448 if ($options['top'] === true)
449 {
450 $top = (100 - $height) / 2;
451 }
452 else
453 {
454 $top = $options['top'];
455 }
456
457 $style .= "top:$top%;";
458 }
459 }
460 else if (is_string($options))
461 {
462 $style = $options;
463 }
464 else
465 {
466 $style = "width:90%;height:80%;margin-left:-45%";
467 }
468
469 $options = array();
470 $options['id'] = $id;
471 $options['title'] = $title;
472 $options['body'] = $body;
473 $options['style'] = $style;
474
475 $layout = new JLayoutFile('html.plugins.modal', null, array('component' => 'com_vikbooking'));
476
477 return $layout->render($options);
478 }
479
480 /**
481 * Adds javascript support for Bootstrap popovers.
482 *
483 * @param string $selector Selector for the popover.
484 * @param array $options An array of options for the popover.
485 * Options for the popover can be:
486 * animation boolean apply a css fade transition to the popover
487 * html boolean Insert HTML into the popover. If false, jQuery's text method will be used to insert
488 * content into the dom.
489 * placement string|function how to position the popover - top | bottom | left | right
490 * selector string If a selector is provided, popover objects will be delegated to the specified targets.
491 * trigger string how popover is triggered - hover | focus | manual
492 * title string|function default title value if `title` tag isn't present
493 * content string|function default content value if `data-content` attribute isn't present
494 * delay number|object delay showing and hiding the popover (ms) - does not apply to manual trigger type
495 * If a number is supplied, delay is applied to both hide/show
496 * Object structure is: delay: { show: 500, hide: 100 }
497 * container string|boolean Appends the popover to a specific element: { container: 'body' }
498 */
499 public function attachPopover($selector = '.wpPopover', array $options = array())
500 {
501 static $loaded = array();
502
503 $sign = serialize(array($selector, $options));
504
505 if (!isset($loaded[$sign]))
506 {
507 $options['sanitize'] = false;
508 $data = $options ? json_encode($options) : '{}';
509 JFactory::getDocument()->addScriptDeclaration(
510 <<<JS
511 jQuery(function() {
512 jQuery('$selector').popover($data);
513 });
514 JS
515 );
516
517 $loaded[$sign] = 1;
518 }
519 }
520
521 /**
522 * Creates a standard tag and attach a popover event.
523 * NOTE. FontAwesome framework MUST be loaded in order to work.
524 *
525 * @param array $options An array of options for the popover.
526 *
527 * @return string The popover HTML.
528 *
529 * @uses _popover()
530 * @see attachPopover() for further details about options keys.
531 */
532 public function createPopover(array $options = array())
533 {
534 $icon = isset($options['icon_class']) ? $options['icon_class'] : 'fas fa-question-circle';
535
536 $icon = isset($options['icon']) ? 'fas fa-'.$options['icon'] : $icon;
537
538 $template = "<i class=\"{$icon} wp-quest-popover\" {popover}></i>";
539
540 return $this->_popover($template, $options);
541 }
542
543 /**
544 * Creates a text span and attach a popover event.
545 *
546 * @param array $options An array of options for the popover.
547 *
548 * @return string The popover HTML.
549 *
550 * @uses _popover()
551 * @see attachPopover() for further details about options keys.
552 */
553 public function textPopover(array $options = array())
554 {
555 $title = isset($options['title']) ? $options['title'] : '[MISSING TITLE]';
556 $template = "<span class=\"inline-popover wp-quest-popover\" {popover}>{$title}</span>";
557
558 return $this->_popover($template, $options);
559 }
560
561 /**
562 * Creates a popover using the provided template.
563 *
564 * @param string $template The popover template.
565 * @param array $options An array of options for the popover.
566 *
567 * @return string The popover HTML.
568 *
569 * @see attachPopover() for further details about options keys.
570 */
571 protected function _popover($template, array $options)
572 {
573 $layout = new JLayoutFile('html.plugins.popover', null, array('component' => 'com_vikbooking'));
574
575 $options['html'] = true;
576 $options['title'] = isset($options['title']) ? $options['title'] : '';
577 $options['content'] = isset($options['content']) ? $options['content'] : '';
578 $options['trigger'] = isset($options['trigger']) ? $options['trigger'] : 'hover focus';
579 $options['placement'] = isset($options['placement']) ? $options['placement'] : 'right';
580 $options['template'] = isset($options['template']) ? $options['template'] : $layout->render();
581
582 // attach an empty array option so that the data will be recovered
583 // directly from the tag during the runtime
584 $this->attachPopover(".wp-quest-popover", array());
585
586 $attr = '';
587 foreach ($options as $k => $v)
588 {
589 $attr .= "data-{$k}=\"" . str_replace('"', '&quot;', $v) . "\" ";
590 }
591
592 return str_replace('{popover}', $attr, $template);
593 }
594
595 /**
596 * Return the WP date format specs.
597 *
598 * @param string $format The format to use.
599 *
600 * @return string The adapted date format.
601 */
602 public function jdateFormat($format = null)
603 {
604 // strip % from date format string, which was required in Joomla
605 return str_replace('%', '', $format);
606 }
607
608 /**
609 * Provides support to handle the wordpress calendar across different frameworks.
610 *
611 * @param string $value The date to fill.
612 * @param string $name The input name.
613 * @param string $id The input id attribute.
614 * @param string $format The date format.
615 * @param array $attributes Some attributes to use.
616 *
617 * @return string The calendar field.
618 */
619 public function calendar($value, $name, $id = null, $format = null, array $attributes = array())
620 {
621 $format = $this->jdateFormat($format);
622
623 JHtml::fetch('behavior.calendar');
624
625 return JHtml::fetch('calendar', $value, $name, $id, $format, $attributes);
626 }
627
628 /**
629 * Returns a masked e-mail address. The e-mail are masked using
630 * a technique to encode the bytes in hexadecimal representation.
631 * The chunk of the masked e-mail will be also encoded to be HTML readable.
632 *
633 * @param string $email The e-mail to mask.
634 * @param boolean $reverse True to reverse the e-mail address.
635 * Only if the e-mail is not contained into an attribute.
636 *
637 * @return string The masked e-mail address.
638 */
639 public function maskMail($email, $reverse = false)
640 {
641 if ($reverse)
642 {
643 // reverse the e-mail address
644 $email = strrev($email);
645 }
646
647 // converts the e-mail address from bin to hex
648 $email = bin2hex($email);
649 // append ;&#x sequence after every chunk of the masked e-mail
650 $email = chunk_split($email, 2, ";&#x");
651 // prepend &#x sequence before the address and trim the ending sequence
652 $email = "&#x" . substr($email, 0, -3);
653
654 return $email;
655 }
656
657 /**
658 * Returns a safemail tag to avoid the bots spoof a plain address.
659 *
660 * @param string $email The e-mail address to mask.
661 * @param boolean $mail_to True if the address should be wrapped
662 * within a "mailto" link.
663 *
664 * @return string The HTML tag containing the masked address.
665 *
666 * @uses maskMail()
667 */
668 public function safeMailTag($email, $mail_to = false)
669 {
670 // include the CSS declaration to reverse the text contained in the <safemail> tags
671 JFactory::getDocument()->addStyleDeclaration('safemail {direction: rtl;unicode-bidi: bidi-override;}');
672
673 // mask the reversed e-mail address
674 $masked = $this->maskMail($email, true);
675
676 // include the address into a custom <safemail> tag
677 $tag = "<safemail>$masked</safemail>";
678
679 if ($mail_to)
680 {
681 // mask the address for mailto command (do not use reverse)
682 $mailto = $this->maskMail($email);
683
684 // wrap the safemail tag within a mailto link
685 $tag = "<a href=\"mailto:$mailto\" class=\"mailto\">$tag</a>";
686 }
687
688 return $tag;
689 }
690
691 /**
692 * Returns the list of all the installed languages.
693 *
694 * @return array The installed languages.
695 */
696 public function getKnownLanguages()
697 {
698 /**
699 * Use JLanguage::getKnownLanguages() native method.
700 *
701 * @since 1.1.4
702 */
703 return JLanguage::getKnownLanguages();
704 }
705
706 /**
707 * Returns the HTML code to display a toggle button in iOS style through a checkbox element.
708 *
709 * @param string $name the checkbox element name.
710 * @param string $label_yes label for the checked status.
711 * @param string $label_no label for the un-checked status.
712 * @param string $cur_value the default checkbox value state.
713 * @param string $yes_value the checkbox value when checked.
714 * @param string $no_value the checkbox value when un-checked (unsupported).
715 * @param string $onclick optional onclick attribute to fire a JS callback.
716 * @param array $class_list optional list of additional CSS classes to add ('blue', 'orange', 'red', 'gold', 'purple').
717 *
718 *
719 * @return string The HTML code to render the radio buttons.
720 *
721 * @since 1.16.9 (J) - 1.6.9 (WP) introduced argument $class_list.
722 */
723 public function printYesNoButtons($name, $label_yes, $label_no, $cur_value = '1', $yes_value = '1', $no_value = '0', $onclick = '', $class_list = [])
724 {
725 $html = '';
726
727 /**
728 * Normalize ID attribute for checkbox.
729 *
730 * @since 1.8.8
731 */
732 $id_yes = preg_replace("/[^a-z0-9_]+/", '-', $name . '-on');
733
734 /**
735 * New toggle button in iOS style.
736 *
737 * @since 1.3.0
738 */
739 $show_labels = ($label_yes != JText::translate('JYES') && $label_yes != JText::translate('VBYES'));
740 $html = '<span class="vik-iostoggle-wrap vbo-iostoggle-wrap' . ($class_list ? ' ' . implode(' ', $class_list) : '') . '">
741 <input type="checkbox" name="' . $name . '" class="vik-iostoggle-elem vbo-iostoggle-elem" id="' . $id_yes . '" value="' . $yes_value . '"' . (!empty($onclick) ? ' onclick="' . $onclick . '"' : '') . ($cur_value === $yes_value ? ' checked' : '').'>
742 <label for="' . $id_yes . '">' . ($show_labels ? '<span class="vik-iostoggle-lbls vbo-iostoggle-lbls" data-on="' . addslashes($label_yes) . '" data-off="' . addslashes($label_no) . '"></span>' : '') . '</label>
743 </span>';
744
745 return $html;
746 }
747
748 /**
749 * Returns the HTML code for displaying an input field for a phone number.
750 * Adds to the documents the necessary style, script and JS code.
751 *
752 * @param array $attrs array of attributes for the input field.
753 * @param array $opts array of options for the input field.
754 * @param bool $load_assets whether to load the CSS/JS assets.
755 *
756 * @return string the plain HTML code to be printed for the input field.
757 *
758 * @since 1.3.0
759 * @since 1.6.0 added argument $load_assets
760 */
761 public function printPhoneInputField($attrs = array(), $opts = array(), $load_assets = true)
762 {
763 if (!empty($attrs['id'])) {
764 $selector = $attrs['id'];
765 } elseif (!empty($attrs['name'])) {
766 $selector = $attrs['name'];
767 } else {
768 $selector = time() . rand();
769 }
770
771 // input default's attributes
772 $default_attrs = array(
773 'type' => 'tel',
774 'name' => (!empty($attrs['name']) ? $attrs['name'] : $selector),
775 'id' => $selector,
776 'value' => '',
777 'size' => '30',
778 );
779
780 // merge arguments attributes with the default ones
781 $final_attrs = array_merge($default_attrs, $attrs);
782
783 // format attributes
784 $attrs_cont = array();
785 foreach ($final_attrs as $k => $v) {
786 array_push($attrs_cont, "{$k}=\"{$v}\"");
787 }
788
789 /**
790 * Get the preferred countries with correct ordering.
791 *
792 * @wponly if multiple plugins are installed, we may have this method defined by another plugin.
793 *
794 * @since 1.3.11
795 */
796 $preferred_countries = array();
797 $plugin_name = str_replace('com_', '', JFactory::getApplication()->input->getString('option', ''));
798 if (!empty($plugin_name) && class_exists($plugin_name) && method_exists($plugin_name, 'preferredCountriesOrdering')) {
799 $preferred_countries = $plugin_name::preferredCountriesOrdering();
800 } elseif (class_exists('VikBooking')) {
801 $preferred_countries = VikBooking::preferredCountriesOrdering();
802 }
803 //
804
805 // build default config object properties
806 $default_opts = array(
807 'nationalMode' => true,
808 'preferredCountries' => $preferred_countries,
809 'formatOnDisplay' => true,
810 'utilsScript' => VBO_SITE_URI . 'resources/intlTelInput_utils.js',
811 /**
812 * This option is not a valid property of intlTelInput plugin.
813 * If set to true, when the input gets blurred, the full phone
814 * number inclusive of prefix will be immediately replaced and
815 * set into the selector input field. Defaults to false when
816 * the form containing the input field gets submitted. It should
817 * be set to true when the form does not get submitted.
818 */
819 'fullNumberOnBlur' => false,
820 /**
821 * Allow to dispatch an event to transport the selected country data.
822 *
823 * @since 1.18.8 (J) - 1.8.8 (WP)
824 */
825 'countryDataEvent' => null,
826 );
827
828 // merge config object with user's specified properties
829 $final_opts = array_merge($default_opts, $opts);
830 $data = json_encode($final_opts);
831
832 // apply set full number on blur
833 $full_number_on_blur = (int) $final_opts['fullNumberOnBlur'];
834
835 // check if an event should be dispatched with the selected country data
836 $countryDataEvent = $final_opts['countryDataEvent'] ? json_encode($final_opts['countryDataEvent']) : 0;
837
838 $document = JFactory::getDocument();
839
840 if ($load_assets) {
841 $document->addStyleSheet(VBO_SITE_URI . 'resources/intlTelInput.css');
842 $document->addScript(VBO_SITE_URI . 'resources/intlTelInput.js');
843 }
844
845 $render_script = <<<JS
846 jQuery(function() {
847 jQuery('#$selector').intlTelInput($data);
848 jQuery('#$selector').on('blur', function() {
849 // set or format phone number on blur
850 var cur_phone = jQuery('#$selector').intlTelInput('getNumber');
851 if (!cur_phone || !cur_phone.length) {
852 return;
853 }
854 if ($full_number_on_blur) {
855 jQuery('#$selector').val(cur_phone);
856 } else {
857 jQuery('#$selector').intlTelInput('setNumber', cur_phone);
858 }
859 if ($countryDataEvent && typeof VBOCore !== 'undefined') {
860 let countryData = jQuery('#$selector').intlTelInput('getSelectedCountryData');
861 if (countryData && countryData?.iso2) {
862 VBOCore.emitEvent($countryDataEvent, countryData);
863 }
864 }
865 });
866 jQuery('#$selector').closest('form').on('submit', function() {
867 // always make sure the input field contains the complete phone number
868 jQuery('#$selector').val(jQuery('#$selector').intlTelInput('getNumber'));
869 });
870 jQuery('#$selector').on('vboupdatephonenumber', function(e, country) {
871 if (country && country.length == 2 && !jQuery('#$selector').val().length) {
872 jQuery('#$selector').intlTelInput('setCountry', country.toLowerCase());
873 }
874 // make sure the input field contains the complete phone number
875 jQuery('#$selector').val(jQuery('#$selector').intlTelInput('getNumber'));
876 });
877 });
878 JS;
879
880 $node_elem = '<input ' . implode(' ', $attrs_cont) . ' />';
881
882 if ($load_assets) {
883 $document->addScriptDeclaration($render_script);
884 } else {
885 $node_elem .= "<script>{$render_script}</script>";
886 }
887
888 return $node_elem;
889 }
890 }
891 }
892