PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.7
VikBooking Hotel Booking Engine & PMS v1.8.7
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 / admin / helpers / widgets / operators_chat.php

operators_chat.php in VikBooking Hotel Booking Engine & PMS 1.8.7, at admin/helpers/widgets/operators_chat.php

264 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - E4J srl
6 * @copyright Copyright (C) 2025 E4J srl. 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 * Class handler for admin widget "operators chat".
15 *
16 * @since 1.18.0 (J) - 1.8.0 (WP)
17 */
18 class VikBookingAdminWidgetOperatorsChat extends VikBookingAdminWidget
19 {
20 /**
21 * The instance counter of this widget.
22 *
23 * @var int
24 */
25 protected static $instance_counter = -1;
26
27 /**
28 * Class constructor will define the widget name and identifier.
29 */
30 public function __construct()
31 {
32 // call parent constructor
33 parent::__construct();
34
35 $this->widgetName = JText::translate('VBO_W_OPERATORSCHAT_TITLE');
36 $this->widgetDescr = JText::translate('VBO_W_OPERATORSCHAT_DESCR');
37 $this->widgetId = basename(__FILE__, '.php');
38
39 $this->widgetIcon = '<i class="' . VikBookingIcons::i('comments') . '"></i>';
40 $this->widgetStyleName = 'light-red';
41 }
42
43 /**
44 * Beside loading the necessary assets, this widget preloads the
45 * ID of the latest message for the administrators in order to
46 * watch the new messages received and to be able to trigger notifications.
47 *
48 * @return ?object
49 */
50 public function preload()
51 {
52 // get the chat mediator
53 $chat = VBOFactory::getChatMediator();
54
55 // preload chat assets
56 $chat->useAssets();
57
58 // get the latest message(s) for the administrators
59 $messages = $chat->getMessages(
60 (new VBOChatSearch)
61 ->sender(0, false)
62 ->limit(1)
63 );
64
65 if ($messages) {
66 $watch_data = [
67 'message_id' => $messages[0]->getID(),
68 ];
69
70 // return the data to watch for notifications
71 return (object) $watch_data;
72 }
73
74 return null;
75 }
76
77 /**
78 * Checks for new notifications by using the previous preloaded watch-data.
79 *
80 * @param ?VBONotificationWatchdata $watch_data The preloaded watch-data object.
81 *
82 * @return array Data object to watch next and notifications array.
83 *
84 * @see preload()
85 */
86 public function getNotifications(?VBONotificationWatchdata $watch_data = null)
87 {
88 // default empty values
89 $watch_next = null;
90 $notifications = null;
91
92 if (!$watch_data) {
93 return [$watch_next, $notifications];
94 }
95
96 $latest_message_id = (int) $watch_data->get('message_id', 0);
97 if (!$latest_message_id) {
98 return [$watch_next, $notifications];
99 }
100
101 // get the latest message for the administrators
102 $messages = VBOFactory::getChatMediator()->getMessages(
103 (new VBOChatSearch)
104 ->aggregate()
105 ->sender(0, false)
106 // search only the messages newer than the latest ID
107 ->message($latest_message_id, '>')
108 ->limit(3)
109 );
110
111 if (!$messages) {
112 return [$watch_next, $notifications];
113 }
114
115 // build the next watch data for this widget
116 $watch_next = new stdClass;
117 $watch_next->message_id = $messages[0]->getID();
118
119 // compose the notification(s) to dispatch
120 $notifications = VBONotificationScheduler::getInstance()->buildOperatorsChatDataObjects($messages);
121
122 return [$watch_next, $notifications];
123 }
124
125 /**
126 * @inheritDoc
127 */
128 public function getWidgetDetails()
129 {
130 // get common widget details from parent abstract class
131 $details = parent::getWidgetDetails();
132
133 // append the modal rendering information
134 $details['modal'] = [
135 'add_class' => 'vbo-modal-large',
136 ];
137
138 return $details;
139 }
140
141 /**
142 * @inheritDoc
143 */
144 public function render(?VBOMultitaskData $data = null)
145 {
146 // increase widget's instance counter
147 static::$instance_counter++;
148
149 // check whether the widget is being rendered via AJAX when adding it through the customizer
150 $is_ajax = $this->isAjaxRendering();
151
152 // generate a unique ID for the widget wrapper instance
153 $wrapper_instance = !$is_ajax ? static::$instance_counter : rand();
154 $wrapper_id = 'vbo-widget-operators-chat-' . $wrapper_instance;
155
156 // get the chat mediator
157 $chat = VBOFactory::getChatMediator();
158
159 // multitask data event identifier for clearing intervals
160 $js_intvals_id = '';
161 $chat_context = null;
162 if ($data && $data->isModalRendering()) {
163 // access Multitask data
164 $js_intvals_id = $data->getModalJsIdentifier();
165
166 // access context alias and id, if any
167 $context_alias = $data->get('context_alias', '') ?: $this->options()->get('context_alias', '');
168 $context_id = $data->get('context_id', 0) ?: $this->options()->get('context_id', 0);
169
170 if ($context_alias && $context_id) {
171 // build chat for the given context
172 $chat_context = $chat->createContext($context_alias, $context_id);
173 }
174 }
175
176 /**
177 * @see Keep the inline styling on the HTML elements for the JS functions to work properly.
178 */
179 ?>
180 <div id="<?php echo $wrapper_id; ?>" class="vbo-admin-widget-wrapper" style="height: 100%;">
181 <div class="vbo-admin-widget-head" style="border-bottom: 0;">
182 <div class="vbo-admin-widget-head-inline">
183 <h4 style="padding: 7px;"><?php echo $this->widgetIcon; ?> <span><?php echo $this->widgetName; ?></span></h4>
184 </div>
185 </div>
186 <?php
187 if ($chat_context) {
188 // display the chat for the identified context
189 echo $chat->render($chat_context, [
190 'assets' => false,
191 ]);
192 } else {
193 // display the chat for all threads
194
195 // take all the threads where the administrator is involved
196 $threads = $chat->getMessages(
197 (new VBOChatSearch)
198 ->aggregate()
199 ->reader($chat->getUser()->getID())
200 ->limit(20)
201 );
202
203 if ($threads) {
204 // render chat threads
205 echo JLayoutHelper::render('chat.threads', [
206 'threads' => $threads,
207 'options' => [
208 'dateformat' => str_replace('/', $this->datesep, $this->df),
209 'limit' => 20,
210 'compact' => true,
211 ],
212 ]);
213 } else {
214 // render the blank layout
215 echo JLayoutHelper::render('chat.blank', []);
216 }
217 }
218 ?>
219 </div>
220
221 <script>
222 (function($) {
223 'use strict';
224
225 <?php if ($js_intvals_id): ?>
226 $(function() {
227 /**
228 * Register callback function for the widget "resize" event (modal only)
229 */
230 const resize_fn = (e) => {
231 const modalContent = $('#<?php echo $wrapper_id; ?>');
232
233 if (modalContent.width() <= 940) {
234 modalContent.find('.vbo-chat-interface').addClass('compact');
235 } else {
236 modalContent.find('.vbo-chat-interface').removeClass('compact');
237 }
238 };
239
240 // add listener for the modal dismissed event
241 document.addEventListener(VBOCore.widget_modal_dismissed + '<?php echo $js_intvals_id; ?>', (e) => {
242 // get rid of widget resizing events
243 document.removeEventListener('vbo-resize-widget-modal<?php echo $js_intvals_id; ?>', resize_fn);
244 document.removeEventListener('vbo-admin-dock-restore-<?php echo $this->getIdentifier(); ?>', resize_fn);
245 window.removeEventListener('resize', resize_fn);
246
247 // destroy the chat
248 if (typeof VBOChat !== 'undefined') {
249 VBOChat.getInstance().destroy();
250 }
251 }, {once: true});
252
253 // register widget resizing events
254 document.addEventListener('vbo-resize-widget-modal<?php echo $js_intvals_id; ?>', resize_fn);
255 document.addEventListener('vbo-admin-dock-restore-<?php echo $this->getIdentifier(); ?>', resize_fn);
256 window.addEventListener('resize', resize_fn);
257 });
258 <?php endif; ?>
259 })(jQuery);
260 </script>
261 <?php
262 }
263 }
264