PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.7.1
VikBooking Hotel Booking Engine & PMS v1.7.1
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 / layouts / operators / permissions.php

permissions.php in VikBooking Hotel Booking Engine & PMS 1.7.1, at admin/layouts/operators/permissions.php

526 lines 24.2 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) 2024 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 * Obtain vars from arguments received in the layout file.
15 * It is possible to manage either all tool permissions for
16 * one operator, or the permissions of one tool for all operators.
17 * It is eventually allowed to manage one tool for one operator,
18 * but it is NOT possible to manage all tools for all operators.
19 *
20 * @var string $tool Optional tool type (i.e. "tableaux").
21 * @var int $operator_id Optional operator ID.
22 * @var string $toggle_event Optional JS event name to toggle the modal.
23 */
24 extract($displayData);
25
26 // define the tool to manage and/or the operator ID
27 $tool = $tool ?? null;
28 $operator_id = $operator_id ?? null;
29
30 // js event to toggle the modal window
31 $toggle_event = $toggle_event ?? 'vbo-tool-permissions-modal-toggle';
32 $loading_event = 'vbo-tool-permissions-modal-loading';
33 $dismiss_event = 'vbo-tool-permissions-modal-dismiss';
34
35 // language definitions
36 JText::script('VBOPERMSOPERATORS');
37 JText::script('VBO_WANT_PROCEED');
38 JText::script('VBSAVE');
39 JText::script('VBO_PLEASE_SELECT');
40
41 // access the global operators object
42 $oper_obj = VikBooking::getOperatorInstance();
43
44 // get the permission types for the request tool, or for all tools
45 $permission_types = $oper_obj->getToolPermissionTypes($tool);
46
47 if (!$permission_types || (!$tool && !$operator_id)) {
48 // invalid layout setup, abort
49 return;
50 }
51
52 if ($tool) {
53 // always convert the permission types into an associative list of tools-permissions
54 $permission_types = [$tool => $permission_types];
55 }
56
57 // check if we should load the details of one exact operator ID or all
58 $operator = [];
59 $operators_list = [];
60 $operators_assoc = [];
61
62 if ($operator_id) {
63 $operator = $oper_obj->getOne($operator_id);
64 if (!$operator) {
65 // abort
66 VBOHttpDocument::getInstance()->close(404, 'Operator not found');
67 }
68 } else {
69 // load all the operators
70 $operators_list = $oper_obj->getAll();
71 foreach ($operators_list as $operator_info) {
72 $operators_assoc[$operator_info['id']] = implode(' ', array_filter([$operator_info['first_name'], $operator_info['last_name']]));
73 }
74 }
75
76 ?>
77
78 <div class="vbo-operator-tool-permissions-container" style="display: none;">
79 <div class="vbo-operator-tool-permissions-wrap">
80 <div class="vbo-operator-tools-list">
81 <div class="vbo-operator-tool-tab vbo-operator-tool-tab-activeperms vbo-operator-tool-tab-active" data-tool-id="">
82 <span class="vbo-operator-tool-name"><?php echo JText::translate('VBO_ACTIVE_PERMS'); ?></span>
83 </div>
84 <?php
85 foreach ($permission_types as $tool_id => $tool_data) {
86 ?>
87 <div class="vbo-operator-tool-tab" data-tool-id="<?php echo JHtml::fetch('esc_attr', $tool_id); ?>">
88 <span class="vbo-operator-tool-name"><?php echo $tool_data['name']; ?></span>
89 </div>
90 <?php
91 }
92 ?>
93 </div>
94 <div class="vbo-operator-tools-permissions">
95 <div class="vbo-operator-tool-permissions vbo-operator-tool-permissions-activeperms" data-tool-id="">
96 <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">
97 <div class="vbo-params-wrap">
98 <div class="vbo-params-container">
99 <?php
100 if ($operator_id) {
101 // display the active permissions for the current operator
102 foreach ($operator['perms'] as $tool_perms) {
103 $tool_name = $oper_obj->getToolName($tool_perms['type']);
104 ?>
105 <div class="vbo-params-block">
106 <div class="vbo-param-container">
107 <div class="vbo-param-label">
108 <span class="label label-info"><?php echo $tool_name; ?></span>
109 </div>
110 <div class="vbo-param-setting">
111 <button type="button" class="btn vbo-tool-permissions-edit-btn" data-operator-id="<?php echo $operator['id']; ?>" data-tool-id="<?php echo $tool_perms['type']; ?>"><?php VikBookingIcons::e('edit'); ?> <?php echo JText::translate('VBMAINPAYMENTSEDIT'); ?></button>
112 <button type="button" class="btn btn-danger vbo-permissions-del-btn" data-operator-id="<?php echo $operator['id']; ?>" data-tool-id="<?php echo $tool_perms['type']; ?>"><?php VikBookingIcons::e('times'); ?> <?php echo JText::translate('VBELIMINA'); ?></button>
113 </div>
114 </div>
115 </div>
116 <?php
117 }
118 if (!$operator['perms']) {
119 ?>
120 <p class="info"><?php echo JText::translate('VBO_NO_RECORDS_FOUND'); ?></p>
121 <?php
122 }
123 } elseif ($tool) {
124 // display all operators with an active permission for this tool
125 $active_operators = $oper_obj->getOperatorsFromPermissions($tool, $operators_list);
126 foreach ($active_operators as $active_operator) {
127 $operator_tool_perms = json_encode($active_operator['perms']);
128 ?>
129 <div class="vbo-params-block">
130 <div class="vbo-param-container">
131 <div class="vbo-param-label">
132 <div class="vbo-customer-info-box">
133 <div class="vbo-customer-info-box-avatar vbo-customer-avatar-small">
134 <span>
135 <?php
136 if (!empty($active_operator['pic'])) {
137 ?>
138 <img class="no-click" src="<?php echo strpos($active_operator['pic'], 'http') === 0 ? $active_operator['pic'] : VBO_SITE_URI . 'resources/uploads/' . $active_operator['pic']; ?>" />
139 <?php
140 } else {
141 VikBookingIcons::e('user-circle');
142 }
143 ?>
144 </span>
145 </div>
146 <div class="vbo-customer-info-box-name">
147 <a href="index.php?option=com_vikbooking&task=editoperator&cid[]=<?php echo $active_operator['id']; ?>" target="_blank">
148 <?php echo implode(' ', array_filter([$active_operator['first_name'], $active_operator['last_name']])); ?>
149 </a>
150 </div>
151 </div>
152 </div>
153 <div class="vbo-param-setting">
154 <input type="hidden" class="vbo-operator-tool-permissions-json" value="<?php echo JHtml::fetch('esc_attr', $operator_tool_perms); ?>" />
155 <button type="button" class="btn vbo-oper-permissions-edit-btn" data-operator-id="<?php echo $active_operator['id']; ?>" data-tool-id="<?php echo $tool; ?>"><?php VikBookingIcons::e('edit'); ?> <?php echo JText::translate('VBMAINPAYMENTSEDIT'); ?></button>
156 <button type="button" class="btn btn-danger vbo-permissions-del-btn" data-operator-id="<?php echo $active_operator['id']; ?>" data-tool-id="<?php echo $tool; ?>"><?php VikBookingIcons::e('times'); ?> <?php echo JText::translate('VBELIMINA'); ?></button>
157 </div>
158 </div>
159 </div>
160 <?php
161 }
162 if (!$active_operators) {
163 ?>
164 <p class="<?php echo !$operators_list ? 'error' : 'info' ?>"><?php echo JText::translate('VBNOOPERATORS'); ?></p>
165 <?php
166 }
167 }
168 ?>
169 </div>
170 </div>
171 </div>
172 </div>
173 <?php
174 foreach ($permission_types as $tool_id => $tool_data) {
175 $tool_permissions = ($tool_data['permissions'] ?? []);
176 $tool_settings = [];
177 if ($tool) {
178 // in case of a single tool being rendered, push the (protected) parameter to choose the operator ID
179 $tool_permissions = array_merge([
180 '_operator_id' => [
181 'type' => 'select',
182 'label' => JText::translate('VBOOPERATOR'),
183 'help' => JText::translate('VBOADDOPERATORPERM'),
184 'assets' => true,
185 'asset_options' => [
186 'placeholder' => '',
187 'allowClear' => true,
188 ],
189 // do NOT merge or unshift to keep the associative list on numeric keys, use the array union operator instead!
190 'options' => (['' => ''] + $operators_assoc),
191 ],
192 ], $tool_permissions);
193 } elseif (($operator['perms'] ?? [])) {
194 // in case of a single operator and related tools being rendered, populate the existing permissions for each tool
195 foreach ($operator['perms'] as $tool_perms) {
196 if (!strcasecmp($tool_perms['type'], $tool_id)) {
197 // operator-tool permissions found
198 $tool_settings = $tool_perms['perms'] ?: [];
199 break;
200 }
201 }
202 }
203 ?>
204 <div class="vbo-operator-tool-permissions vbo-operator-tool-tab-selector" data-tool-id="<?php echo JHtml::fetch('esc_attr', $tool_id); ?>" style="display: none;">
205 <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">
206 <div class="vbo-params-wrap">
207 <div class="vbo-params-container">
208 <?php echo VBOParamsRendering::getInstance($tool_permissions, $tool_settings)->setInputName('tool_perms[' . $tool_id . ']')->getHtml(); ?>
209 </div>
210 </div>
211 </div>
212 </div>
213 <?php
214 }
215 ?>
216 </div>
217 </div>
218 </div>
219
220 <script type="text/javascript">
221 // save button handler
222 function vboHandleSaveToolPermissions(e) {
223 // disable the saving button
224 let button = e.target;
225 if (button.tagName.toLowerCase() === 'i') {
226 button = button.parentNode;
227 }
228 button.disabled = true;
229
230 // find the active tool-tab
231 let active_tab = document.querySelector('.vbo-operator-tool-tab.vbo-operator-tool-tab-active');
232
233 if (!active_tab) {
234 // enable the button
235 button.disabled = false;
236
237 // dismiss the modal
238 VBOCore.emitEvent('<?php echo $toggle_event; ?>');
239
240 // abort (nothing to save)
241 return false;
242 }
243
244 let tool_id = active_tab.getAttribute('data-tool-id');
245 let active_params = document.querySelector('.vbo-operator-tool-permissions[data-tool-id="' + (tool_id || '') + '"]');
246
247 if (!tool_id || !active_params) {
248 // enable the button
249 button.disabled = false;
250
251 // dismiss the modal
252 VBOCore.emitEvent('<?php echo $dismiss_event; ?>');
253
254 // abort (nothing to save)
255 return false;
256 }
257
258 // detect the saving mode, either one tool for various operators,
259 // or various tools for one operator, to match mandatory values.
260 let manage_mode = '<?php echo $tool ? 'tool_to_operators' : 'tools_to_operator'; ?>';
261 let operator_id = null;
262
263 if (manage_mode === 'tool_to_operators') {
264 // one tool for various operators
265
266 // make sure the operator ID param was selected
267 operator_id = active_params.querySelector('select[name="tool_perms[tableaux][_operator_id]"]')?.value;
268 if (!operator_id) {
269 // missing operator
270 alert(Joomla.JText._('VBO_PLEASE_SELECT'));
271
272 // enable the button
273 button.disabled = false;
274
275 // abort
276 return false;
277 }
278 } else {
279 // various tools for one operator
280 operator_id = '<?php echo $operator_id; ?>';
281 }
282
283 // build the request data object
284 let permsData = {};
285
286 // scan all permission params to collect the values
287 active_params.querySelectorAll('input, select, textarea').forEach((input_el) => {
288 // use a regex to get the proper input name, array values will be supported as long as the value is an array
289 let first_rx = new RegExp("^tool_perms\\[" + tool_id + "\\]\\[", 'g');
290 let input_name = input_el.getAttribute('name')?.replace(first_rx, '')?.replace(/\]?\[?\]$/, '');
291 if (!input_name || input_name === '_operator_id') {
292 // invalid or protected param field (i.e. select2 helper elements)
293 return;
294 }
295
296 // get the param value
297 let input_value = input_el.value;
298
299 // check if an array, only supported on multiple-select
300 if (input_el.tagName.toLowerCase() === 'select' && input_el.multiple) {
301 // start an array
302 input_value = [];
303 // scan all selected (use ":checked" pseudoselector) options
304 input_el.querySelectorAll('option:checked').forEach((opt) => {
305 input_value.push(opt.value);
306 });
307 }
308
309 // set request property and value
310 permsData[input_name] = input_value;
311 });
312
313 // start loading and make the request
314 VBOCore.emitEvent('<?php echo $loading_event; ?>');
315
316 VBOCore.doAjax(
317 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=operators.savePermission'); ?>",
318 {
319 operator_id: operator_id,
320 tool_id: tool_id,
321 perms: permsData,
322 tmpl: "component",
323 },
324 (response) => {
325 // stop loading
326 VBOCore.emitEvent('<?php echo $loading_event; ?>');
327
328 // dismiss the modal
329 VBOCore.emitEvent('<?php echo $dismiss_event; ?>');
330
331 // reload the current page
332 window.location.reload();
333 },
334 (error) => {
335 // display error
336 alert(error.responseText);
337
338 // stop loading
339 VBOCore.emitEvent('<?php echo $loading_event; ?>');
340
341 // enable the button
342 button.disabled = false;
343 }
344 );
345 }
346
347 jQuery(function() {
348
349 // handle tool tabs switching
350 jQuery('.vbo-operator-tool-tab').on('click', function(e) {
351 let tool_id = jQuery(this).attr('data-tool-id');
352 jQuery('.vbo-operator-tool-tab').removeClass('vbo-operator-tool-tab-active');
353 jQuery('.vbo-operator-tool-permissions').hide().removeClass('vbo-operator-tool-permissions-active');
354 jQuery(this).addClass('vbo-operator-tool-tab-active');
355 jQuery('.vbo-operator-tool-permissions[data-tool-id="' + tool_id + '"]').show().addClass('vbo-operator-tool-permissions-active');
356 if (tool_id && <?php echo $tool ? 'true' : 'false'; ?>) {
357 // when clicking a tool-tab during the tool permissions management, reset the current operator id and other fields
358 if (jQuery(e.target).hasClass('vbo-operator-tool-name')) {
359 // not a JS event triggered, but a real click on this tool-tab
360 let container = jQuery('.vbo-operator-tool-permissions[data-tool-id="' + tool_id + '"]');
361 container.find('select[name="tool_perms[' + tool_id + '][_operator_id]"]').find('option:checked').prop('selected', false);
362 container.find('select[name="tool_perms[' + tool_id + '][_operator_id]"]').trigger('change');
363 // reset additional fields
364 container.find('input, textarea').val('').trigger('change');
365 container.find('select[multiple]').find('option:checked').prop('selected', false);
366 container.find('select[multiple]').trigger('change');
367 }
368 }
369 });
370
371 // handle button to edit the tool permissions for a specific operator
372 jQuery('.vbo-oper-permissions-edit-btn').on('click', function() {
373 let operator_id = jQuery(this).attr('data-operator-id');
374 let tool_id = jQuery(this).attr('data-tool-id');
375 let oper_tool_perms_json = jQuery(this).parent().find('input.vbo-operator-tool-permissions-json').val();
376
377 if (!operator_id || !tool_id) {
378 return false;
379 }
380
381 // attempt to decode the current operator tool permissions
382 let oper_tool_perms = {};
383 try {
384 oper_tool_perms = oper_tool_perms_json ? JSON.parse(oper_tool_perms_json) : {};
385 } catch(err) {
386 oper_tool_perms = {};
387 console.error('could not parse JSON permissions', err, oper_tool_perms_json);
388 }
389
390 // scan all tool permission fields
391 document.querySelector('.vbo-operator-tool-permissions[data-tool-id="' + tool_id + '"]').querySelectorAll('input, select, textarea').forEach((input_el) => {
392 let first_rx = new RegExp("^tool_perms\\[" + tool_id + "\\]\\[", 'g');
393 let input_name = input_el.getAttribute('name')?.replace(first_rx, '')?.replace(/\]?\[?\]$/, '');
394
395 if (!input_name) {
396 // invalid param field (i.e. select2 helper elements)
397 return;
398 }
399
400 if (input_name === '_operator_id') {
401 // ensure to populate the operator ID
402 (input_el.querySelector('option[value="' + operator_id + '"]') || {}).selected = true;
403
404 // trigger the element change event
405 input_el.dispatchEvent(new Event('change'));
406
407 // parse next
408 return;
409 }
410
411 if (oper_tool_perms.hasOwnProperty(input_name)) {
412 if (Array.isArray(oper_tool_perms[input_name])) {
413 // multiple values
414 oper_tool_perms[input_name].forEach((cur_value) => {
415 (input_el.querySelector('option[value="' + cur_value + '"]') || {}).selected = true;
416 });
417 } else {
418 // single value
419 input_el.value = oper_tool_perms[input_name];
420 }
421 } else {
422 // reset this setting to the initial empty state
423
424 // check if an array, only supported on multiple-select
425 if (input_el.tagName.toLowerCase() === 'select' && input_el.multiple) {
426 // scan all selected (use ":checked" pseudoselector) options
427 input_el.querySelectorAll('option:checked').forEach((opt) => {
428 // un-select this option
429 opt.selected = false;
430 });
431 } else {
432 input_el.value = '';
433 }
434 }
435
436 // trigger the element change event
437 input_el.dispatchEvent(new Event('change'));
438 });
439
440 // trigger the event to open the requested tool tab
441 jQuery('.vbo-operator-tool-tab[data-tool-id="' + tool_id + '"]').trigger('click');
442 });
443
444 // handle button to edit the operator permissions for a specific tool
445 jQuery('.vbo-tool-permissions-edit-btn').on('click', function() {
446 let operator_id = jQuery(this).attr('data-operator-id');
447 let tool_id = jQuery(this).attr('data-tool-id');
448
449 // trigger the event to open the requested tool tab
450 jQuery('.vbo-operator-tool-tab[data-tool-id="' + tool_id + '"]').trigger('click');
451
452 // we do not really need to inject or populate the fields, because they must have been populated already
453 });
454
455 // handle button to remove an operator-tool-permission
456 jQuery('.vbo-permissions-del-btn').on('click', function() {
457 if (!confirm(Joomla.JText._('VBO_WANT_PROCEED'))) {
458 return false;
459 }
460
461 let operator_id = jQuery(this).attr('data-operator-id');
462 let tool_id = jQuery(this).attr('data-tool-id');
463
464 let element = jQuery(this).closest('.vbo-params-block');
465
466 // start loading and make the request
467 VBOCore.emitEvent('<?php echo $loading_event; ?>');
468
469 VBOCore.doAjax(
470 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=operators.removePermission'); ?>",
471 {
472 operator_id: operator_id,
473 tool_id: tool_id,
474 tmpl: "component"
475 },
476 (response) => {
477 // stop loading
478 VBOCore.emitEvent('<?php echo $loading_event; ?>');
479
480 // delete the element from the DOM
481 element.remove();
482 },
483 (error) => {
484 console.error(error);
485 alert(error.responseText);
486 // stop loading
487 VBOCore.emitEvent('<?php echo $loading_event; ?>');
488 }
489 );
490 });
491
492 // build footer save button
493 const permissionsButtonSave = document.createElement('button');
494 permissionsButtonSave.classList.add('btn', 'btn-success');
495 permissionsButtonSave.setAttribute('type', 'button');
496 permissionsButtonSave.innerHTML = '<?php VikBookingIcons::e('save'); ?> ' + Joomla.JText._('VBSAVE');
497 permissionsButtonSave.addEventListener('click', vboHandleSaveToolPermissions);
498
499 // handle modal toggle (show/hide)
500 document.addEventListener('<?php echo $toggle_event; ?>', () => {
501 // always enable the footer saving button
502 permissionsButtonSave.disabled = false;
503
504 // render modal
505 let modalBody = VBOCore.displayModal({
506 suffix: 'operator_permissions_modal',
507 extra_class: 'vbo-modal-rounded vbo-modal-tall',
508 title: Joomla.JText._('VBOPERMSOPERATORS'),
509 body_prepend: true,
510 lock_scroll: true,
511 footer_right: permissionsButtonSave,
512 loading_event: '<?php echo $loading_event; ?>',
513 dismiss_event: '<?php echo $dismiss_event; ?>',
514 onDismiss: () => {
515 // move modal content back
516 jQuery('.vbo-operator-tool-permissions-wrap').appendTo(jQuery('.vbo-operator-tool-permissions-container'));
517 }
518 });
519
520 // set modal content
521 jQuery('.vbo-operator-tool-permissions-wrap').appendTo(modalBody);
522 });
523
524 });
525 </script>
526