This commit refactors the access control logic to replace references to 'inscriptions_mobile' with 'inscriptions_gestion', aligning the permission structure with the new management system. Changes include updates to SQL scripts, PHP functions, and documentation comments to ensure consistency in permission handling for event management. This enhances clarity and maintains the integrity of the access control system.
625 lines
27 KiB
PHP
625 lines
27 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Super admin — gestion des kits d'acces v2 (roles + matrice permissions).
|
|
*/
|
|
|
|
require_once dirname(__DIR__, 2) . '/php/inc_fx_eve_acces.php';
|
|
|
|
function fxEveAccesAdminHasDelegableColumn()
|
|
{
|
|
global $objDatabase;
|
|
|
|
static $blnHas = null;
|
|
if ($blnHas !== null) {
|
|
return $blnHas;
|
|
}
|
|
|
|
if (!fxEveAccesIsEnabled()) {
|
|
$blnHas = false;
|
|
return $blnHas;
|
|
}
|
|
|
|
$tab = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_eve_roles LIKE 'role_delegable'");
|
|
$blnHas = ($tab != null && count($tab) > 0);
|
|
|
|
return $blnHas;
|
|
}
|
|
|
|
function fxEveAccesAdminPermGroupLabels()
|
|
{
|
|
return array(
|
|
'api' => 'API mobile',
|
|
'inscriptions' => 'Inscriptions',
|
|
'dossards' => 'Dossards',
|
|
'epreuves' => 'Épreuves',
|
|
'rabais' => 'Rabais',
|
|
'emails' => 'Courriels',
|
|
'reports' => 'Rapports',
|
|
'team' => 'Équipe',
|
|
'tools' => 'Outils',
|
|
'action' => 'Actions mobile',
|
|
'general' => 'Général',
|
|
);
|
|
}
|
|
|
|
function fxEveAccesAdminNormalizeRoleCode($strCode)
|
|
{
|
|
$strCode = strtolower(trim((string)$strCode));
|
|
$strCode = preg_replace('/[^a-z0-9_]+/', '_', $strCode);
|
|
$strCode = preg_replace('/_+/', '_', $strCode);
|
|
$strCode = trim($strCode, '_');
|
|
|
|
return substr($strCode, 0, 32);
|
|
}
|
|
|
|
function fxEveAccesAdminRoleCodeExists($strCode, $intExcludeRoleId = 0)
|
|
{
|
|
global $objDatabase;
|
|
|
|
$sql = "SELECT COUNT(*) FROM inscriptions_eve_roles
|
|
WHERE role_code = '" . $objDatabase->fxEscape($strCode) . "'";
|
|
if (intval($intExcludeRoleId) > 0) {
|
|
$sql .= ' AND role_id <> ' . intval($intExcludeRoleId);
|
|
}
|
|
|
|
return intval($objDatabase->fxGetVar($sql)) > 0;
|
|
}
|
|
|
|
function fxEveAccesAdminGetRolesForList($blnActifOnly = false)
|
|
{
|
|
global $objDatabase;
|
|
|
|
if (!fxEveAccesIsEnabled()) {
|
|
return array();
|
|
}
|
|
|
|
$strDelegable = fxEveAccesAdminHasDelegableColumn() ? ', r.role_delegable' : ', 0 AS role_delegable';
|
|
|
|
$sql = "SELECT r.role_id, r.role_code, r.role_label_fr, r.role_label_en,
|
|
r.role_description_fr, r.role_icone, r.role_systeme, r.role_actif, r.role_tri
|
|
{$strDelegable},
|
|
(SELECT COUNT(*) FROM inscriptions_eve_role_permissions erp WHERE erp.role_id = r.role_id) AS perm_count,
|
|
(SELECT COUNT(*) FROM inscriptions_eve_acces ea
|
|
WHERE ea.role_id = r.role_id AND ea.ea_statut = 'actif') AS assign_count
|
|
FROM inscriptions_eve_roles r";
|
|
|
|
if ($blnActifOnly) {
|
|
$sql .= ' WHERE r.role_actif = 1';
|
|
}
|
|
|
|
$sql .= ' ORDER BY r.role_tri ASC, r.role_label_fr ASC';
|
|
|
|
return $objDatabase->fxGetResults($sql);
|
|
}
|
|
|
|
function fxEveAccesAdminGetRoleById($intRoleId)
|
|
{
|
|
global $objDatabase;
|
|
|
|
if (!fxEveAccesIsEnabled() || intval($intRoleId) <= 0) {
|
|
return null;
|
|
}
|
|
|
|
$strDelegable = fxEveAccesAdminHasDelegableColumn() ? ', role_delegable' : ', 0 AS role_delegable';
|
|
|
|
$sql = "SELECT role_id, role_code, role_label_fr, role_label_en,
|
|
role_description_fr, role_description_en, role_icone,
|
|
role_systeme, role_actif, role_tri {$strDelegable}
|
|
FROM inscriptions_eve_roles
|
|
WHERE role_id = " . intval($intRoleId) . "
|
|
LIMIT 1";
|
|
|
|
return $objDatabase->fxGetRow($sql);
|
|
}
|
|
|
|
function fxEveAccesAdminGetRolePermKeys($intRoleId)
|
|
{
|
|
global $objDatabase;
|
|
|
|
if (!fxEveAccesIsEnabled() || intval($intRoleId) <= 0) {
|
|
return array();
|
|
}
|
|
|
|
$sql = "SELECT perm_key FROM inscriptions_eve_role_permissions
|
|
WHERE role_id = " . intval($intRoleId) . "
|
|
ORDER BY perm_key ASC";
|
|
$tab = $objDatabase->fxGetResults($sql);
|
|
$arrKeys = array();
|
|
|
|
if ($tab != null) {
|
|
foreach ($tab as $row) {
|
|
$arrKeys[] = $row['perm_key'];
|
|
}
|
|
}
|
|
|
|
return $arrKeys;
|
|
}
|
|
|
|
function fxEveAccesAdminCountActiveAssignments($intRoleId)
|
|
{
|
|
global $objDatabase;
|
|
|
|
$sql = "SELECT COUNT(*) FROM inscriptions_eve_acces
|
|
WHERE role_id = " . intval($intRoleId) . "
|
|
AND ea_statut = 'actif'";
|
|
|
|
return intval($objDatabase->fxGetVar($sql));
|
|
}
|
|
|
|
function fxEveAccesAdminSaveRole($arrData, $arrPermKeys)
|
|
{
|
|
global $objDatabase;
|
|
|
|
if (!fxEveAccesIsEnabled()) {
|
|
return array('state' => 'error', 'message' => 'Tables acces v2 non installees.');
|
|
}
|
|
|
|
$intRoleId = intval($arrData['role_id'] ?? 0);
|
|
$rowExisting = ($intRoleId > 0) ? fxEveAccesAdminGetRoleById($intRoleId) : null;
|
|
|
|
$strLabelFr = trim((string)($arrData['role_label_fr'] ?? ''));
|
|
$strLabelEn = trim((string)($arrData['role_label_en'] ?? ''));
|
|
if ($strLabelFr === '') {
|
|
return array('state' => 'error', 'message' => 'Le libelle FR est obligatoire.');
|
|
}
|
|
if ($strLabelEn === '') {
|
|
$strLabelEn = $strLabelFr;
|
|
}
|
|
|
|
$strCode = fxEveAccesAdminNormalizeRoleCode($arrData['role_code'] ?? '');
|
|
if ($strCode === '' || !preg_match('/^[a-z][a-z0-9_]{0,31}$/', $strCode)) {
|
|
return array('state' => 'error', 'message' => 'Code invalide (a-z, 0-9, _, min. 2 caracteres).');
|
|
}
|
|
|
|
$blnSysteme = ($rowExisting !== null && intval($rowExisting['role_systeme']) === 1);
|
|
if ($blnSysteme) {
|
|
$strCode = $rowExisting['role_code'];
|
|
} elseif (fxEveAccesAdminRoleCodeExists($strCode, $intRoleId)) {
|
|
return array('state' => 'error', 'message' => 'Ce code de kit existe deja.');
|
|
}
|
|
|
|
$strDescFr = trim((string)($arrData['role_description_fr'] ?? ''));
|
|
$strDescEn = trim((string)($arrData['role_description_en'] ?? ''));
|
|
$strIcone = trim((string)($arrData['role_icone'] ?? ''));
|
|
if ($strIcone !== '' && !preg_match('/^fa-[a-z0-9-]+$/', $strIcone)) {
|
|
$strIcone = '';
|
|
}
|
|
|
|
$intTri = intval($arrData['role_tri'] ?? 0);
|
|
$blnActif = !empty($arrData['role_actif']) ? 1 : 0;
|
|
$blnDelegable = !empty($arrData['role_delegable']) ? 1 : 0;
|
|
if ($blnSysteme && in_array($strCode, array('owner', 'qr_debug'), true)) {
|
|
$blnDelegable = 0;
|
|
}
|
|
|
|
$arrValidKeys = array();
|
|
if (!empty($arrPermKeys)) {
|
|
$arrCatalog = fxEveAccesGetCatalogPermissions(null, true);
|
|
$arrCatalogKeys = array();
|
|
if ($arrCatalog != null) {
|
|
foreach ($arrCatalog as $rowPerm) {
|
|
$arrCatalogKeys[$rowPerm['perm_key']] = true;
|
|
}
|
|
}
|
|
foreach ($arrPermKeys as $strKey) {
|
|
$strKey = trim((string)$strKey);
|
|
if ($strKey !== '' && isset($arrCatalogKeys[$strKey])) {
|
|
$arrValidKeys[$strKey] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($intRoleId > 0 && $rowExisting === null) {
|
|
return array('state' => 'error', 'message' => 'Kit introuvable.');
|
|
}
|
|
|
|
if ($intRoleId <= 0) {
|
|
$sqlInsert = "INSERT INTO inscriptions_eve_roles SET
|
|
role_code = '" . $objDatabase->fxEscape($strCode) . "',
|
|
role_label_fr = '" . $objDatabase->fxEscape($strLabelFr) . "',
|
|
role_label_en = '" . $objDatabase->fxEscape($strLabelEn) . "',
|
|
role_description_fr = " . ($strDescFr !== '' ? "'" . $objDatabase->fxEscape($strDescFr) . "'" : 'NULL') . ",
|
|
role_description_en = " . ($strDescEn !== '' ? "'" . $objDatabase->fxEscape($strDescEn) . "'" : 'NULL') . ",
|
|
role_icone = " . ($strIcone !== '' ? "'" . $objDatabase->fxEscape($strIcone) . "'" : 'NULL') . ",
|
|
role_systeme = 0,
|
|
role_actif = " . intval($blnActif) . ",
|
|
role_tri = " . intval($intTri);
|
|
if (fxEveAccesAdminHasDelegableColumn()) {
|
|
$sqlInsert .= ', role_delegable = ' . intval($blnDelegable);
|
|
}
|
|
$objDatabase->fxQuery($sqlInsert);
|
|
$intRoleId = intval($objDatabase->fxGetVar('SELECT LAST_INSERT_ID()'));
|
|
} else {
|
|
$sqlUpdate = "UPDATE inscriptions_eve_roles SET
|
|
role_code = '" . $objDatabase->fxEscape($strCode) . "',
|
|
role_label_fr = '" . $objDatabase->fxEscape($strLabelFr) . "',
|
|
role_label_en = '" . $objDatabase->fxEscape($strLabelEn) . "',
|
|
role_description_fr = " . ($strDescFr !== '' ? "'" . $objDatabase->fxEscape($strDescFr) . "'" : 'NULL') . ",
|
|
role_description_en = " . ($strDescEn !== '' ? "'" . $objDatabase->fxEscape($strDescEn) . "'" : 'NULL') . ",
|
|
role_icone = " . ($strIcone !== '' ? "'" . $objDatabase->fxEscape($strIcone) . "'" : 'NULL') . ",
|
|
role_actif = " . intval($blnActif) . ",
|
|
role_tri = " . intval($intTri);
|
|
if (fxEveAccesAdminHasDelegableColumn()) {
|
|
$sqlUpdate .= ', role_delegable = ' . intval($blnDelegable);
|
|
}
|
|
$sqlUpdate .= ' WHERE role_id = ' . intval($intRoleId);
|
|
$objDatabase->fxQuery($sqlUpdate);
|
|
}
|
|
|
|
$objDatabase->fxQuery('DELETE FROM inscriptions_eve_role_permissions WHERE role_id = ' . intval($intRoleId));
|
|
foreach (array_keys($arrValidKeys) as $strKey) {
|
|
$objDatabase->fxQuery(
|
|
"INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key)
|
|
VALUES (" . intval($intRoleId) . ", '" . $objDatabase->fxEscape($strKey) . "')"
|
|
);
|
|
}
|
|
|
|
return array(
|
|
'state' => 'ok',
|
|
'message' => 'Kit enregistre.',
|
|
'role_id' => $intRoleId,
|
|
);
|
|
}
|
|
|
|
function fxEveAccesAdminDuplicateRole($intRoleId)
|
|
{
|
|
global $objDatabase;
|
|
|
|
$row = fxEveAccesAdminGetRoleById($intRoleId);
|
|
if ($row === null) {
|
|
return array('state' => 'error', 'message' => 'Kit introuvable.');
|
|
}
|
|
|
|
$strBase = fxEveAccesAdminNormalizeRoleCode($row['role_code'] . '_copy');
|
|
$strCode = $strBase;
|
|
$intSuffix = 2;
|
|
while (fxEveAccesAdminRoleCodeExists($strCode)) {
|
|
$strCode = substr($strBase, 0, 28) . '_' . $intSuffix;
|
|
$intSuffix++;
|
|
}
|
|
|
|
$arrSave = array(
|
|
'role_id' => 0,
|
|
'role_code' => $strCode,
|
|
'role_label_fr' => $row['role_label_fr'] . ' (copie)',
|
|
'role_label_en' => ($row['role_label_en'] !== '' ? $row['role_label_en'] : $row['role_label_fr']) . ' (copy)',
|
|
'role_description_fr' => $row['role_description_fr'] ?? '',
|
|
'role_description_en' => $row['role_description_en'] ?? '',
|
|
'role_icone' => $row['role_icone'] ?? '',
|
|
'role_tri' => intval($row['role_tri']) + 1,
|
|
'role_actif' => 1,
|
|
'role_delegable' => !empty($row['role_delegable']) ? 1 : 0,
|
|
);
|
|
|
|
return fxEveAccesAdminSaveRole($arrSave, fxEveAccesAdminGetRolePermKeys($intRoleId));
|
|
}
|
|
|
|
function fxEveAccesAdminToggleRoleActif($intRoleId)
|
|
{
|
|
global $objDatabase;
|
|
|
|
$row = fxEveAccesAdminGetRoleById($intRoleId);
|
|
if ($row === null) {
|
|
return array('state' => 'error', 'message' => 'Kit introuvable.');
|
|
}
|
|
|
|
$blnNew = intval($row['role_actif']) === 1 ? 0 : 1;
|
|
$objDatabase->fxQuery(
|
|
'UPDATE inscriptions_eve_roles SET role_actif = ' . intval($blnNew)
|
|
. ' WHERE role_id = ' . intval($intRoleId)
|
|
);
|
|
|
|
return array(
|
|
'state' => 'ok',
|
|
'message' => $blnNew ? 'Kit reactive.' : 'Kit desactive.',
|
|
);
|
|
}
|
|
|
|
function fxEveAccesAdminRenderKitsList($strFlash = '')
|
|
{
|
|
if (!fxEveAccesIsEnabled()) {
|
|
echo '<div class="alert alert-warning">Tables acces v2 non installees. Executer les SQL MSIN-eve-acces-v2-phase1.</div>';
|
|
return;
|
|
}
|
|
|
|
if (!fxEveAccesAdminHasDelegableColumn()) {
|
|
echo '<div class="alert alert-info">Executer <code>sql/MSIN-eve-acces-v2-phase3-role-delegable.sql</code> pour activer le flag « delegable par promoteur ».</div>';
|
|
}
|
|
|
|
$blnActifOnly = isset($_GET['actif']) && $_GET['actif'] === '1';
|
|
$arrRoles = fxEveAccesAdminGetRolesForList($blnActifOnly);
|
|
|
|
if ($strFlash !== '') {
|
|
echo '<div class="alert alert-success">' . htmlspecialchars($strFlash, ENT_QUOTES, 'UTF-8') . '</div>';
|
|
}
|
|
?>
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h1 class="mb-0">Kits d'accès</h1>
|
|
<a class="btn btn-success" href="eve_acces.php?p=kit">
|
|
<i class="fa fa-plus"></i> Nouveau kit
|
|
</a>
|
|
</div>
|
|
<p class="text-muted">
|
|
Un kit regroupe des permissions. Les kits marqués « délégables » pourront être proposés par un promoteur
|
|
lors de l'invitation d'équipe (phase suivante). L'assignation aux comptes se fait sur la fiche compte.
|
|
</p>
|
|
<p>
|
|
<a href="eve_acces.php?p=kits" class="btn btn-sm btn-outline-secondary<?= !$blnActifOnly ? ' active' : '' ?>">Tous</a>
|
|
<a href="eve_acces.php?p=kits&actif=1" class="btn btn-sm btn-outline-secondary<?= $blnActifOnly ? ' active' : '' ?>">Actifs seulement</a>
|
|
</p>
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-sm table-hover mb-0 align-middle">
|
|
<thead class="thead-dark">
|
|
<tr>
|
|
<th class="text-center" style="width:2.5rem" aria-label="Icône"></th>
|
|
<th>Kit</th>
|
|
<th class="text-center text-nowrap" style="width:1%">Perms</th>
|
|
<th class="text-center text-nowrap" style="width:1%">Assign.</th>
|
|
<th class="text-center text-nowrap" style="width:1%">Délég.</th>
|
|
<th class="text-center text-nowrap" style="width:1%">Statut</th>
|
|
<th class="text-right text-nowrap" style="width:1%"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
if ($arrRoles === null || count($arrRoles) === 0) {
|
|
echo '<tr><td colspan="7" class="text-muted">Aucun kit.</td></tr>';
|
|
} else {
|
|
foreach ($arrRoles as $row) {
|
|
$strIcon = trim((string)($row['role_icone'] ?? ''));
|
|
?>
|
|
<tr>
|
|
<td class="text-center text-muted">
|
|
<?php if ($strIcon !== '') { ?>
|
|
<i class="fa fa-lg <?= htmlspecialchars($strIcon, ENT_QUOTES, 'UTF-8') ?>" aria-hidden="true"></i>
|
|
<?php } else { ?>
|
|
<span class="small">–</span>
|
|
<?php } ?>
|
|
</td>
|
|
<td>
|
|
<div class="font-weight-bold"><?= htmlspecialchars($row['role_label_fr'], ENT_QUOTES, 'UTF-8') ?></div>
|
|
<div class="small text-muted font-monospace"><?= htmlspecialchars($row['role_code'], ENT_QUOTES, 'UTF-8') ?></div>
|
|
</td>
|
|
<td class="text-center"><?= intval($row['perm_count']) ?></td>
|
|
<td class="text-center"><?= intval($row['assign_count']) ?></td>
|
|
<td class="text-center"><?= !empty($row['role_delegable']) ? '<span class="badge badge-info">oui</span>' : '<span class="text-muted">—</span>' ?></td>
|
|
<td class="text-center text-nowrap">
|
|
<?php if (intval($row['role_systeme']) === 1) { ?>
|
|
<span class="badge badge-secondary">système</span>
|
|
<?php } ?>
|
|
<?php if (intval($row['role_actif']) === 1) { ?>
|
|
<span class="badge badge-success">actif</span>
|
|
<?php } else { ?>
|
|
<span class="badge badge-warning">inactif</span>
|
|
<?php } ?>
|
|
</td>
|
|
<td class="text-right text-nowrap">
|
|
<a class="btn btn-sm btn-primary" href="eve_acces.php?p=kit&id=<?= intval($row['role_id']) ?>" title="Modifier">
|
|
<i class="fa fa-pencil"></i>
|
|
</a>
|
|
<a class="btn btn-sm btn-secondary" href="eve_acces.php?action=duplicate&id=<?= intval($row['role_id']) ?>"
|
|
title="Dupliquer">
|
|
<i class="fa fa-copy"></i>
|
|
</a>
|
|
<a class="btn btn-sm btn-outline-secondary" href="eve_acces.php?action=toggle&id=<?= intval($row['role_id']) ?>"
|
|
title="<?= intval($row['role_actif']) === 1 ? 'Desactiver' : 'Activer' ?>"
|
|
onclick="return confirm('Changer le statut de ce kit ?');">
|
|
<i class="fa fa-power-off"></i>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
<?php
|
|
}
|
|
}
|
|
?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
function fxEveAccesAdminRenderKitForm($intRoleId, $strError = '')
|
|
{
|
|
if (!fxEveAccesIsEnabled()) {
|
|
echo '<div class="alert alert-warning">Tables acces v2 non installees.</div>';
|
|
return;
|
|
}
|
|
|
|
$row = null;
|
|
$arrSelected = array();
|
|
if ($intRoleId > 0) {
|
|
$row = fxEveAccesAdminGetRoleById($intRoleId);
|
|
if ($row === null) {
|
|
echo '<div class="alert alert-danger">Kit introuvable.</div>';
|
|
return;
|
|
}
|
|
foreach (fxEveAccesAdminGetRolePermKeys($intRoleId) as $strKey) {
|
|
$arrSelected[$strKey] = true;
|
|
}
|
|
}
|
|
|
|
$blnSysteme = ($row !== null && intval($row['role_systeme']) === 1);
|
|
$arrCatalog = fxEveAccesGetCatalogPermissions(null, true);
|
|
$arrByGroup = array();
|
|
if ($arrCatalog != null) {
|
|
foreach ($arrCatalog as $rowPerm) {
|
|
$strGroup = $rowPerm['perm_group'] ?? 'general';
|
|
if (!isset($arrByGroup[$strGroup])) {
|
|
$arrByGroup[$strGroup] = array();
|
|
}
|
|
$arrByGroup[$strGroup][] = $rowPerm;
|
|
}
|
|
}
|
|
$arrGroupLabels = fxEveAccesAdminPermGroupLabels();
|
|
ksort($arrByGroup);
|
|
|
|
if ($strError !== '') {
|
|
echo '<div class="alert alert-danger">' . htmlspecialchars($strError, ENT_QUOTES, 'UTF-8') . '</div>';
|
|
}
|
|
?>
|
|
<div class="mb-3">
|
|
<a href="eve_acces.php?p=kits" class="btn btn-sm btn-outline-secondary">
|
|
<i class="fa fa-chevron-left"></i> Retour à la liste
|
|
</a>
|
|
</div>
|
|
<h1><?= $intRoleId > 0 ? 'Modifier le kit' : 'Nouveau kit' ?></h1>
|
|
|
|
<form method="post" action="eve_acces.php?p=kit<?= $intRoleId > 0 ? '&id=' . intval($intRoleId) : '' ?>">
|
|
<input type="hidden" name="action" value="save_kit">
|
|
<input type="hidden" name="role_id" value="<?= intval($intRoleId) ?>">
|
|
|
|
<div class="card mb-3">
|
|
<div class="card-header">Identité</div>
|
|
<div class="card-body">
|
|
<div class="form-row">
|
|
<div class="form-group col-md-4">
|
|
<label for="role_code">Code <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control" id="role_code" name="role_code" maxlength="32"
|
|
value="<?= htmlspecialchars($row['role_code'] ?? '', ENT_QUOTES, 'UTF-8') ?>"
|
|
<?= $blnSysteme ? 'readonly' : '' ?>
|
|
placeholder="ex. gestion_statut">
|
|
<?php if ($blnSysteme) { ?>
|
|
<small class="text-muted">Code verrouillé (kit système).</small>
|
|
<?php } ?>
|
|
</div>
|
|
<div class="form-group col-md-4">
|
|
<label for="role_label_fr">Libellé FR <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control" id="role_label_fr" name="role_label_fr" maxlength="80"
|
|
value="<?= htmlspecialchars($row['role_label_fr'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
|
</div>
|
|
<div class="form-group col-md-4">
|
|
<label for="role_label_en">Libellé EN</label>
|
|
<input type="text" class="form-control" id="role_label_en" name="role_label_en" maxlength="80"
|
|
value="<?= htmlspecialchars($row['role_label_en'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group col-md-8">
|
|
<label for="role_description_fr">Description FR</label>
|
|
<input type="text" class="form-control" id="role_description_fr" name="role_description_fr" maxlength="255"
|
|
value="<?= htmlspecialchars($row['role_description_fr'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
|
</div>
|
|
<div class="form-group col-md-2">
|
|
<label for="role_icone">Icône FA</label>
|
|
<input type="text" class="form-control" id="role_icone" name="role_icone" maxlength="32"
|
|
placeholder="fa-mobile"
|
|
value="<?= htmlspecialchars($row['role_icone'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
|
</div>
|
|
<div class="form-group col-md-2">
|
|
<label for="role_tri">Ordre</label>
|
|
<input type="number" class="form-control" id="role_tri" name="role_tri" min="0" max="9999"
|
|
value="<?= intval($row['role_tri'] ?? 50) ?>">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group col-md-4">
|
|
<div class="custom-control custom-checkbox mt-2">
|
|
<input type="checkbox" class="custom-control-input" id="role_actif" name="role_actif" value="1"
|
|
<?= ($row === null || intval($row['role_actif']) === 1) ? 'checked' : '' ?>>
|
|
<label class="custom-control-label" for="role_actif">Kit actif (proposable à l'assignation)</label>
|
|
</div>
|
|
</div>
|
|
<?php if (fxEveAccesAdminHasDelegableColumn()) { ?>
|
|
<div class="form-group col-md-8">
|
|
<div class="custom-control custom-checkbox mt-2">
|
|
<input type="checkbox" class="custom-control-input" id="role_delegable" name="role_delegable" value="1"
|
|
<?= !empty($row['role_delegable']) ? 'checked' : '' ?>
|
|
<?= ($blnSysteme && in_array($row['role_code'] ?? '', array('owner', 'qr_debug'), true)) ? 'disabled' : '' ?>>
|
|
<label class="custom-control-label" for="role_delegable">
|
|
Délégable par le promoteur (invitation équipe — phase suivante)
|
|
</label>
|
|
</div>
|
|
<small class="text-muted">Le promoteur pourra assigner ce kit à un membre invité, dans les limites définies par l'admin.</small>
|
|
</div>
|
|
<?php } ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card mb-3">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<span>Permissions incluses</span>
|
|
<span>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" id="btn-perm-all">Tout cocher</button>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="btn-perm-none">Tout décocher</button>
|
|
</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<?php
|
|
foreach ($arrByGroup as $strGroup => $arrPerms) {
|
|
$strGroupLabel = $arrGroupLabels[$strGroup] ?? ucfirst($strGroup);
|
|
$strGroupId = preg_replace('/[^a-z0-9_]/', '_', $strGroup);
|
|
?>
|
|
<div class="border rounded p-3 mb-3 perm-group-block" data-group="<?= htmlspecialchars($strGroupId, ENT_QUOTES, 'UTF-8') ?>">
|
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
<h5 class="mb-0"><?= htmlspecialchars($strGroupLabel, ENT_QUOTES, 'UTF-8') ?></h5>
|
|
<span>
|
|
<button type="button" class="btn btn-xs btn-link btn-group-all p-0 mr-2">Tout</button>
|
|
<button type="button" class="btn btn-xs btn-link btn-group-none p-0">Aucun</button>
|
|
</span>
|
|
</div>
|
|
<div class="row">
|
|
<?php foreach ($arrPerms as $rowPerm) {
|
|
$strKey = $rowPerm['perm_key'];
|
|
$strId = 'perm_' . preg_replace('/[^a-z0-9_]/', '_', $strKey);
|
|
?>
|
|
<div class="col-md-6 col-lg-4 mb-2">
|
|
<div class="custom-control custom-checkbox">
|
|
<input type="checkbox" class="custom-control-input perm-checkbox"
|
|
id="<?= htmlspecialchars($strId, ENT_QUOTES, 'UTF-8') ?>"
|
|
name="perm_keys[]"
|
|
value="<?= htmlspecialchars($strKey, ENT_QUOTES, 'UTF-8') ?>"
|
|
<?= isset($arrSelected[$strKey]) ? 'checked' : '' ?>>
|
|
<label class="custom-control-label" for="<?= htmlspecialchars($strId, ENT_QUOTES, 'UTF-8') ?>">
|
|
<?= htmlspecialchars($rowPerm['perm_label_fr'], ENT_QUOTES, 'UTF-8') ?>
|
|
<br><small class="text-muted"><code><?= htmlspecialchars($strKey, ENT_QUOTES, 'UTF-8') ?></code></small>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
?>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-success">
|
|
<i class="fa fa-save"></i> Enregistrer
|
|
</button>
|
|
</form>
|
|
<script>
|
|
(function () {
|
|
$('#btn-perm-all').on('click', function () {
|
|
$('.perm-checkbox').prop('checked', true);
|
|
});
|
|
$('#btn-perm-none').on('click', function () {
|
|
$('.perm-checkbox').prop('checked', false);
|
|
});
|
|
$('.perm-group-block').each(function () {
|
|
var $block = $(this);
|
|
$block.find('.btn-group-all').on('click', function () {
|
|
$block.find('.perm-checkbox').prop('checked', true);
|
|
});
|
|
$block.find('.btn-group-none').on('click', function () {
|
|
$block.find('.perm-checkbox').prop('checked', false);
|
|
});
|
|
});
|
|
$('#role_label_fr').on('blur', function () {
|
|
var $code = $('#role_code');
|
|
if ($code.length && !$code.prop('readonly') && $.trim($code.val()) === '') {
|
|
var slug = $.trim($(this).val()).toLowerCase()
|
|
.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
|
|
.replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '').substr(0, 32);
|
|
if (slug.length >= 2) {
|
|
$code.val(slug);
|
|
}
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
<?php
|
|
}
|