File "permissions.php"

Full Path: /home/romayxjt/public_html/wp-content/plugins/vikbooking/admin/layouts/operators/permissions.php
File size: 24.57 KB
MIME-type: text/x-php
Charset: utf-8

<?php
/**
 * @package     VikBooking
 * @subpackage  com_vikbooking
 * @author      Alessio Gaggii - E4J srl
 * @copyright   Copyright (C) 2024 E4J srl. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 * @link        https://vikwp.com
 */

defined('ABSPATH') or die('No script kiddies please!');

/**
 * Obtain vars from arguments received in the layout file.
 * It is possible to manage either all tool permissions for
 * one operator, or the permissions of one tool for all operators.
 * It is eventually allowed to manage one tool for one operator,
 * but it is NOT possible to manage all tools for all operators.
 * 
 * @var string  $tool 	       Optional tool type (i.e. "tableaux").
 * @var int     $operator_id   Optional operator ID.
 * @var string  $toggle_event  Optional JS event name to toggle the modal.
 */
extract($displayData);

// define the tool to manage and/or the operator ID
$tool        = $tool ?? null;
$operator_id = $operator_id ?? null;

// js event to toggle the modal window
$toggle_event  = $toggle_event ?? 'vbo-tool-permissions-modal-toggle';
$loading_event = 'vbo-tool-permissions-modal-loading';
$dismiss_event = 'vbo-tool-permissions-modal-dismiss';

// language definitions
JText::script('VBOPERMSOPERATORS');
JText::script('VBO_WANT_PROCEED');
JText::script('VBSAVE');
JText::script('VBO_PLEASE_SELECT');

// access the global operators object
$oper_obj = VikBooking::getOperatorInstance();

// get the permission types for the request tool, or for all tools
$permission_types = $oper_obj->getToolPermissionTypes($tool);

if (!$permission_types || (!$tool && !$operator_id)) {
    // invalid layout setup, abort
    return;
}

if ($tool) {
    // always convert the permission types into an associative list of tools-permissions
    $permission_types = [$tool => $permission_types];
}

// check if we should load the details of one exact operator ID or all
$operator        = [];
$operators_list  = [];
$operators_assoc = [];

if ($operator_id) {
    $operator = $oper_obj->getOne($operator_id);
    if (!$operator) {
        // abort
        VBOHttpDocument::getInstance()->close(404, 'Operator not found');
    }
} else {
    // load all the operators
    $operators_list = $oper_obj->getAll();
    foreach ($operators_list as $operator_info) {
        $operators_assoc[$operator_info['id']] = implode(' ', array_filter([$operator_info['first_name'], $operator_info['last_name']]));
    }
}

?>

<div class="vbo-operator-tool-permissions-container" style="display: none;">
    <div class="vbo-operator-tool-permissions-wrap">
        <div class="vbo-operator-tools-list">
            <div class="vbo-operator-tool-tab vbo-operator-tool-tab-activeperms vbo-operator-tool-tab-active" data-tool-id="">
                <span class="vbo-operator-tool-name"><?php echo JText::translate('VBO_ACTIVE_PERMS'); ?></span>
            </div>
        <?php
        foreach ($permission_types as $tool_id => $tool_data) {
            ?>
            <div class="vbo-operator-tool-tab" data-tool-id="<?php echo JHtml::fetch('esc_attr', $tool_id); ?>">
                <span class="vbo-operator-tool-name"><?php echo $tool_data['name']; ?></span>
            </div>
            <?php
        }
        ?>
        </div>
        <div class="vbo-operator-tools-permissions">
            <div class="vbo-operator-tool-permissions vbo-operator-tool-permissions-activeperms" data-tool-id="">
                <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">
                    <div class="vbo-params-wrap">
                        <div class="vbo-params-container">
                    <?php
                    if ($operator_id) {
                        // display the active permissions for the current operator
                        foreach ($operator['perms'] as $tool_perms) {
                            $tool_name = $oper_obj->getToolName($tool_perms['type']);
                            ?>
                            <div class="vbo-params-block">
                                <div class="vbo-param-container">
                                    <div class="vbo-param-label">
                                        <span class="label label-info"><?php echo $tool_name; ?></span>
                                    </div>
                                    <div class="vbo-param-setting">
                                        <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>
                                        <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>
                                    </div>
                                </div>
                            </div>
                            <?php
                        }
                        if (!$operator['perms']) {
                            ?>
                            <p class="info"><?php echo JText::translate('VBO_NO_RECORDS_FOUND'); ?></p>
                            <?php
                        }
                    } elseif ($tool) {
                        // display all operators with an active permission for this tool
                        $active_operators = $oper_obj->getOperatorsFromPermissions($tool, $operators_list);
                        foreach ($active_operators as $active_operator) {
                            $operator_tool_perms = json_encode($active_operator['perms']);
                            ?>
                            <div class="vbo-params-block">
                                <div class="vbo-param-container">
                                    <div class="vbo-param-label">
                                        <div class="vbo-customer-info-box">
                                            <div class="vbo-customer-info-box-avatar vbo-customer-avatar-small">
                                                <span>
                                                <?php
                                                if (!empty($active_operator['pic'])) {
                                                    ?>
                                                    <img class="no-click" src="<?php echo strpos($active_operator['pic'], 'http') === 0 ? $active_operator['pic'] : VBO_SITE_URI . 'resources/uploads/' . $active_operator['pic']; ?>" />
                                                    <?php
                                                } else {
                                                    VikBookingIcons::e('user-circle');
                                                }
                                                ?>
                                                </span>
                                            </div>
                                            <div class="vbo-customer-info-box-name">
                                                <a href="index.php?option=com_vikbooking&task=editoperator&cid[]=<?php echo $active_operator['id']; ?>" target="_blank">
                                                    <?php echo implode(' ', array_filter([$active_operator['first_name'], $active_operator['last_name']])); ?>
                                                </a>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="vbo-param-setting">
                                        <input type="hidden" class="vbo-operator-tool-permissions-json" value="<?php echo JHtml::fetch('esc_attr', $operator_tool_perms); ?>" />
                                        <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>
                                        <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>
                                    </div>
                                </div>
                            </div>
                            <?php
                        }
                        if (!$active_operators) {
                            ?>
                            <p class="<?php echo !$operators_list ? 'error' : 'info' ?>"><?php echo JText::translate('VBNOOPERATORS'); ?></p>
                            <?php
                        }
                    }
                    ?>
                        </div>
                    </div>
                </div>
            </div>
        <?php
        foreach ($permission_types as $tool_id => $tool_data) {
            $tool_permissions = ($tool_data['permissions'] ?? []);
            $tool_settings    = [];
            if ($tool) {
                // in case of a single tool being rendered, push the (protected) parameter to choose the operator ID
                $tool_permissions = array_merge([
                    '_operator_id' => [
                        'type'          => 'select',
                        'label'         => JText::translate('VBOOPERATOR'),
                        'help'          => JText::translate('VBOADDOPERATORPERM'),
                        'assets'        => true,
                        'asset_options' => [
                            'placeholder' => '',
                            'allowClear'  => true,
                        ],
                        // do NOT merge or unshift to keep the associative list on numeric keys, use the array union operator instead!
                        'options' => (['' => ''] + $operators_assoc),
                    ],
                ], $tool_permissions);
            } elseif (($operator['perms'] ?? [])) {
                // in case of a single operator and related tools being rendered, populate the existing permissions for each tool
                foreach ($operator['perms'] as $tool_perms) {
                    if (!strcasecmp($tool_perms['type'], $tool_id)) {
                        // operator-tool permissions found
                        $tool_settings = $tool_perms['perms'] ?: [];
                        break;
                    }
                }
            }
            ?>
            <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;">
                <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">
                    <div class="vbo-params-wrap">
                        <div class="vbo-params-container">
                            <?php echo VBOParamsRendering::getInstance($tool_permissions, $tool_settings)->setInputName('tool_perms[' . $tool_id . ']')->getHtml(); ?>
                        </div>
                    </div>
                </div>

                <?php
                // if the current user does not have access to this tool, display a warning
                if ($operator_id && !in_array($tool_id, array_column($operator['perms'], 'type'))): ?>
                    <p class="warn"><?php echo JText::translate('VBO_OPERATOR_NO_TOOL_PERMS'); ?></p>
                <?php endif; ?>
            </div>
            <?php
        }
        ?>
        </div>
    </div>
</div>

<script type="text/javascript">
    // save button handler
    function vboHandleSaveToolPermissions(e) {
        // disable the saving button
        let button = e.target;
        if (button.tagName.toLowerCase() === 'i') {
            button = button.parentNode;
        }
        button.disabled = true;

        // find the active tool-tab
        let active_tab = document.querySelector('.vbo-operator-tool-tab.vbo-operator-tool-tab-active');

        if (!active_tab) {
            // enable the button
            button.disabled = false;

            // dismiss the modal
            VBOCore.emitEvent('<?php echo $toggle_event; ?>');

            // abort (nothing to save)
            return false;
        }

        let tool_id = active_tab.getAttribute('data-tool-id');
        let active_params = document.querySelector('.vbo-operator-tool-permissions[data-tool-id="' + (tool_id || '') + '"]');

        if (!tool_id || !active_params) {
            // enable the button
            button.disabled = false;

            // dismiss the modal
            VBOCore.emitEvent('<?php echo $dismiss_event; ?>');

            // abort (nothing to save)
            return false;
        }

        // detect the saving mode, either one tool for various operators,
        // or various tools for one operator, to match mandatory values.
        let manage_mode = '<?php echo $tool ? 'tool_to_operators' : 'tools_to_operator'; ?>';
        let operator_id = null;

        if (manage_mode === 'tool_to_operators') {
            // one tool for various operators

            // make sure the operator ID param was selected
            operator_id = active_params.querySelector('select[name="tool_perms[tableaux][_operator_id]"]')?.value;
            if (!operator_id) {
                // missing operator
                alert(Joomla.JText._('VBO_PLEASE_SELECT'));

                // enable the button
                button.disabled = false;

                // abort
                return false;
            }
        } else {
            // various tools for one operator
            operator_id = '<?php echo $operator_id; ?>';
        }

        // build the request data object
        let permsData = {};

        // scan all permission params to collect the values
        active_params.querySelectorAll('input, select, textarea').forEach((input_el) => {
            // use a regex to get the proper input name, array values will be supported as long as the value is an array
            let first_rx = new RegExp("^tool_perms\\[" + tool_id + "\\]\\[", 'g');
            let input_name = input_el.getAttribute('name')?.replace(first_rx, '')?.replace(/\]?\[?\]$/, '');
            if (!input_name || input_name === '_operator_id') {
                // invalid or protected param field (i.e. select2 helper elements)
                return;
            }

            // get the param value
            let input_value = input_el.value;

            // check if an array, only supported on multiple-select
            if (input_el.tagName.toLowerCase() === 'select' && input_el.multiple) {
                // start an array
                input_value = [];
                // scan all selected (use ":checked" pseudoselector) options
                input_el.querySelectorAll('option:checked').forEach((opt) => {
                    input_value.push(opt.value);
                });
            }

            // set request property and value
            permsData[input_name] = input_value;
        });

        // start loading and make the request
        VBOCore.emitEvent('<?php echo $loading_event; ?>');

        VBOCore.doAjax(
            "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=operators.savePermission'); ?>",
            {
                operator_id: operator_id,
                tool_id: tool_id,
                perms: permsData,
                tmpl: "component",
            },
            (response) => {
                // stop loading
                VBOCore.emitEvent('<?php echo $loading_event; ?>');

                // dismiss the modal
                VBOCore.emitEvent('<?php echo $dismiss_event; ?>');

                // reload the current page
                window.location.reload();
            },
            (error) => {
                // display error
                alert(error.responseText);

                // stop loading
                VBOCore.emitEvent('<?php echo $loading_event; ?>');

                // enable the button
                button.disabled = false;
            }
        );
    }

    jQuery(function() {

        // handle tool tabs switching
        jQuery('.vbo-operator-tool-tab').on('click', function(e) {
            let tool_id = jQuery(this).attr('data-tool-id');
            jQuery('.vbo-operator-tool-tab').removeClass('vbo-operator-tool-tab-active');
            jQuery('.vbo-operator-tool-permissions').hide().removeClass('vbo-operator-tool-permissions-active');
            jQuery(this).addClass('vbo-operator-tool-tab-active');
            jQuery('.vbo-operator-tool-permissions[data-tool-id="' + tool_id + '"]').show().addClass('vbo-operator-tool-permissions-active');
            if (tool_id && <?php echo $tool ? 'true' : 'false'; ?>) {
                // when clicking a tool-tab during the tool permissions management, reset the current operator id and other fields
                if (jQuery(e.target).hasClass('vbo-operator-tool-name')) {
                    // not a JS event triggered, but a real click on this tool-tab
                    let container = jQuery('.vbo-operator-tool-permissions[data-tool-id="' + tool_id + '"]');
                    container.find('select[name="tool_perms[' + tool_id + '][_operator_id]"]').find('option:checked').prop('selected', false);
                    container.find('select[name="tool_perms[' + tool_id + '][_operator_id]"]').trigger('change');
                    // reset additional fields
                    container.find('input, textarea').val('').trigger('change');
                    container.find('select[multiple]').find('option:checked').prop('selected', false);
                    container.find('select[multiple]').trigger('change');
                }
            }
        });

        // handle button to edit the tool permissions for a specific operator
        jQuery('.vbo-oper-permissions-edit-btn').on('click', function() {
            let operator_id = jQuery(this).attr('data-operator-id');
            let tool_id = jQuery(this).attr('data-tool-id');
            let oper_tool_perms_json = jQuery(this).parent().find('input.vbo-operator-tool-permissions-json').val();

            if (!operator_id || !tool_id) {
                return false;
            }

            // attempt to decode the current operator tool permissions
            let oper_tool_perms = {};
            try {
                oper_tool_perms = oper_tool_perms_json ? JSON.parse(oper_tool_perms_json) : {};
            } catch(err) {
                oper_tool_perms = {};
                console.error('could not parse JSON permissions', err, oper_tool_perms_json);
            }

            // scan all tool permission fields
            document.querySelector('.vbo-operator-tool-permissions[data-tool-id="' + tool_id + '"]').querySelectorAll('input, select, textarea').forEach((input_el) => {
                let first_rx = new RegExp("^tool_perms\\[" + tool_id + "\\]\\[", 'g');
                let input_name = input_el.getAttribute('name')?.replace(first_rx, '')?.replace(/\]?\[?\]$/, '');

                if (!input_name) {
                    // invalid param field (i.e. select2 helper elements)
                    return;
                }

                if (input_name === '_operator_id') {
                    // ensure to populate the operator ID
                    (input_el.querySelector('option[value="' + operator_id + '"]') || {}).selected = true;

                    // trigger the element change event
                    input_el.dispatchEvent(new Event('change'));

                    // parse next
                    return;
                }

                if (oper_tool_perms.hasOwnProperty(input_name)) {
                    if (Array.isArray(oper_tool_perms[input_name])) {
                        // multiple values
                        oper_tool_perms[input_name].forEach((cur_value) => {
                            (input_el.querySelector('option[value="' + cur_value + '"]') || {}).selected = true;
                        });
                    } else {
                        // single value
                        input_el.value = oper_tool_perms[input_name];
                    }
                } else {
                    // reset this setting to the initial empty state

                    // check if an array, only supported on multiple-select
                    if (input_el.tagName.toLowerCase() === 'select' && input_el.multiple) {
                        // scan all selected (use ":checked" pseudoselector) options
                        input_el.querySelectorAll('option:checked').forEach((opt) => {
                            // un-select this option
                            opt.selected = false;
                        });
                    } else {
                        input_el.value = '';
                    }
                }

                // trigger the element change event
                input_el.dispatchEvent(new Event('change'));
            });

            // trigger the event to open the requested tool tab
            jQuery('.vbo-operator-tool-tab[data-tool-id="' + tool_id + '"]').trigger('click');
        });

        // handle button to edit the operator permissions for a specific tool
        jQuery('.vbo-tool-permissions-edit-btn').on('click', function() {
            let operator_id = jQuery(this).attr('data-operator-id');
            let tool_id = jQuery(this).attr('data-tool-id');

            // trigger the event to open the requested tool tab
            jQuery('.vbo-operator-tool-tab[data-tool-id="' + tool_id + '"]').trigger('click');

            // we do not really need to inject or populate the fields, because they must have been populated already
        });

        // handle button to remove an operator-tool-permission
        jQuery('.vbo-permissions-del-btn').on('click', function() {
            if (!confirm(Joomla.JText._('VBO_WANT_PROCEED'))) {
                return false;
            }

            let operator_id = jQuery(this).attr('data-operator-id');
            let tool_id = jQuery(this).attr('data-tool-id');

            let element = jQuery(this).closest('.vbo-params-block');

            // start loading and make the request
            VBOCore.emitEvent('<?php echo $loading_event; ?>');

            VBOCore.doAjax(
                "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=operators.removePermission'); ?>",
                {
                    operator_id: operator_id,
                    tool_id: tool_id,
                    tmpl: "component"
                },
                (response) => {
                    // stop loading
                    VBOCore.emitEvent('<?php echo $loading_event; ?>');
                    
                    // delete the element from the DOM
                    element.remove();
                },
                (error) => {
                    console.error(error);
                    alert(error.responseText);
                    // stop loading
                    VBOCore.emitEvent('<?php echo $loading_event; ?>');
                }
            );
        });

        // build footer save button
        const permissionsButtonSave = document.createElement('button');
        permissionsButtonSave.classList.add('btn', 'btn-success');
        permissionsButtonSave.setAttribute('type', 'button');
        permissionsButtonSave.innerHTML = '<?php VikBookingIcons::e('save'); ?> ' + Joomla.JText._('VBSAVE');
        permissionsButtonSave.addEventListener('click', vboHandleSaveToolPermissions);

        // handle modal toggle (show/hide)
        document.addEventListener('<?php echo $toggle_event; ?>', () => {
            // always enable the footer saving button
            permissionsButtonSave.disabled = false;

            // render modal
            let modalBody = VBOCore.displayModal({
                suffix: 'operator_permissions_modal',
                extra_class: 'vbo-modal-rounded vbo-modal-tall',
                title: Joomla.JText._('VBOPERMSOPERATORS'),
                body_prepend: true,
                lock_scroll: true,
                footer_right: permissionsButtonSave,
                loading_event: '<?php echo $loading_event; ?>',
                dismiss_event: '<?php echo $dismiss_event; ?>',
                onDismiss: () => {
                    // move modal content back
                    jQuery('.vbo-operator-tool-permissions-wrap').appendTo(jQuery('.vbo-operator-tool-permissions-container'));
                }
            });

            // set modal content
            jQuery('.vbo-operator-tool-permissions-wrap').appendTo(modalBody);
        });

    });
</script>