2187 lines
75 KiB
PHP
2187 lines
75 KiB
PHP
<?php
|
||
|
||
/**
|
||
* Acces evenement v2 — parallele au legacy com_eve_promoteur.
|
||
* Ne modifie jamais les champs legacy.
|
||
*/
|
||
|
||
function fxEveAccesIsEnabled()
|
||
{
|
||
static $blnEnabled = null;
|
||
|
||
global $objDatabase;
|
||
|
||
if (!isset($objDatabase)) {
|
||
return false;
|
||
}
|
||
|
||
if ($blnEnabled !== null) {
|
||
return $blnEnabled;
|
||
}
|
||
|
||
$tab = $objDatabase->fxGetResults("SHOW TABLES LIKE 'inscriptions_eve_acces'");
|
||
$blnEnabled = ($tab != null && count($tab) > 0);
|
||
|
||
return $blnEnabled;
|
||
}
|
||
|
||
/**
|
||
* Super admin connecte (canal usa_id).
|
||
* MSIN-4401 — N'accorde AUCUN droit metier v2 (kits / permissions).
|
||
* Sert uniquement aux outils admin (inspecteur cadenas, edition kits, etc.).
|
||
*/
|
||
function fxEveAccesIsSuperAdminSession()
|
||
{
|
||
return !empty($_SESSION['usa_id']);
|
||
}
|
||
|
||
/**
|
||
* Corps SELECT des acces actifs (remplace l'ancienne vue v_eve_acces_actif).
|
||
* Pas de vue stockee : evite le DEFINER non copiable par Navicat / releve.
|
||
*/
|
||
function fxEveAccesActifBody()
|
||
{
|
||
return "SELECT ea.ea_id, ea.com_id, ea.eve_id, ea.role_id,
|
||
r.role_code, r.role_label_fr, r.role_label_en,
|
||
ea.ea_statut, ea.ea_expires_at, ea.ea_expire_days,
|
||
ea.ea_granted_by, ea.ea_created_at
|
||
FROM inscriptions_eve_acces ea
|
||
INNER JOIN inscriptions_eve_roles r
|
||
ON r.role_id = ea.role_id AND r.role_actif = 1
|
||
WHERE ea.ea_statut = 'actif'
|
||
AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW())";
|
||
}
|
||
|
||
/** Sous-requete aliasee, equivalente a l'ancienne vue v_eve_acces_actif. */
|
||
function fxEveAccesActifSql()
|
||
{
|
||
return "(" . fxEveAccesActifBody() . ") v_eve_acces_actif";
|
||
}
|
||
|
||
/**
|
||
* Sous-requete aliasee, equivalente a l'ancienne vue v_eve_acces_permissions
|
||
* (kits via roles + permissions extra individuelles).
|
||
*/
|
||
function fxEveAccesPermSql()
|
||
{
|
||
return "((SELECT v.ea_id, v.com_id, v.eve_id, v.role_id, v.role_code,
|
||
erp.perm_key, p.perm_group, p.perm_scope, p.perm_label_fr, p.perm_phase
|
||
FROM (" . fxEveAccesActifBody() . ") v
|
||
INNER JOIN inscriptions_eve_role_permissions erp ON erp.role_id = v.role_id
|
||
INNER JOIN inscriptions_eve_permissions p ON p.perm_key = erp.perm_key AND p.perm_actif = 1)
|
||
UNION
|
||
(SELECT NULL AS ea_id, ae.com_id, ae.eve_id, NULL AS role_id, 'extra' AS role_code,
|
||
ae.perm_key, p.perm_group, p.perm_scope, p.perm_label_fr, p.perm_phase
|
||
FROM inscriptions_eve_acces_extra ae
|
||
INNER JOIN inscriptions_eve_permissions p ON p.perm_key = ae.perm_key AND p.perm_actif = 1
|
||
WHERE ae.ae_statut = 'actif')) v_eve_acces_permissions";
|
||
}
|
||
|
||
function fxEveAccesGetRoles($blnActifOnly = true)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array();
|
||
}
|
||
|
||
$sql = "SELECT role_id, role_code, role_label_fr, role_label_en, role_description_fr
|
||
FROM inscriptions_eve_roles";
|
||
|
||
if ($blnActifOnly) {
|
||
$sql .= " WHERE role_actif = 1";
|
||
}
|
||
|
||
$sql .= " ORDER BY role_tri ASC, role_label_fr ASC";
|
||
|
||
return $objDatabase->fxGetResults($sql);
|
||
}
|
||
|
||
/** Kits proposables par un promoteur (role_delegable = 1, hors migration_legacy / kit total). */
|
||
function fxEveAccesGetDelegableRoles()
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array();
|
||
}
|
||
|
||
$blnHasDelegable = false;
|
||
$tabCol = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_eve_roles LIKE 'role_delegable'");
|
||
if ($tabCol != null && count($tabCol) > 0) {
|
||
$blnHasDelegable = true;
|
||
}
|
||
|
||
if (!$blnHasDelegable) {
|
||
return array();
|
||
}
|
||
|
||
// MSIN-4478 — jamais offrir un kit total (rapports / argent / tout) en invitation promoteur.
|
||
$strNoGrantsAll = '';
|
||
if (fxEveAccesHasGrantsAllColumn()) {
|
||
$strNoGrantsAll = ' AND role_grants_all = 0';
|
||
}
|
||
|
||
$sql = "SELECT role_id, role_code, role_label_fr, role_label_en, role_description_fr
|
||
FROM inscriptions_eve_roles
|
||
WHERE role_actif = 1
|
||
AND role_delegable = 1
|
||
AND role_code <> 'migration_legacy'
|
||
$strNoGrantsAll
|
||
ORDER BY role_tri ASC, role_label_fr ASC";
|
||
$tab = $objDatabase->fxGetResults($sql);
|
||
|
||
return ($tab != null) ? $tab : array();
|
||
}
|
||
|
||
/** Le kit est-il délégable (invite promoteur) ? */
|
||
function fxEveAccesRoleIsDelegable($intRoleId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
$intRoleId = intval($intRoleId);
|
||
if ($intRoleId <= 0 || !fxEveAccesIsEnabled()) {
|
||
return false;
|
||
}
|
||
|
||
$tabCol = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_eve_roles LIKE 'role_delegable'");
|
||
if ($tabCol == null || count($tabCol) === 0) {
|
||
return false;
|
||
}
|
||
|
||
$strGrantsCol = fxEveAccesHasGrantsAllColumn() ? ', role_grants_all' : ', 0 AS role_grants_all';
|
||
$row = $objDatabase->fxGetRow(
|
||
"SELECT role_id, role_code, role_delegable, role_actif $strGrantsCol
|
||
FROM inscriptions_eve_roles WHERE role_id = $intRoleId LIMIT 1"
|
||
);
|
||
if ($row === null || intval($row['role_actif']) !== 1) {
|
||
return false;
|
||
}
|
||
if (($row['role_code'] ?? '') === 'migration_legacy') {
|
||
return false;
|
||
}
|
||
// MSIN-4478 — kit total = non délégable (même si la case est cochée en BD).
|
||
if (intval($row['role_grants_all'] ?? 0) === 1) {
|
||
return false;
|
||
}
|
||
|
||
return intval($row['role_delegable'] ?? 0) === 1;
|
||
}
|
||
|
||
function fxEveAccesCanTeamManage($intComId, $intEveId)
|
||
{
|
||
return fxEveAccesHasPermission(intval($intComId), intval($intEveId), 'team.manage');
|
||
}
|
||
|
||
/** Promoteur peut gérer / inviter des accès v2 sur cet événement ? */
|
||
function fxEveAccesCanTeamInvite($intComId, $intEveId)
|
||
{
|
||
return fxEveAccesHasAnyPermission(
|
||
intval($intComId),
|
||
intval($intEveId),
|
||
array('team.invite', 'team.manage')
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Accès v2 actifs (et invitations) pour un événement — vue promoteur.
|
||
*
|
||
* @return array<int, array<string, mixed>>
|
||
*/
|
||
function fxEveAccesListByEveId($intEveId, $blnActifOnly = true)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled() || intval($intEveId) <= 0) {
|
||
return array();
|
||
}
|
||
|
||
$sql = "SELECT ea.ea_id, ea.com_id, ea.eve_id, ea.role_id, ea.ea_statut,
|
||
ea.ea_created_at, ea.ea_expires_at, ea.ea_expire_days, ea.ea_granted_by,
|
||
r.role_code, r.role_label_fr, r.role_label_en,
|
||
c.com_prenom, c.com_nom, c.com_courriel, c.com_lastvisit";
|
||
|
||
// MSIN-4401 — flag invitation (si colonne présente)
|
||
$tabInviteCol = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_comptes LIKE 'com_invite_team'");
|
||
if ($tabInviteCol != null && count($tabInviteCol) > 0) {
|
||
$sql .= ', c.com_invite_team';
|
||
}
|
||
|
||
$sql .= "
|
||
FROM inscriptions_eve_acces ea
|
||
INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id
|
||
INNER JOIN inscriptions_comptes c ON c.com_id = ea.com_id
|
||
WHERE ea.eve_id = " . intval($intEveId);
|
||
|
||
if ($blnActifOnly) {
|
||
$sql .= " AND ea.ea_statut IN ('actif', 'invite')
|
||
AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW())";
|
||
}
|
||
|
||
$sql .= " ORDER BY FIELD(ea.ea_statut, 'actif', 'invite', 'revoke'),
|
||
c.com_nom ASC, c.com_prenom ASC, r.role_label_fr ASC";
|
||
|
||
$tab = $objDatabase->fxGetResults($sql);
|
||
|
||
return ($tab != null) ? $tab : array();
|
||
}
|
||
|
||
function fxEveAccesListByComId($intComId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array();
|
||
}
|
||
|
||
$sql = "SELECT ea.ea_id, ea.com_id, ea.eve_id, ea.role_id, ea.ea_statut,
|
||
ea.ea_expires_at, ea.ea_expire_days, ea.ea_granted_by, ea.ea_note,
|
||
ea.ea_created_at, ea.ea_revoked_at,
|
||
r.role_code, r.role_label_fr,
|
||
e.eve_nom_fr, e.eve_date_fin
|
||
FROM inscriptions_eve_acces ea
|
||
INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id
|
||
LEFT JOIN inscriptions_evenements e ON e.eve_id = ea.eve_id
|
||
WHERE ea.com_id = " . intval($intComId) . "
|
||
ORDER BY ea.ea_statut ASC, e.eve_date_fin DESC, ea.ea_created_at DESC";
|
||
|
||
return $objDatabase->fxGetResults($sql);
|
||
}
|
||
|
||
function fxEveAccesComHasV2($intComId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return false;
|
||
}
|
||
|
||
$sql = "SELECT COUNT(*) FROM " . fxEveAccesActifSql() . " WHERE com_id = " . intval($intComId);
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
function fxEveAccesComHasV2ForEvent($intComId, $intEveId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return false;
|
||
}
|
||
|
||
$sql = "SELECT COUNT(*) FROM " . fxEveAccesActifSql() . "
|
||
WHERE com_id = " . intval($intComId) . "
|
||
AND eve_id = " . intval($intEveId);
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
function fxEveAccesGetEventIds($intComId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array();
|
||
}
|
||
|
||
$sql = "SELECT eve_id FROM " . fxEveAccesActifSql() . " WHERE com_id = " . intval($intComId);
|
||
$tab = $objDatabase->fxGetResults($sql);
|
||
$arrIds = array();
|
||
|
||
if ($tab != null) {
|
||
foreach ($tab as $row) {
|
||
$arrIds[] = (string) intval($row['eve_id']);
|
||
}
|
||
}
|
||
|
||
return $arrIds;
|
||
}
|
||
|
||
/** Acces web gestion inscriptions : page V2 OU au moins une action inscriptions_gestion.* */
|
||
function fxEveAccesHasInscrGestionWebAccess($intComId, $intEveId)
|
||
{
|
||
if (fxEveAccesComEventHasGrantsAllKit(intval($intComId), intval($intEveId))) {
|
||
return true;
|
||
}
|
||
|
||
// MSIN-4401 — plus de registrations.view (ancienne clé API) : uniquement la page / actions V2
|
||
if (fxEveAccesHasPermission(intval($intComId), intval($intEveId), 'inscriptions_gestion.view')) {
|
||
return true;
|
||
}
|
||
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return false;
|
||
}
|
||
|
||
$sql = "SELECT COUNT(*) FROM " . fxEveAccesPermSql() . "
|
||
WHERE com_id = " . intval($intComId) . "
|
||
AND eve_id = " . intval($intEveId) . "
|
||
AND perm_key LIKE 'inscriptions_gestion.%'";
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
function fxEveAccesGetEventIdsWithInscrGestionAccess($intComId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array();
|
||
}
|
||
|
||
$arrIds = array();
|
||
|
||
if (fxEveAccesHasGrantsAllColumn()) {
|
||
$sqlAll = "SELECT DISTINCT ea.eve_id FROM inscriptions_eve_acces ea
|
||
INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id AND r.role_actif = 1
|
||
WHERE ea.com_id = " . intval($intComId) . "
|
||
AND ea.ea_statut = 'actif'
|
||
AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW())
|
||
AND r.role_grants_all = 1
|
||
ORDER BY ea.eve_id ASC";
|
||
$tabAll = $objDatabase->fxGetResults($sqlAll);
|
||
if ($tabAll != null) {
|
||
foreach ($tabAll as $row) {
|
||
$arrIds[intval($row['eve_id'])] = intval($row['eve_id']);
|
||
}
|
||
}
|
||
}
|
||
|
||
$sql = "SELECT DISTINCT eve_id FROM " . fxEveAccesPermSql() . "
|
||
WHERE com_id = " . intval($intComId) . "
|
||
AND (
|
||
perm_key = 'inscriptions_gestion.view'
|
||
OR perm_key LIKE 'inscriptions_gestion.%'
|
||
)
|
||
ORDER BY eve_id ASC";
|
||
$tab = $objDatabase->fxGetResults($sql);
|
||
|
||
if ($tab != null) {
|
||
foreach ($tab as $row) {
|
||
$arrIds[intval($row['eve_id'])] = intval($row['eve_id']);
|
||
}
|
||
}
|
||
|
||
$arrIds = array_values($arrIds);
|
||
sort($arrIds, SORT_NUMERIC);
|
||
|
||
return $arrIds;
|
||
}
|
||
|
||
function fxEveAccesHasGrantsAllColumn()
|
||
{
|
||
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_grants_all'");
|
||
$blnHas = ($tab != null && count($tab) > 0);
|
||
|
||
return $blnHas;
|
||
}
|
||
|
||
function fxEveAccesCatalogPermIsActive($strPermKey)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled() || trim((string)$strPermKey) === '') {
|
||
return false;
|
||
}
|
||
|
||
$sql = "SELECT COUNT(*) FROM inscriptions_eve_permissions
|
||
WHERE perm_key = '" . $objDatabase->fxEscape($strPermKey) . "'
|
||
AND perm_actif = 1";
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
/** MSIN-4484 — Colonne catalogue perm_grants_all presente ? */
|
||
function fxEveAccesHasPermGrantsAllColumn()
|
||
{
|
||
global $objDatabase;
|
||
|
||
static $blnHas = null;
|
||
if ($blnHas !== null) {
|
||
return $blnHas;
|
||
}
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
$blnHas = false;
|
||
return $blnHas;
|
||
}
|
||
|
||
$tab = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_eve_permissions LIKE 'perm_grants_all'");
|
||
$blnHas = ($tab != null && count($tab) > 0);
|
||
|
||
return $blnHas;
|
||
}
|
||
|
||
/**
|
||
* MSIN-4484 — Cle active et incluse dans un kit role_grants_all ?
|
||
* perm_grants_all = 0 → hors propagation (matrice / extra seulement).
|
||
*/
|
||
function fxEveAccesCatalogPermPropagatesWithGrantsAll($strPermKey)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled() || trim((string)$strPermKey) === '') {
|
||
return false;
|
||
}
|
||
|
||
if (!fxEveAccesHasPermGrantsAllColumn()) {
|
||
return fxEveAccesCatalogPermIsActive($strPermKey);
|
||
}
|
||
|
||
$sql = "SELECT COUNT(*) FROM inscriptions_eve_permissions
|
||
WHERE perm_key = '" . $objDatabase->fxEscape($strPermKey) . "'
|
||
AND perm_actif = 1
|
||
AND perm_grants_all = 1";
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
/** Compte avec au moins un kit role_grants_all actif sur cet evenement. */
|
||
function fxEveAccesComEventHasGrantsAllKit($intComId, $intEveId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled() || !fxEveAccesHasGrantsAllColumn()) {
|
||
return false;
|
||
}
|
||
|
||
$sql = "SELECT COUNT(*) FROM inscriptions_eve_acces ea
|
||
INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id AND r.role_actif = 1
|
||
WHERE ea.com_id = " . intval($intComId) . "
|
||
AND ea.eve_id = " . intval($intEveId) . "
|
||
AND ea.ea_statut = 'actif'
|
||
AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW())
|
||
AND r.role_grants_all = 1";
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
/** MSIN-4401 — Colonne kit role_fiche_sections_open presente ? */
|
||
function fxEveAccesHasFicheSectionsOpenColumn()
|
||
{
|
||
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_fiche_sections_open'");
|
||
$blnHas = ($tab != null && count($tab) > 0);
|
||
|
||
return $blnHas;
|
||
}
|
||
|
||
/**
|
||
* MSIN-4401 — Au moins un kit actif du compte force les sections de la fiche inscriptions ouvertes.
|
||
*/
|
||
function fxEveAccesComEventHasFicheSectionsOpenKit($intComId, $intEveId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled() || !fxEveAccesHasFicheSectionsOpenColumn()) {
|
||
return false;
|
||
}
|
||
|
||
$sql = "SELECT COUNT(*) FROM inscriptions_eve_acces ea
|
||
INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id AND r.role_actif = 1
|
||
WHERE ea.com_id = " . intval($intComId) . "
|
||
AND ea.eve_id = " . intval($intEveId) . "
|
||
AND ea.ea_statut = 'actif'
|
||
AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW())
|
||
AND r.role_fiche_sections_open = 1";
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
function fxEveAccesHasPermission($intComId, $intEveId, $strPermKey)
|
||
{
|
||
// MSIN-4401 — Pas de bypass super-admin : seuls kits / extras (ou grants_all) comptent.
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return false;
|
||
}
|
||
|
||
// MSIN-4484 — kit total = cles propagées ; cles hors kit total → matrice / extra seulement.
|
||
if (fxEveAccesComEventHasGrantsAllKit($intComId, $intEveId)
|
||
&& fxEveAccesCatalogPermPropagatesWithGrantsAll($strPermKey)) {
|
||
return true;
|
||
}
|
||
|
||
$sql = "SELECT COUNT(*) FROM " . fxEveAccesPermSql() . "
|
||
WHERE com_id = " . intval($intComId) . "
|
||
AND eve_id = " . intval($intEveId) . "
|
||
AND perm_key = '" . $objDatabase->fxEscape($strPermKey) . "'";
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
function fxEveAccesHasAnyPermission($intComId, $intEveId, $arrPermKeys)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled() || empty($arrPermKeys)) {
|
||
return false;
|
||
}
|
||
|
||
// MSIN-4484 — kit total pour les cles propagées ; sinon (ou cles hors total) → explicite.
|
||
if (fxEveAccesComEventHasGrantsAllKit($intComId, $intEveId)) {
|
||
foreach ($arrPermKeys as $strKey) {
|
||
if (fxEveAccesCatalogPermPropagatesWithGrantsAll($strKey)) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
$arrEsc = array();
|
||
foreach ($arrPermKeys as $strKey) {
|
||
$arrEsc[] = "'" . $objDatabase->fxEscape($strKey) . "'";
|
||
}
|
||
|
||
$sql = "SELECT COUNT(*) FROM " . fxEveAccesPermSql() . "
|
||
WHERE com_id = " . intval($intComId) . "
|
||
AND eve_id = " . intval($intEveId) . "
|
||
AND perm_key IN (" . implode(',', $arrEsc) . ")";
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
function fxEveAccesGetEventIdsWithAnyPermission($intComId, $arrPermKeys)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled() || empty($arrPermKeys)) {
|
||
return array();
|
||
}
|
||
|
||
$arrEsc = array();
|
||
foreach ($arrPermKeys as $strKey) {
|
||
$arrEsc[] = "'" . $objDatabase->fxEscape($strKey) . "'";
|
||
}
|
||
|
||
$sql = "SELECT DISTINCT eve_id FROM " . fxEveAccesPermSql() . "
|
||
WHERE com_id = " . intval($intComId) . "
|
||
AND perm_key IN (" . implode(',', $arrEsc) . ")
|
||
ORDER BY eve_id ASC";
|
||
$tab = $objDatabase->fxGetResults($sql);
|
||
$arrIds = array();
|
||
|
||
if ($tab != null) {
|
||
foreach ($tab as $row) {
|
||
$arrIds[] = intval($row['eve_id']);
|
||
}
|
||
}
|
||
|
||
return $arrIds;
|
||
}
|
||
|
||
/** Outil debug QR — permission v2 tools.qr_test (pas de bypass super-admin). */
|
||
function fxEveAccesCanQrTest($intComId)
|
||
{
|
||
if (!fxEveAccesIsEnabled() || intval($intComId) <= 0) {
|
||
return false;
|
||
}
|
||
|
||
global $objDatabase;
|
||
|
||
$sql = "SELECT COUNT(*) FROM " . fxEveAccesPermSql() . "
|
||
WHERE com_id = " . intval($intComId) . "
|
||
AND perm_key = 'tools.qr_test'";
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
function fxEveAccesGetCatalogPermissions($strScope = null, $blnActifOnly = true)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array();
|
||
}
|
||
|
||
// MSIN-4484 — perm_grants_all pour UI matrice (badge hors kit total).
|
||
$strGrantsCol = fxEveAccesHasPermGrantsAllColumn()
|
||
? ', perm_grants_all'
|
||
: ', 1 AS perm_grants_all';
|
||
|
||
$sql = "SELECT perm_key, perm_group, perm_scope, perm_label_fr, perm_label_en, perm_phase, perm_tri"
|
||
. $strGrantsCol
|
||
. " FROM inscriptions_eve_permissions";
|
||
|
||
$arrWhere = array();
|
||
if ($blnActifOnly) {
|
||
$arrWhere[] = 'perm_actif = 1';
|
||
}
|
||
if ($strScope !== null && $strScope !== '') {
|
||
$arrWhere[] = "perm_scope = '" . $objDatabase->fxEscape($strScope) . "'";
|
||
}
|
||
if (!empty($arrWhere)) {
|
||
$sql .= ' WHERE ' . implode(' AND ', $arrWhere);
|
||
}
|
||
$sql .= ' ORDER BY perm_group ASC, perm_tri ASC, perm_key ASC';
|
||
|
||
return $objDatabase->fxGetResults($sql);
|
||
}
|
||
|
||
function fxEveAccesListExtraByComId($intComId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array();
|
||
}
|
||
|
||
$sql = "SELECT ae.ae_id, ae.com_id, ae.eve_id, ae.perm_key, ae.ae_statut, ae.ae_created_at,
|
||
p.perm_label_fr, p.perm_scope,
|
||
e.eve_nom_fr
|
||
FROM inscriptions_eve_acces_extra ae
|
||
INNER JOIN inscriptions_eve_permissions p ON p.perm_key = ae.perm_key
|
||
LEFT JOIN inscriptions_evenements e ON e.eve_id = ae.eve_id
|
||
WHERE ae.com_id = " . intval($intComId) . "
|
||
ORDER BY ae.ae_statut ASC, e.eve_date_fin DESC, p.perm_group ASC, p.perm_tri ASC";
|
||
|
||
return $objDatabase->fxGetResults($sql);
|
||
}
|
||
|
||
function fxEveAccesGrantExtra($intComId, $intEveId, $strPermKey, $intGrantedBy, $strNote = '')
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array('state' => 'error', 'message' => 'Tables v2 non installees');
|
||
}
|
||
|
||
$intComId = intval($intComId);
|
||
$intEveId = intval($intEveId);
|
||
$strPermKey = trim((string)$strPermKey);
|
||
|
||
if ($intComId <= 0 || $intEveId <= 0 || $strPermKey === '') {
|
||
return array('state' => 'error', 'message' => 'Parametres invalides');
|
||
}
|
||
|
||
$tabPerm = $objDatabase->fxGetRow(
|
||
"SELECT perm_key FROM inscriptions_eve_permissions
|
||
WHERE perm_key = '" . $objDatabase->fxEscape($strPermKey) . "' AND perm_actif = 1 LIMIT 1"
|
||
);
|
||
if ($tabPerm == null) {
|
||
return array('state' => 'error', 'message' => 'Permission invalide');
|
||
}
|
||
|
||
$intNbKits = intval($objDatabase->fxGetVar(
|
||
"SELECT COUNT(*) FROM inscriptions_eve_acces
|
||
WHERE com_id = $intComId AND eve_id = $intEveId AND ea_statut = 'actif'"
|
||
));
|
||
if ($intNbKits <= 0) {
|
||
return array('state' => 'error', 'message' => 'Assigner au moins un kit avant un droit individuel.');
|
||
}
|
||
|
||
$strNote = $objDatabase->fxEscape(trim($strNote));
|
||
$strGrantedBy = (intval($intGrantedBy) > 0) ? intval($intGrantedBy) : 'NULL';
|
||
|
||
$sql = "INSERT INTO inscriptions_eve_acces_extra
|
||
(com_id, eve_id, perm_key, ae_statut, ae_granted_by, ae_note)
|
||
VALUES
|
||
($intComId, $intEveId, '" . $objDatabase->fxEscape($strPermKey) . "', 'actif', $strGrantedBy, '$strNote')
|
||
ON DUPLICATE KEY UPDATE
|
||
ae_statut = 'actif',
|
||
ae_granted_by = VALUES(ae_granted_by),
|
||
ae_note = VALUES(ae_note),
|
||
ae_revoked_at = NULL,
|
||
ae_updated_at = NOW()";
|
||
$objDatabase->fxQuery($sql);
|
||
|
||
$intAeId = intval($objDatabase->fxGetVar(
|
||
"SELECT ae_id FROM inscriptions_eve_acces_extra
|
||
WHERE com_id = $intComId AND eve_id = $intEveId
|
||
AND perm_key = '" . $objDatabase->fxEscape($strPermKey) . "' LIMIT 1"
|
||
));
|
||
|
||
fxEveAccesWriteLog(null, $intComId, $intEveId, null, 'extra_grant', 'Grant extra: ' . $strPermKey, $intGrantedBy);
|
||
|
||
return array('state' => 'success', 'ae_id' => $intAeId);
|
||
}
|
||
|
||
function fxEveAccesRevokeExtra($intAeId, $intRevokedBy)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array('state' => 'error', 'message' => 'Tables v2 non installees');
|
||
}
|
||
|
||
$intAeId = intval($intAeId);
|
||
$tab = $objDatabase->fxGetRow("SELECT * FROM inscriptions_eve_acces_extra WHERE ae_id = " . $intAeId . " LIMIT 1");
|
||
|
||
if ($tab == null) {
|
||
return array('state' => 'error', 'message' => 'Grant extra introuvable');
|
||
}
|
||
|
||
$sql = "UPDATE inscriptions_eve_acces_extra
|
||
SET ae_statut = 'revoke',
|
||
ae_revoked_at = NOW(),
|
||
ae_updated_at = NOW()
|
||
WHERE ae_id = " . $intAeId;
|
||
$objDatabase->fxQuery($sql);
|
||
|
||
fxEveAccesWriteLog(null, $tab['com_id'], $tab['eve_id'], null, 'extra_revoke', 'Revoke extra: ' . $tab['perm_key'], $intRevokedBy);
|
||
|
||
return array('state' => 'success');
|
||
}
|
||
|
||
function fxEveAccesResolveEveIdFromParId($intParId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
$intParId = intval($intParId);
|
||
if ($intParId <= 0) {
|
||
return 0;
|
||
}
|
||
|
||
$intEveId = intval($objDatabase->fxGetVar(
|
||
'SELECT eve_id FROM resultats_participants WHERE par_id = ' . $intParId . ' LIMIT 1'
|
||
));
|
||
|
||
return ($intEveId > 0) ? $intEveId : 0;
|
||
}
|
||
|
||
/**
|
||
* Gate AJAX promoteur : legacy promoteur OU permission v2 explicite.
|
||
* Si le compte a deja des acces v2 actifs, exige la permission demandee.
|
||
*/
|
||
function fxEveAccesAssertPromoteurAction($intComId, $intEveId, $strPermKey)
|
||
{
|
||
$intComId = intval($intComId);
|
||
$intEveId = intval($intEveId);
|
||
|
||
if ($intComId <= 0 || $intEveId <= 0) {
|
||
return false;
|
||
}
|
||
|
||
if (!fxEveAccesComHasV2ForEvent($intComId, $intEveId)) {
|
||
if (!function_exists('fxIsPromoteur')) {
|
||
require_once __DIR__ . '/inc_fonctions.php';
|
||
}
|
||
return fxIsPromoteur($intComId, $intEveId);
|
||
}
|
||
|
||
return fxEveAccesHasPermission($intComId, $intEveId, $strPermKey);
|
||
}
|
||
|
||
function fxEveAccesGrant($intComId, $intEveId, $intRoleId, $intExpireDays, $intGrantedBy, $strNote = '', $strStatut = 'actif')
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array('state' => 'error', 'message' => 'Tables v2 non installees');
|
||
}
|
||
|
||
$intComId = intval($intComId);
|
||
$intEveId = intval($intEveId);
|
||
$intRoleId = intval($intRoleId);
|
||
$intGrantedBy = intval($intGrantedBy);
|
||
$strStatut = ($strStatut === 'invite') ? 'invite' : 'actif';
|
||
|
||
if ($intComId <= 0 || $intEveId <= 0 || $intRoleId <= 0) {
|
||
return array('state' => 'error', 'message' => 'Parametres invalides');
|
||
}
|
||
|
||
$tabRole = $objDatabase->fxGetRow("SELECT role_id FROM inscriptions_eve_roles WHERE role_id = " . $intRoleId . " AND role_actif = 1 LIMIT 1");
|
||
if ($tabRole == null) {
|
||
return array('state' => 'error', 'message' => 'Role invalide');
|
||
}
|
||
|
||
$tabCom = $objDatabase->fxGetRow("SELECT com_id FROM inscriptions_comptes WHERE com_id = " . $intComId . " LIMIT 1");
|
||
if ($tabCom == null) {
|
||
return array('state' => 'error', 'message' => 'Compte introuvable');
|
||
}
|
||
|
||
$tabEve = $objDatabase->fxGetRow("SELECT eve_id FROM inscriptions_evenements WHERE eve_id = " . $intEveId . " LIMIT 1");
|
||
if ($tabEve == null) {
|
||
return array('state' => 'error', 'message' => 'Evenement introuvable');
|
||
}
|
||
|
||
$strExpires = 'NULL';
|
||
$intExpireDaysStore = 'NULL';
|
||
|
||
if ($intExpireDays > 0) {
|
||
$strExpires = "'" . $objDatabase->fxEscape(date('Y-m-d H:i:s', strtotime('+' . intval($intExpireDays) . ' days'))) . "'";
|
||
$intExpireDaysStore = intval($intExpireDays);
|
||
}
|
||
|
||
$strNote = $objDatabase->fxEscape(trim($strNote));
|
||
$strGrantedBy = ($intGrantedBy > 0) ? $intGrantedBy : 'NULL';
|
||
|
||
$sql = "INSERT INTO inscriptions_eve_acces
|
||
(com_id, eve_id, role_id, ea_statut, ea_expires_at, ea_expire_days, ea_granted_by, ea_note)
|
||
VALUES
|
||
($intComId, $intEveId, $intRoleId, '$strStatut', $strExpires, $intExpireDaysStore, $strGrantedBy, '$strNote')
|
||
ON DUPLICATE KEY UPDATE
|
||
role_id = VALUES(role_id),
|
||
ea_statut = VALUES(ea_statut),
|
||
ea_expires_at = VALUES(ea_expires_at),
|
||
ea_expire_days = VALUES(ea_expire_days),
|
||
ea_granted_by = VALUES(ea_granted_by),
|
||
ea_note = VALUES(ea_note),
|
||
ea_revoked_at = NULL,
|
||
ea_revoked_by = NULL,
|
||
ea_updated_at = NOW()";
|
||
|
||
$objDatabase->fxQuery($sql);
|
||
|
||
$intEaId = intval($objDatabase->fxGetVar(
|
||
"SELECT ea_id FROM inscriptions_eve_acces
|
||
WHERE com_id = $intComId AND eve_id = $intEveId AND role_id = $intRoleId
|
||
LIMIT 1"
|
||
));
|
||
|
||
if ($intEaId <= 0) {
|
||
// Repli si unique legacy (com+eve) encore en place sur certains environnements
|
||
$intEaId = intval($objDatabase->fxGetVar(
|
||
"SELECT ea_id FROM inscriptions_eve_acces
|
||
WHERE com_id = $intComId AND eve_id = $intEveId
|
||
ORDER BY ea_id DESC LIMIT 1"
|
||
));
|
||
}
|
||
|
||
if ($intEaId <= 0) {
|
||
return array('state' => 'error', 'message' => 'Acces non enregistre');
|
||
}
|
||
|
||
fxEveAccesWriteLog($intEaId, $intComId, $intEveId, $intRoleId, 'create', 'Grant / mise a jour acces v2', $intGrantedBy);
|
||
|
||
return array('state' => 'success', 'ea_id' => $intEaId);
|
||
}
|
||
|
||
/**
|
||
* MSIN-4401 — active les accès encore en statut invite après création du mot de passe.
|
||
*/
|
||
function fxEveAccesActivateInvitesForCompte($intComId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
$intComId = intval($intComId);
|
||
if ($intComId <= 0 || !fxEveAccesIsEnabled()) {
|
||
return;
|
||
}
|
||
|
||
$objDatabase->fxQuery(
|
||
"UPDATE inscriptions_eve_acces
|
||
SET ea_statut = 'actif',
|
||
ea_updated_at = NOW()
|
||
WHERE com_id = $intComId
|
||
AND ea_statut = 'invite'"
|
||
);
|
||
}
|
||
|
||
function fxEveAccesRevoke($intEaId, $intRevokedBy)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array('state' => 'error', 'message' => 'Tables v2 non installees');
|
||
}
|
||
|
||
$intEaId = intval($intEaId);
|
||
$tab = $objDatabase->fxGetRow("SELECT * FROM inscriptions_eve_acces WHERE ea_id = " . $intEaId . " LIMIT 1");
|
||
|
||
if ($tab == null) {
|
||
return array('state' => 'error', 'message' => 'Acces introuvable');
|
||
}
|
||
|
||
$sql = "UPDATE inscriptions_eve_acces
|
||
SET ea_statut = 'revoke',
|
||
ea_revoked_at = NOW(),
|
||
ea_revoked_by = " . intval($intRevokedBy) . ",
|
||
ea_updated_at = NOW()
|
||
WHERE ea_id = " . $intEaId;
|
||
$objDatabase->fxQuery($sql);
|
||
|
||
fxEveAccesWriteLog($intEaId, $tab['com_id'], $tab['eve_id'], $tab['role_id'], 'revoke', 'Revoke manuel super admin', $intRevokedBy);
|
||
|
||
return array('state' => 'success');
|
||
}
|
||
|
||
function fxEveAccesRowIsActif($row)
|
||
{
|
||
if ($row['ea_statut'] !== 'actif') {
|
||
return false;
|
||
}
|
||
if (!empty($row['ea_expires_at']) && strtotime($row['ea_expires_at']) <= time()) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
function fxEveAccesReactivate($intEaId, $intGrantedBy)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array('state' => 'error', 'message' => 'Tables v2 non installees');
|
||
}
|
||
|
||
$tab = $objDatabase->fxGetRow("SELECT * FROM inscriptions_eve_acces WHERE ea_id = " . intval($intEaId) . " LIMIT 1");
|
||
if ($tab == null) {
|
||
return array('state' => 'error', 'message' => 'Acces introuvable');
|
||
}
|
||
|
||
$intExpireDays = intval($tab['ea_expire_days'] ?? 0);
|
||
|
||
return fxEveAccesGrant(
|
||
intval($tab['com_id']),
|
||
intval($tab['eve_id']),
|
||
intval($tab['role_id']),
|
||
$intExpireDays,
|
||
intval($intGrantedBy),
|
||
'Reactivation super admin'
|
||
);
|
||
}
|
||
|
||
function fxEveAccesReactivateExtra($intAeId, $intGrantedBy)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array('state' => 'error', 'message' => 'Tables v2 non installees');
|
||
}
|
||
|
||
$tab = $objDatabase->fxGetRow("SELECT * FROM inscriptions_eve_acces_extra WHERE ae_id = " . intval($intAeId) . " LIMIT 1");
|
||
if ($tab == null) {
|
||
return array('state' => 'error', 'message' => 'Grant extra introuvable');
|
||
}
|
||
|
||
return fxEveAccesGrantExtra(
|
||
intval($tab['com_id']),
|
||
intval($tab['eve_id']),
|
||
$tab['perm_key'],
|
||
intval($intGrantedBy),
|
||
'Reactivation super admin'
|
||
);
|
||
}
|
||
|
||
function fxEveAccesWriteLog($intEaId, $intComId, $intEveId, $intRoleId, $strAction, $strDetail, $intByComId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return;
|
||
}
|
||
|
||
$intEaId = ($intEaId > 0) ? intval($intEaId) : 'NULL';
|
||
$intRoleId = ($intRoleId > 0) ? intval($intRoleId) : 'NULL';
|
||
$intByComId = ($intByComId > 0) ? intval($intByComId) : 'NULL';
|
||
|
||
$sql = "INSERT INTO inscriptions_eve_acces_log
|
||
(ea_id, com_id, eve_id, role_id, log_action, log_detail, log_by_com_id)
|
||
VALUES
|
||
($intEaId, " . intval($intComId) . ", " . intval($intEveId) . ", $intRoleId,
|
||
'" . $objDatabase->fxEscape($strAction) . "',
|
||
'" . $objDatabase->fxEscape($strDetail) . "',
|
||
$intByComId)";
|
||
$objDatabase->fxQuery($sql);
|
||
}
|
||
|
||
function fxEveAccesGetPermissionsForComEvent($intComId, $intEveId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array();
|
||
}
|
||
|
||
$sql = "SELECT perm_key, perm_group, perm_label_fr
|
||
FROM " . fxEveAccesPermSql() . "
|
||
WHERE com_id = " . intval($intComId) . "
|
||
AND eve_id = " . intval($intEveId) . "
|
||
ORDER BY perm_group, perm_key";
|
||
|
||
return $objDatabase->fxGetResults($sql);
|
||
}
|
||
|
||
/** Regroupe kits et extras actifs par eve_id pour la fiche compte super admin. */
|
||
function fxEveAccesCompteFormGroupByEvent($arrAcces, $arrExtras)
|
||
{
|
||
$arrGroups = array();
|
||
|
||
if ($arrAcces != null) {
|
||
foreach ($arrAcces as $row) {
|
||
if (!fxEveAccesRowIsActif($row)) {
|
||
continue;
|
||
}
|
||
$intEveId = intval($row['eve_id']);
|
||
if (!isset($arrGroups[$intEveId])) {
|
||
$arrGroups[$intEveId] = array(
|
||
'eve_id' => $intEveId,
|
||
'eve_nom_fr' => $row['eve_nom_fr'] ?? ('Événement #' . $intEveId),
|
||
'kits' => array(),
|
||
'extras' => array(),
|
||
);
|
||
}
|
||
$arrGroups[$intEveId]['kits'][] = $row;
|
||
}
|
||
}
|
||
|
||
if ($arrExtras != null) {
|
||
foreach ($arrExtras as $row) {
|
||
if (($row['ae_statut'] ?? '') !== 'actif') {
|
||
continue;
|
||
}
|
||
$intEveId = intval($row['eve_id']);
|
||
if (!isset($arrGroups[$intEveId])) {
|
||
$arrGroups[$intEveId] = array(
|
||
'eve_id' => $intEveId,
|
||
'eve_nom_fr' => $row['eve_nom_fr'] ?? ('Événement #' . $intEveId),
|
||
'kits' => array(),
|
||
'extras' => array(),
|
||
);
|
||
}
|
||
$arrGroups[$intEveId]['extras'][] = $row;
|
||
}
|
||
}
|
||
|
||
uasort($arrGroups, function ($a, $b) {
|
||
return strcasecmp($a['eve_nom_fr'], $b['eve_nom_fr']);
|
||
});
|
||
|
||
return $arrGroups;
|
||
}
|
||
|
||
/** URL fiche compte super admin (section acces v2). */
|
||
function fxEveAccesCompteAdminUrl($intComId, $intFocusEveId = 0)
|
||
{
|
||
$strUrl = 'index.php?t=' . urlencode(base64_encode('2'))
|
||
. '&a=mod&id=' . intval($intComId);
|
||
if (intval($intFocusEveId) > 0) {
|
||
$strUrl .= '&eve_acces_focus=' . intval($intFocusEveId);
|
||
}
|
||
|
||
return $strUrl . '#eve-acces-v2';
|
||
}
|
||
|
||
/** Regroupe kits et extras actifs par com_id pour la fiche evenement super admin. */
|
||
function fxEveAccesEventFormGroupByCom($intEveId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array();
|
||
}
|
||
|
||
$intEveId = intval($intEveId);
|
||
$arrGroups = array();
|
||
|
||
$sqlKits = "SELECT ea.ea_id, ea.com_id, ea.role_id, ea.ea_statut, ea.ea_expires_at,
|
||
r.role_label_fr,
|
||
c.com_prenom, c.com_nom, c.com_courriel, c.com_telephone1
|
||
FROM inscriptions_eve_acces ea
|
||
INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id
|
||
INNER JOIN inscriptions_comptes c ON c.com_id = ea.com_id
|
||
WHERE ea.eve_id = $intEveId
|
||
AND ea.ea_statut = 'actif'
|
||
AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW())
|
||
ORDER BY c.com_nom ASC, c.com_prenom ASC, r.role_tri ASC";
|
||
|
||
$arrKits = $objDatabase->fxGetResults($sqlKits);
|
||
if ($arrKits != null) {
|
||
foreach ($arrKits as $row) {
|
||
$intComId = intval($row['com_id']);
|
||
if (!isset($arrGroups[$intComId])) {
|
||
$arrGroups[$intComId] = array(
|
||
'com_id' => $intComId,
|
||
'com_prenom' => $row['com_prenom'],
|
||
'com_nom' => $row['com_nom'],
|
||
'com_courriel' => $row['com_courriel'],
|
||
'com_telephone1' => $row['com_telephone1'],
|
||
'kits' => array(),
|
||
'extras' => array(),
|
||
);
|
||
}
|
||
$arrGroups[$intComId]['kits'][] = $row;
|
||
}
|
||
}
|
||
|
||
$sqlExtras = "SELECT ae.ae_id, ae.com_id, ae.perm_key,
|
||
p.perm_label_fr,
|
||
c.com_prenom, c.com_nom, c.com_courriel, c.com_telephone1
|
||
FROM inscriptions_eve_acces_extra ae
|
||
INNER JOIN inscriptions_eve_permissions p ON p.perm_key = ae.perm_key
|
||
INNER JOIN inscriptions_comptes c ON c.com_id = ae.com_id
|
||
WHERE ae.eve_id = $intEveId
|
||
AND ae.ae_statut = 'actif'
|
||
ORDER BY c.com_nom ASC, c.com_prenom ASC, p.perm_tri ASC";
|
||
|
||
$arrExtras = $objDatabase->fxGetResults($sqlExtras);
|
||
if ($arrExtras != null) {
|
||
foreach ($arrExtras as $row) {
|
||
$intComId = intval($row['com_id']);
|
||
if (!isset($arrGroups[$intComId])) {
|
||
$arrGroups[$intComId] = array(
|
||
'com_id' => $intComId,
|
||
'com_prenom' => $row['com_prenom'],
|
||
'com_nom' => $row['com_nom'],
|
||
'com_courriel' => $row['com_courriel'],
|
||
'com_telephone1' => $row['com_telephone1'],
|
||
'kits' => array(),
|
||
'extras' => array(),
|
||
);
|
||
}
|
||
$arrGroups[$intComId]['extras'][] = $row;
|
||
}
|
||
}
|
||
|
||
uasort($arrGroups, function ($a, $b) {
|
||
$cmp = strcasecmp($a['com_nom'], $b['com_nom']);
|
||
if ($cmp !== 0) {
|
||
return $cmp;
|
||
}
|
||
return strcasecmp($a['com_prenom'], $b['com_prenom']);
|
||
});
|
||
|
||
return $arrGroups;
|
||
}
|
||
|
||
function fxEveAccesShowEventAccessPanel($intEveId)
|
||
{
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return;
|
||
}
|
||
|
||
$intEveId = intval($intEveId);
|
||
$arrGroups = fxEveAccesEventFormGroupByCom($intEveId);
|
||
$intNb = count($arrGroups);
|
||
|
||
require_once __DIR__ . '/inc_fx_superadm_v2_ui.php';
|
||
|
||
$strHeaderExtra = '';
|
||
if ($intNb > 0) {
|
||
$strHeaderExtra = '<span class="superadm-v2-panel__header-extra ml-2">'
|
||
. '<span class="badge badge-light">' . intval($intNb) . '</span></span>';
|
||
}
|
||
|
||
fxSuperadmV2PanelOpen('Accès v2 — cet événement', array(
|
||
'collapse_id' => 'tableEveAccesV2',
|
||
'zone_class' => 'superadm-content-v2-zone mt-3 mb-2',
|
||
'header_extra' => $strHeaderExtra,
|
||
));
|
||
?>
|
||
<div id="pick-eve-acces-compte" class="position-relative mb-2" style="max-width:420px;">
|
||
<label class="small text-muted mb-0" for="pp-eve-acces-compte-email">
|
||
Rechercher un compte par courriel pour lui assigner des accès
|
||
</label>
|
||
<input type="text" class="form-control form-control-sm mt-1" id="pp-eve-acces-compte-email"
|
||
placeholder="Tapez un e-mail…" autocomplete="off">
|
||
<div id="pp-results-eve-acces-compte" class="list-group d-none mt-1"
|
||
style="position:absolute;left:0;right:0;z-index:1000;max-height:220px;overflow:auto;"></div>
|
||
</div>
|
||
|
||
<table class="table table-sm table-striped mt-2 mb-3">
|
||
<thead>
|
||
<tr>
|
||
<th style="width:20px">#</th>
|
||
<th>Prénom</th>
|
||
<th>Nom</th>
|
||
<th>Courriel</th>
|
||
<th>Droits</th>
|
||
<th style="width:90px" class="text-center">Compte</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php
|
||
if ($intNb === 0) {
|
||
echo '<tr><td colspan="6" class="text-muted">Aucun accès v2 sur cet événement.</td></tr>';
|
||
} else {
|
||
$intIdx = 0;
|
||
foreach ($arrGroups as $arrGroup) {
|
||
?>
|
||
<tr>
|
||
<td class="text-muted"><?= $intIdx ?></td>
|
||
<td><?= htmlspecialchars($arrGroup['com_prenom'], ENT_QUOTES, 'UTF-8') ?></td>
|
||
<td><?= htmlspecialchars($arrGroup['com_nom'], ENT_QUOTES, 'UTF-8') ?></td>
|
||
<td><?= htmlspecialchars($arrGroup['com_courriel'], ENT_QUOTES, 'UTF-8') ?></td>
|
||
<td>
|
||
<?php
|
||
foreach ($arrGroup['kits'] as $rowKit) { ?>
|
||
<span class="badge badge-primary mr-1 mb-1 py-1 px-2">
|
||
<?= htmlspecialchars($rowKit['role_label_fr'], ENT_QUOTES, 'UTF-8') ?>
|
||
</span>
|
||
<?php }
|
||
foreach ($arrGroup['extras'] as $rowExtra) { ?>
|
||
<span class="badge mr-1 mb-1 py-1 px-2" style="background-color:#e67e22;color:#fff;">
|
||
<?= htmlspecialchars($rowExtra['perm_label_fr'], ENT_QUOTES, 'UTF-8') ?>
|
||
</span>
|
||
<?php }
|
||
if (count($arrGroup['kits']) === 0 && count($arrGroup['extras']) === 0) {
|
||
echo '<span class="text-muted">—</span>';
|
||
}
|
||
?>
|
||
</td>
|
||
<td class="text-center">
|
||
<a href="<?= htmlspecialchars(fxEveAccesCompteAdminUrl($arrGroup['com_id'], $intEveId), ENT_QUOTES, 'UTF-8') ?>"
|
||
class="btn btn-sm btn-outline-primary py-0"
|
||
title="Ouvrir la fiche compte">
|
||
<i class="fa fa-user"></i>
|
||
</a>
|
||
</td>
|
||
</tr>
|
||
<?php
|
||
$intIdx++;
|
||
}
|
||
}
|
||
?>
|
||
</tbody>
|
||
<?php if ($intNb > 0) { ?>
|
||
<tfoot>
|
||
<tr>
|
||
<th colspan="6" class="text-muted small font-weight-normal">
|
||
<?= $intNb ?> compte<?= $intNb > 1 ? 's' : '' ?> avec accès v2
|
||
</th>
|
||
</tr>
|
||
</tfoot>
|
||
<?php } ?>
|
||
</table>
|
||
|
||
<?php
|
||
fxSuperadmV2PanelClose(array('collapse_id' => 'tableEveAccesV2'));
|
||
?>
|
||
|
||
<script>
|
||
(function($){
|
||
var intFocusEveId = <?= $intEveId ?>;
|
||
var strCompteAccesBase = <?= json_encode('index.php?t=' . urlencode(base64_encode('2')) . '&a=mod&id=') ?>;
|
||
|
||
function compteAccesUrl(intComId) {
|
||
var url = strCompteAccesBase + encodeURIComponent(intComId);
|
||
if (intFocusEveId > 0) {
|
||
url += '&eve_acces_focus=' + encodeURIComponent(intFocusEveId);
|
||
}
|
||
return url + '#eve-acces-v2';
|
||
}
|
||
|
||
var $wrap = $('#pick-eve-acces-compte');
|
||
var $in = $('#pp-eve-acces-compte-email');
|
||
var $list = $('#pp-results-eve-acces-compte');
|
||
var timer = null, xhr = null;
|
||
|
||
function renderComptePick(items) {
|
||
$list.empty();
|
||
if (!items || !items.length) {
|
||
$list.addClass('d-none');
|
||
return;
|
||
}
|
||
items.forEach(function(it) {
|
||
var intComId = it.id || it.com_id;
|
||
var strLabel = it.email || it.com_courriel || '';
|
||
if (it.com_prenom || it.com_nom) {
|
||
strLabel = $.trim((it.com_prenom || '') + ' ' + (it.com_nom || ''))
|
||
+ ' — ' + strLabel;
|
||
}
|
||
$('<a href="#" class="list-group-item list-group-item-action"></a>')
|
||
.text(strLabel)
|
||
.data('comId', intComId)
|
||
.appendTo($list);
|
||
});
|
||
$list.removeClass('d-none');
|
||
}
|
||
|
||
$in.on('input', function() {
|
||
var q = $.trim(this.value);
|
||
$list.addClass('d-none').empty();
|
||
if (q.length < 2) {
|
||
return;
|
||
}
|
||
clearTimeout(timer);
|
||
timer = setTimeout(function() {
|
||
if (xhr) {
|
||
xhr.abort();
|
||
}
|
||
xhr = $.getJSON('ajax_newpromoteur.php', { action: 'search_email', q: q, eve_id: 0 }, renderComptePick)
|
||
.fail(function() { renderComptePick([]); });
|
||
}, 200);
|
||
});
|
||
|
||
$list.on('click', '.list-group-item', function(e) {
|
||
e.preventDefault();
|
||
var intComId = $(this).data('comId');
|
||
if (!intComId) {
|
||
return;
|
||
}
|
||
window.location.href = compteAccesUrl(intComId);
|
||
});
|
||
|
||
$(document).on('click', function(e) {
|
||
if (!$(e.target).closest($wrap).length) {
|
||
$list.addClass('d-none');
|
||
}
|
||
});
|
||
})(jQuery);
|
||
</script>
|
||
<?php
|
||
}
|
||
|
||
/** IDs evenements depuis inscriptions_comptes.com_eve_promoteur (CSV). */
|
||
function fxEveAccesParseLegacyPromoteurCsv($strCsv)
|
||
{
|
||
$strCsv = trim((string)$strCsv);
|
||
if ($strCsv === '') {
|
||
return array();
|
||
}
|
||
|
||
$arrIds = array();
|
||
foreach (explode(',', $strCsv) as $strPart) {
|
||
$intId = intval(trim($strPart));
|
||
if ($intId > 0) {
|
||
$arrIds[$intId] = $intId;
|
||
}
|
||
}
|
||
|
||
return array_values($arrIds);
|
||
}
|
||
|
||
function fxEveAccesGetMigrationLegacyRoleId()
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return 0;
|
||
}
|
||
|
||
$intRoleId = intval($objDatabase->fxGetVar(
|
||
"SELECT role_id FROM inscriptions_eve_roles
|
||
WHERE role_code = 'migration_legacy' AND role_actif = 1
|
||
LIMIT 1"
|
||
));
|
||
|
||
return ($intRoleId > 0) ? $intRoleId : 0;
|
||
}
|
||
|
||
/** Le compte a-t-il deja le kit migration_legacy actif sur cet evenement ? */
|
||
function fxEveAccesComEventHasMigrationKit($intComId, $intEveId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return false;
|
||
}
|
||
|
||
$sql = "SELECT COUNT(*) FROM inscriptions_eve_acces ea
|
||
INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id
|
||
WHERE ea.com_id = " . intval($intComId) . "
|
||
AND ea.eve_id = " . intval($intEveId) . "
|
||
AND ea.ea_statut = 'actif'
|
||
AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW())
|
||
AND r.role_code = 'migration_legacy'";
|
||
$intNb = $objDatabase->fxGetVar($sql);
|
||
|
||
return ($intNb != null && intval($intNb) > 0);
|
||
}
|
||
|
||
/**
|
||
* Tampon historique migration legacy (ponctuelle) par compte × evenement.
|
||
* Ne depend pas du kit migration_legacy encore actif — journal + note de migration.
|
||
*
|
||
* @return array<int, string> eve_id => migrated_at (datetime)
|
||
*/
|
||
function fxEveAccesLegacyMigratedMapForCom($intComId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
static $arrCache = array();
|
||
|
||
$intComId = intval($intComId);
|
||
if ($intComId <= 0) {
|
||
return array();
|
||
}
|
||
|
||
if (isset($arrCache[$intComId])) {
|
||
return $arrCache[$intComId];
|
||
}
|
||
|
||
$arrCache[$intComId] = array();
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return $arrCache[$intComId];
|
||
}
|
||
|
||
$sql = "SELECT l.eve_id, MIN(l.log_created_at) AS migrated_at
|
||
FROM inscriptions_eve_acces_log l
|
||
INNER JOIN inscriptions_eve_roles r ON r.role_id = l.role_id
|
||
AND r.role_code = 'migration_legacy'
|
||
WHERE l.com_id = $intComId
|
||
AND l.log_action IN ('legacy_migrated', 'create')
|
||
GROUP BY l.eve_id";
|
||
$tab = $objDatabase->fxGetResults($sql);
|
||
|
||
if ($tab != null) {
|
||
foreach ($tab as $row) {
|
||
$intEveId = intval($row['eve_id']);
|
||
if ($intEveId > 0) {
|
||
$arrCache[$intComId][$intEveId] = (string)$row['migrated_at'];
|
||
}
|
||
}
|
||
}
|
||
|
||
$sqlNote = "SELECT eve_id, MIN(ea_created_at) AS migrated_at
|
||
FROM inscriptions_eve_acces
|
||
WHERE com_id = $intComId
|
||
AND ea_note LIKE 'Migration depuis com_eve_promoteur%'
|
||
GROUP BY eve_id";
|
||
$tabNote = $objDatabase->fxGetResults($sqlNote);
|
||
|
||
if ($tabNote != null) {
|
||
foreach ($tabNote as $row) {
|
||
$intEveId = intval($row['eve_id']);
|
||
if ($intEveId > 0 && !isset($arrCache[$intComId][$intEveId])) {
|
||
$arrCache[$intComId][$intEveId] = (string)$row['migrated_at'];
|
||
}
|
||
}
|
||
}
|
||
|
||
$sqlEa = "SELECT ea.eve_id, MIN(ea.ea_created_at) AS migrated_at
|
||
FROM inscriptions_eve_acces ea
|
||
INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id
|
||
AND r.role_code = 'migration_legacy'
|
||
WHERE ea.com_id = $intComId
|
||
GROUP BY ea.eve_id";
|
||
$tabEa = $objDatabase->fxGetResults($sqlEa);
|
||
|
||
if ($tabEa != null) {
|
||
foreach ($tabEa as $row) {
|
||
$intEveId = intval($row['eve_id']);
|
||
if ($intEveId > 0 && !isset($arrCache[$intComId][$intEveId])) {
|
||
$arrCache[$intComId][$intEveId] = (string)$row['migrated_at'];
|
||
}
|
||
}
|
||
}
|
||
|
||
return $arrCache[$intComId];
|
||
}
|
||
|
||
/** Migration legacy deja effectuee pour cet evenement (tampon ponctuel, pas etat temps reel). */
|
||
function fxEveAccesComEventWasLegacyMigrated($intComId, $intEveId, $arrMigratedMap = null)
|
||
{
|
||
$intComId = intval($intComId);
|
||
$intEveId = intval($intEveId);
|
||
|
||
if ($intComId <= 0 || $intEveId <= 0) {
|
||
return false;
|
||
}
|
||
|
||
if ($arrMigratedMap === null) {
|
||
$arrMigratedMap = fxEveAccesLegacyMigratedMapForCom($intComId);
|
||
}
|
||
|
||
return isset($arrMigratedMap[$intEveId]);
|
||
}
|
||
|
||
/**
|
||
* Etat migration legacy → v2 pour un compte (lecture inscriptions_comptes.com_eve_promoteur).
|
||
*
|
||
* @return array{com_id:int,legacy_csv:string,role_id:int,events:array,pending_count:int,migrated_count:int}
|
||
*/
|
||
function fxEveAccesMigrationStatusForCom($intComId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
$intComId = intval($intComId);
|
||
$arrOut = array(
|
||
'com_id' => $intComId,
|
||
'legacy_csv' => '',
|
||
'role_id' => fxEveAccesGetMigrationLegacyRoleId(),
|
||
'events' => array(),
|
||
'pending_count' => 0,
|
||
'migrated_count' => 0,
|
||
);
|
||
|
||
if (!fxEveAccesIsEnabled() || $intComId <= 0) {
|
||
return $arrOut;
|
||
}
|
||
|
||
$row = $objDatabase->fxGetRow(
|
||
"SELECT com_id, com_eve_promoteur FROM inscriptions_comptes WHERE com_id = $intComId LIMIT 1"
|
||
);
|
||
if ($row === null) {
|
||
return $arrOut;
|
||
}
|
||
|
||
$arrOut['legacy_csv'] = trim((string)($row['com_eve_promoteur'] ?? ''));
|
||
$arrEveIds = fxEveAccesParseLegacyPromoteurCsv($arrOut['legacy_csv']);
|
||
|
||
if (empty($arrEveIds)) {
|
||
return $arrOut;
|
||
}
|
||
|
||
$sql = "SELECT eve_id, eve_nom_fr FROM inscriptions_evenements
|
||
WHERE eve_id IN (" . implode(',', array_map('intval', $arrEveIds)) . ")";
|
||
$tabEve = $objDatabase->fxGetResults($sql);
|
||
$arrEveNames = array();
|
||
if ($tabEve != null) {
|
||
foreach ($tabEve as $rowEve) {
|
||
$arrEveNames[intval($rowEve['eve_id'])] = $rowEve['eve_nom_fr'];
|
||
}
|
||
}
|
||
|
||
$arrMigratedMap = fxEveAccesLegacyMigratedMapForCom($intComId);
|
||
|
||
foreach ($arrEveIds as $intEveId) {
|
||
$blnMigrated = fxEveAccesComEventWasLegacyMigrated($intComId, $intEveId, $arrMigratedMap);
|
||
$arrOut['events'][] = array(
|
||
'eve_id' => $intEveId,
|
||
'eve_nom_fr' => $arrEveNames[$intEveId] ?? ('Événement #' . $intEveId),
|
||
'migrated' => $blnMigrated,
|
||
'migrated_at' => $arrMigratedMap[$intEveId] ?? null,
|
||
);
|
||
if ($blnMigrated) {
|
||
$arrOut['migrated_count']++;
|
||
} else {
|
||
$arrOut['pending_count']++;
|
||
}
|
||
}
|
||
|
||
return $arrOut;
|
||
}
|
||
|
||
/**
|
||
* Cree les acces v2 (kit migration_legacy) pour chaque evenement du promoteur legacy.
|
||
*
|
||
* @return array{state:string,message:string,granted:int,skipped:int,errors:array}
|
||
*/
|
||
function fxEveAccesMigrateCompteFromLegacy($intComId, $intGrantedBy = 0)
|
||
{
|
||
$arrStatus = fxEveAccesMigrationStatusForCom($intComId);
|
||
$intRoleId = intval($arrStatus['role_id']);
|
||
|
||
if ($intRoleId <= 0) {
|
||
return array(
|
||
'state' => 'error',
|
||
'message' => 'Kit migration_legacy introuvable. Executer sql/MSIN-eve-acces-v2-phase4-role-grants-all.sql',
|
||
'granted' => 0,
|
||
'skipped' => 0,
|
||
'errors' => array(),
|
||
);
|
||
}
|
||
|
||
if ($arrStatus['legacy_csv'] === '') {
|
||
return array(
|
||
'state' => 'error',
|
||
'message' => 'Aucun evenement dans com_eve_promoteur (inscriptions_comptes).',
|
||
'granted' => 0,
|
||
'skipped' => 0,
|
||
'errors' => array(),
|
||
);
|
||
}
|
||
|
||
$intGranted = 0;
|
||
$intSkipped = 0;
|
||
$arrErrors = array();
|
||
|
||
foreach ($arrStatus['events'] as $arrEvent) {
|
||
$intEveId = intval($arrEvent['eve_id']);
|
||
if (!empty($arrEvent['migrated'])) {
|
||
$intSkipped++;
|
||
continue;
|
||
}
|
||
|
||
$arrResult = fxEveAccesGrant(
|
||
$intComId,
|
||
$intEveId,
|
||
$intRoleId,
|
||
0,
|
||
$intGrantedBy,
|
||
'Migration depuis com_eve_promoteur'
|
||
);
|
||
|
||
if (($arrResult['state'] ?? '') === 'success') {
|
||
$intGranted++;
|
||
fxEveAccesWriteLog(
|
||
intval($arrResult['ea_id'] ?? 0),
|
||
$intComId,
|
||
$intEveId,
|
||
$intRoleId,
|
||
'legacy_migrated',
|
||
'Migration promoteur legacy (ponctuelle)',
|
||
$intGrantedBy
|
||
);
|
||
} else {
|
||
$arrErrors[] = '#' . $intEveId . ': ' . ($arrResult['message'] ?? 'erreur');
|
||
}
|
||
}
|
||
|
||
if (!empty($arrErrors)) {
|
||
return array(
|
||
'state' => 'error',
|
||
'message' => $intGranted . ' migre(s), ' . count($arrErrors) . ' erreur(s).',
|
||
'granted' => $intGranted,
|
||
'skipped' => $intSkipped,
|
||
'errors' => $arrErrors,
|
||
);
|
||
}
|
||
|
||
if ($intGranted === 0 && $intSkipped > 0) {
|
||
return array(
|
||
'state' => 'success',
|
||
'message' => 'Deja migre : tampon historique en place pour tous les evenements legacy.',
|
||
'granted' => 0,
|
||
'skipped' => $intSkipped,
|
||
'errors' => array(),
|
||
);
|
||
}
|
||
|
||
return array(
|
||
'state' => 'success',
|
||
'message' => $intGranted . ' evenement(s) migre(s)'
|
||
. ($intSkipped > 0 ? ', ' . $intSkipped . ' deja en place' : '') . '.',
|
||
'granted' => $intGranted,
|
||
'skipped' => $intSkipped,
|
||
'errors' => array(),
|
||
);
|
||
}
|
||
|
||
/** Tous les comptes avec com_eve_promoteur non vide. */
|
||
function fxEveAccesMigrationListAllLegacyComptes()
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return array();
|
||
}
|
||
|
||
$sql = "SELECT com_id, com_nom, com_prenom, com_courriel, com_eve_promoteur
|
||
FROM inscriptions_comptes
|
||
WHERE com_eve_promoteur IS NOT NULL
|
||
AND TRIM(com_eve_promoteur) <> ''
|
||
ORDER BY com_nom ASC, com_prenom ASC";
|
||
$tab = $objDatabase->fxGetResults($sql);
|
||
|
||
return ($tab != null) ? $tab : array();
|
||
}
|
||
|
||
/** @deprecated Utiliser fxEveAccesMigrationListAllLegacyComptes + filtre pending si besoin. */
|
||
function fxEveAccesMigrationListComptesPending()
|
||
{
|
||
$arrRows = array();
|
||
|
||
foreach (fxEveAccesMigrationListAllLegacyComptes() as $row) {
|
||
$arrStatus = fxEveAccesMigrationStatusForCom(intval($row['com_id']));
|
||
if ($arrStatus['pending_count'] <= 0) {
|
||
continue;
|
||
}
|
||
$arrRows[] = array(
|
||
'com_id' => intval($row['com_id']),
|
||
'com_nom' => $row['com_nom'],
|
||
'com_prenom' => $row['com_prenom'],
|
||
'com_courriel' => $row['com_courriel'],
|
||
'legacy_csv' => $arrStatus['legacy_csv'],
|
||
'pending_count' => $arrStatus['pending_count'],
|
||
'migrated_count' => $arrStatus['migrated_count'],
|
||
'event_count' => count($arrStatus['events']),
|
||
);
|
||
}
|
||
|
||
return $arrRows;
|
||
}
|
||
|
||
/** Nombre d'evenements legacy encore sans tampon migration (tous comptes). */
|
||
function fxEveAccesMigrationCountPendingEvents()
|
||
{
|
||
$intPending = 0;
|
||
|
||
foreach (fxEveAccesMigrationListAllLegacyComptes() as $row) {
|
||
$arrStatus = fxEveAccesMigrationStatusForCom(intval($row['com_id']));
|
||
$intPending += intval($arrStatus['pending_count']);
|
||
}
|
||
|
||
return $intPending;
|
||
}
|
||
|
||
/** Totaux migration legacy (affichage super admin). */
|
||
function fxEveAccesMigrationGetStats()
|
||
{
|
||
global $objDatabase;
|
||
|
||
$arrOut = array(
|
||
'total_legacy' => 0,
|
||
'pending_events' => 0,
|
||
);
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
return $arrOut;
|
||
}
|
||
|
||
$arrOut['total_legacy'] = count(fxEveAccesMigrationListAllLegacyComptes());
|
||
$arrOut['pending_events'] = fxEveAccesMigrationCountPendingEvents();
|
||
|
||
return $arrOut;
|
||
}
|
||
|
||
function fxEveAccesShowCompteForm($intComId)
|
||
{
|
||
global $objDatabase;
|
||
|
||
if (!fxEveAccesIsEnabled()) {
|
||
echo '<div class="alert alert-warning">Tables acces v2 non installees. Executer les SQL MSIN-eve-acces-v2-phase1.</div>';
|
||
return;
|
||
}
|
||
|
||
$arrAcces = fxEveAccesListByComId($intComId);
|
||
$arrExtras = fxEveAccesListExtraByComId($intComId);
|
||
$arrRoles = fxEveAccesGetRoles(true);
|
||
// MSIN-4485 — extras = actions ; clés hors kit total en tête de liste.
|
||
$arrActionPerms = fxEveAccesGetCatalogPermissions('action');
|
||
if ($arrActionPerms != null && is_array($arrActionPerms)) {
|
||
usort($arrActionPerms, function ($a, $b) {
|
||
$intA = isset($a['perm_grants_all']) ? intval($a['perm_grants_all']) : 1;
|
||
$intB = isset($b['perm_grants_all']) ? intval($b['perm_grants_all']) : 1;
|
||
if ($intA !== $intB) {
|
||
return $intA <=> $intB; // 0 (hors total) avant 1
|
||
}
|
||
return strcmp((string)($a['perm_label_fr'] ?? ''), (string)($b['perm_label_fr'] ?? ''));
|
||
});
|
||
}
|
||
$strT = urlencode($_GET['t'] ?? '');
|
||
$intComId = intval($intComId);
|
||
|
||
global $vDomaine;
|
||
|
||
$arrAccesRevoke = array();
|
||
$arrExtrasRevoke = array();
|
||
|
||
if ($arrAcces != null) {
|
||
foreach ($arrAcces as $row) {
|
||
if (!fxEveAccesRowIsActif($row)) {
|
||
if (($row['ea_statut'] ?? '') === 'revoke') {
|
||
$arrAccesRevoke[] = $row;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if ($arrExtras != null) {
|
||
foreach ($arrExtras as $row) {
|
||
if (($row['ae_statut'] ?? '') !== 'actif') {
|
||
$arrExtrasRevoke[] = $row;
|
||
}
|
||
}
|
||
}
|
||
|
||
$arrGroups = fxEveAccesCompteFormGroupByEvent($arrAcces, $arrExtras);
|
||
|
||
$intFocusEveId = intval($_GET['eve_acces_focus'] ?? 0);
|
||
$strFocusEveNom = '';
|
||
if ($intFocusEveId > 0) {
|
||
$tabFocusEve = $objDatabase->fxGetRow(
|
||
"SELECT eve_nom_fr FROM inscriptions_evenements WHERE eve_id = $intFocusEveId LIMIT 1"
|
||
);
|
||
if ($tabFocusEve != null) {
|
||
$strFocusEveNom = $tabFocusEve['eve_nom_fr'];
|
||
} else {
|
||
$intFocusEveId = 0;
|
||
}
|
||
}
|
||
|
||
$strRoleOptions = '<option value="">—</option>';
|
||
if ($arrRoles != null) {
|
||
foreach ($arrRoles as $rowRole) {
|
||
$strRoleOptions .= '<option value="' . intval($rowRole['role_id']) . '">'
|
||
. htmlspecialchars($rowRole['role_label_fr'], ENT_QUOTES, 'UTF-8') . '</option>';
|
||
}
|
||
}
|
||
|
||
$strPermOptions = '<option value="">—</option>';
|
||
if ($arrActionPerms != null) {
|
||
foreach ($arrActionPerms as $rowPerm) {
|
||
$blnHorsTotal = isset($rowPerm['perm_grants_all']) && intval($rowPerm['perm_grants_all']) === 0;
|
||
$strLabel = (string)($rowPerm['perm_label_fr'] ?? $rowPerm['perm_key']);
|
||
if ($blnHorsTotal) {
|
||
$strLabel = '★ ' . $strLabel . ' (hors kit total)';
|
||
}
|
||
$strPermOptions .= '<option value="' . htmlspecialchars($rowPerm['perm_key'], ENT_QUOTES, 'UTF-8') . '">'
|
||
. htmlspecialchars($strLabel, ENT_QUOTES, 'UTF-8') . '</option>';
|
||
}
|
||
}
|
||
require_once __DIR__ . '/inc_fx_superadm_v2_ui.php';
|
||
|
||
fxSuperadmV2PanelOpen('Accès aux événements', array(
|
||
'zone_id' => 'eve-acces-v2',
|
||
'zone_class' => 'superadm-content-v2-zone mt-4 mb-3',
|
||
));
|
||
?>
|
||
<p class="text-muted small mb-2">
|
||
<a href="<?= htmlspecialchars($vDomaine, ENT_QUOTES, 'UTF-8') ?>/superadm/eve_acces.php?p=kits">Gérer les kits</a>
|
||
</p>
|
||
|
||
<table class="table table-sm table-striped mb-2">
|
||
<thead>
|
||
<tr>
|
||
<th style="width:32%">Événement</th>
|
||
<th>Assigné</th>
|
||
<th class="text-right text-nowrap" style="width:130px">Ajouter un kit</th>
|
||
<th class="text-right text-nowrap" style="width:130px">Ajouter un droit</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php
|
||
if (count($arrGroups) === 0) {
|
||
echo '<tr><td colspan="4" class="text-muted">Aucun accès.</td></tr>';
|
||
} else {
|
||
foreach ($arrGroups as $arrGroup) {
|
||
$intEveId = intval($arrGroup['eve_id']);
|
||
$blnHasKit = count($arrGroup['kits']) > 0;
|
||
?>
|
||
<tr>
|
||
<td class="align-middle">
|
||
<strong><?= htmlspecialchars($arrGroup['eve_nom_fr'], ENT_QUOTES, 'UTF-8') ?></strong>
|
||
<span class="text-muted small">(#<?= $intEveId ?>)</span>
|
||
</td>
|
||
<td class="align-middle">
|
||
<?php
|
||
if (!$blnHasKit && count($arrGroup['extras']) === 0) {
|
||
echo '<span class="text-muted">—</span>';
|
||
} else {
|
||
foreach ($arrGroup['kits'] as $rowKit) { ?>
|
||
<span class="badge badge-primary mr-1 mb-1 py-1 px-2">
|
||
<?= htmlspecialchars($rowKit['role_label_fr'], ENT_QUOTES, 'UTF-8') ?>
|
||
<a href="index.php?t=<?= $strT ?>&a=mod&id=<?= $intComId ?>&action=revokeveacces&ea_id=<?= intval($rowKit['ea_id']) ?>"
|
||
class="text-white ml-1"
|
||
title="Retirer ce kit"
|
||
onclick="return confirm('Retirer ce kit ?');">×</a>
|
||
</span>
|
||
<?php }
|
||
foreach ($arrGroup['extras'] as $rowExtra) { ?>
|
||
<span class="badge mr-1 mb-1 py-1 px-2" style="background-color:#e67e22;color:#fff;">
|
||
<?= htmlspecialchars($rowExtra['perm_label_fr'], ENT_QUOTES, 'UTF-8') ?>
|
||
<a href="index.php?t=<?= $strT ?>&a=mod&id=<?= $intComId ?>&action=revokeveaccesextra&ae_id=<?= intval($rowExtra['ae_id']) ?>"
|
||
class="text-white ml-1"
|
||
title="Retirer ce droit"
|
||
onclick="return confirm('Retirer ce droit ?');">×</a>
|
||
</span>
|
||
<?php }
|
||
}
|
||
?>
|
||
</td>
|
||
<td class="align-middle text-right text-nowrap">
|
||
<select id="eve-role-<?= $intEveId ?>" class="custom-select custom-select-sm d-inline-block" style="width:96px;vertical-align:middle;" aria-label="Kit">
|
||
<?= $strRoleOptions ?>
|
||
</select>
|
||
<button type="button" class="btn btn-outline-primary btn-sm py-0 btn-eve-add-kit" data-eve-id="<?= $intEveId ?>" title="Ajouter un kit">+</button>
|
||
</td>
|
||
<td class="align-middle text-right text-nowrap">
|
||
<?php if ($blnHasKit) { ?>
|
||
<select id="eve-extra-<?= $intEveId ?>" class="custom-select custom-select-sm d-inline-block" style="width:220px;max-width:40vw;vertical-align:middle;" aria-label="Droit individuel">
|
||
<?= $strPermOptions ?>
|
||
</select>
|
||
<button type="button" class="btn btn-outline-warning btn-sm py-0 btn-eve-add-extra" data-eve-id="<?= $intEveId ?>" title="Ajouter un droit individuel" style="border-color:#e67e22;color:#e67e22;">+</button>
|
||
<?php } else { ?>
|
||
<span class="text-muted small">—</span>
|
||
<?php } ?>
|
||
</td>
|
||
</tr>
|
||
<?php
|
||
}
|
||
}
|
||
?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<details class="mb-2">
|
||
<summary class="small" style="cursor:pointer;">Ajouter un événement</summary>
|
||
<div class="border rounded p-2 mt-2 bg-light">
|
||
<div class="form-row align-items-end">
|
||
<div class="form-group col-md-5 mb-2">
|
||
<label class="small mb-0" for="pp-eve-acces-v2">Événement</label>
|
||
<div id="pick-eve-acces-v2">
|
||
<input id="pp-eve-acces-v2" type="text" class="form-control form-control-sm" placeholder="Rechercher…" autocomplete="off">
|
||
<input type="hidden" id="pp-eve-acces-v2-id" value="">
|
||
<!-- MSIN-4457 — En flux (pas absolute) pour eviter le clip du parent ; hauteur utile. -->
|
||
<div id="pp-results-eve-acces-v2" class="list-group d-none mt-1"
|
||
style="max-height:min(60vh, 480px);overflow:auto;border:1px solid #ced4da;"></div>
|
||
</div>
|
||
</div>
|
||
<div class="form-group col-md-3 mb-2">
|
||
<label class="small mb-0" for="pp-eve-acces-v2-role">Kit</label>
|
||
<select id="pp-eve-acces-v2-role" class="form-control form-control-sm">
|
||
<option value="">— Choisir —</option>
|
||
<?php
|
||
if ($arrRoles != null) {
|
||
foreach ($arrRoles as $row) {
|
||
echo '<option value="' . intval($row['role_id']) . '">'
|
||
. htmlspecialchars($row['role_label_fr']) . '</option>';
|
||
}
|
||
}
|
||
?>
|
||
</select>
|
||
</div>
|
||
<div class="form-group col-md-2 mb-2">
|
||
<!-- MSIN-4457 — Libelle explicite (ex. J. trop opaque). -->
|
||
<label class="small mb-0" for="pp-eve-acces-v2-days" title="Vide = sans expiration">Jours</label>
|
||
<input type="number" id="pp-eve-acces-v2-days" class="form-control form-control-sm" min="0" placeholder="∞">
|
||
</div>
|
||
<div class="form-group col-md-2 mb-2">
|
||
<button type="button" class="btn btn-success btn-sm btn-block" id="btn-eve-acces-v2-add">
|
||
<i class="fa fa-plus"></i> Ajouter
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</details>
|
||
|
||
<?php if (count($arrAccesRevoke) > 0 || count($arrExtrasRevoke) > 0) { ?>
|
||
<details class="mb-3">
|
||
<summary class="text-muted small" style="cursor:pointer;">
|
||
Historique — kits et permissions retirés
|
||
(<?= count($arrAccesRevoke) + count($arrExtrasRevoke) ?>)
|
||
</summary>
|
||
<table class="table table-sm table-borderless mt-2 mb-0">
|
||
<tbody>
|
||
<?php foreach ($arrAccesRevoke as $row) { ?>
|
||
<tr class="text-muted">
|
||
<td><?= htmlspecialchars($row['eve_nom_fr'] ?? ('#' . $row['eve_id']), ENT_QUOTES, 'UTF-8') ?></td>
|
||
<td>Kit : <?= htmlspecialchars($row['role_label_fr'], ENT_QUOTES, 'UTF-8') ?></td>
|
||
<td class="text-right">
|
||
<a href="index.php?t=<?= $strT ?>&a=mod&id=<?= $intComId ?>&action=reactivateveacces&ea_id=<?= intval($row['ea_id']) ?>"
|
||
class="btn btn-sm btn-outline-success">Réactiver</a>
|
||
</td>
|
||
</tr>
|
||
<?php } ?>
|
||
<?php foreach ($arrExtrasRevoke as $row) { ?>
|
||
<tr class="text-muted">
|
||
<td><?= htmlspecialchars($row['eve_nom_fr'] ?? ('#' . $row['eve_id']), ENT_QUOTES, 'UTF-8') ?></td>
|
||
<td><?= htmlspecialchars($row['perm_label_fr'], ENT_QUOTES, 'UTF-8') ?></td>
|
||
<td class="text-right">
|
||
<a href="index.php?t=<?= $strT ?>&a=mod&id=<?= $intComId ?>&action=reactivateveaccesextra&ae_id=<?= intval($row['ae_id']) ?>"
|
||
class="btn btn-sm btn-outline-success">Réactiver</a>
|
||
</td>
|
||
</tr>
|
||
<?php } ?>
|
||
</tbody>
|
||
</table>
|
||
</details>
|
||
<?php } ?>
|
||
|
||
<script>
|
||
(function($){
|
||
function renderEvePick($box, items){
|
||
$box.empty();
|
||
if (!items || !items.length){
|
||
$box.addClass('d-none');
|
||
return;
|
||
}
|
||
items.forEach(function(it){
|
||
var id = it.eve_id || it.eveId || it.id;
|
||
var label = it.eve_nom_fr || it.nom || ('#' + id);
|
||
$('<a href="#" class="list-group-item list-group-item-action"></a>')
|
||
.text(label + ' (#' + id + ')')
|
||
.data('item', it)
|
||
.appendTo($box);
|
||
});
|
||
$box.removeClass('d-none');
|
||
}
|
||
|
||
function bindEveSearch(inputSel, resultsSel, hiddenSel){
|
||
var timer = null, xhr = null;
|
||
$(inputSel).on('input', function(){
|
||
var q = $(this).val().trim();
|
||
var $box = $(resultsSel);
|
||
if (q.length < 2) {
|
||
$box.addClass('d-none').empty();
|
||
return;
|
||
}
|
||
clearTimeout(timer);
|
||
timer = setTimeout(function(){
|
||
if (xhr) xhr.abort();
|
||
xhr = $.getJSON('ajax_newpromoteur.php', { action: 'search_evenement', q: q }, function(items){
|
||
renderEvePick($box, items);
|
||
}).fail(function(){ renderEvePick($box, []); });
|
||
}, 200);
|
||
});
|
||
|
||
$(resultsSel).on('click', '.list-group-item', function(e){
|
||
e.preventDefault();
|
||
var item = $(this).data('item') || {};
|
||
var id = item.eve_id || item.eveId || item.id;
|
||
var label = item.eve_nom_fr || $(this).text();
|
||
$(hiddenSel).val(id);
|
||
$(inputSel).val(label);
|
||
$(resultsSel).addClass('d-none').empty();
|
||
});
|
||
}
|
||
|
||
bindEveSearch('#pp-eve-acces-v2', '#pp-results-eve-acces-v2', '#pp-eve-acces-v2-id');
|
||
|
||
$('#btn-eve-acces-v2-add').on('click', function(){
|
||
var eveId = $('#pp-eve-acces-v2-id').val();
|
||
var roleId = $('#pp-eve-acces-v2-role').val();
|
||
var days = $('#pp-eve-acces-v2-days').val() || 0;
|
||
if (!eveId || !roleId) {
|
||
alert('Choisir un événement et un kit.');
|
||
return;
|
||
}
|
||
var p = new URLSearchParams(window.location.search);
|
||
window.location.href = 'index.php'
|
||
+ '?t=' + encodeURIComponent(p.get('t') || '')
|
||
+ '&a=mod'
|
||
+ '&id=' + encodeURIComponent(p.get('id') || '0')
|
||
+ '&action=addeveacces'
|
||
+ '&evenement_id=' + encodeURIComponent(eveId)
|
||
+ '&role_id=' + encodeURIComponent(roleId)
|
||
+ '&expire_days=' + encodeURIComponent(days)
|
||
+ '#eve-acces-v2';
|
||
});
|
||
|
||
$('.btn-eve-add-kit').on('click', function(){
|
||
var intEveId = $(this).data('eveId');
|
||
var roleId = $('#eve-role-' + intEveId).val();
|
||
if (!roleId) {
|
||
alert('Choisir un kit.');
|
||
return;
|
||
}
|
||
var p = new URLSearchParams(window.location.search);
|
||
window.location.href = 'index.php'
|
||
+ '?t=' + encodeURIComponent(p.get('t') || '')
|
||
+ '&a=mod'
|
||
+ '&id=' + encodeURIComponent(p.get('id') || '0')
|
||
+ '&action=addeveacces'
|
||
+ '&evenement_id=' + encodeURIComponent(intEveId)
|
||
+ '&role_id=' + encodeURIComponent(roleId)
|
||
+ '&expire_days=0'
|
||
+ '#eve-acces-v2';
|
||
});
|
||
|
||
$('.btn-eve-add-extra').on('click', function(){
|
||
var intEveId = $(this).data('eveId');
|
||
var permKey = $('#eve-extra-' + intEveId).val();
|
||
if (!permKey) {
|
||
alert('Choisir un droit.');
|
||
return;
|
||
}
|
||
var p = new URLSearchParams(window.location.search);
|
||
window.location.href = 'index.php'
|
||
+ '?t=' + encodeURIComponent(p.get('t') || '')
|
||
+ '&a=mod'
|
||
+ '&id=' + encodeURIComponent(p.get('id') || '0')
|
||
+ '&action=addeveaccesextra'
|
||
+ '&evenement_id=' + encodeURIComponent(intEveId)
|
||
+ '&perm_key=' + encodeURIComponent(permKey)
|
||
+ '#eve-acces-v2';
|
||
});
|
||
|
||
(function(){
|
||
var focusEve = <?= $intFocusEveId ?>;
|
||
var focusNom = <?= json_encode($strFocusEveNom, JSON_UNESCAPED_UNICODE) ?>;
|
||
if (focusEve <= 0) {
|
||
return;
|
||
}
|
||
var $sel = $('#eve-role-' + focusEve);
|
||
if (!$sel.length) {
|
||
$sel = $('#eve-extra-' + focusEve);
|
||
}
|
||
if ($sel.length) {
|
||
var $row = $sel.closest('tr');
|
||
setTimeout(function(){
|
||
$('html, body').animate({ scrollTop: $row.offset().top - 100 }, 300);
|
||
$row.addClass('table-info');
|
||
setTimeout(function(){ $row.removeClass('table-info'); }, 2500);
|
||
}, 100);
|
||
return;
|
||
}
|
||
if (focusNom) {
|
||
var $det = $('details').has('#pp-eve-acces-v2').first();
|
||
if ($det.length) {
|
||
$det.prop('open', true);
|
||
$('#pp-eve-acces-v2-id').val(String(focusEve));
|
||
$('#pp-eve-acces-v2').val(focusNom + ' (#' + focusEve + ')');
|
||
setTimeout(function(){
|
||
$('html, body').animate({ scrollTop: $det.offset().top - 100 }, 300);
|
||
}, 100);
|
||
}
|
||
}
|
||
})();
|
||
})(jQuery);
|
||
</script>
|
||
<?php
|
||
fxSuperadmV2PanelClose();
|
||
}
|
||
|
||
/**
|
||
* Badge cadenas droits v2 (visible si super admin + mode inspecteur actif).
|
||
*/
|
||
function fxEveAccesPermInspectBadge($strPermKey, $strContext = 'v2')
|
||
{
|
||
if (!function_exists('fxAdminPermInspectModeActive') || !fxAdminPermInspectModeActive()) {
|
||
return '';
|
||
}
|
||
|
||
$strPermKey = trim((string)$strPermKey);
|
||
if ($strPermKey === '') {
|
||
return '';
|
||
}
|
||
|
||
$strTitle = ($strContext !== '' ? $strContext . ' — ' : '') . $strPermKey;
|
||
|
||
return '<span class="ms1-perm-inspect-badge" title="' . htmlspecialchars($strTitle, ENT_QUOTES, 'UTF-8') . '">'
|
||
. '<i class="fa fa-lock" aria-hidden="true"></i> '
|
||
. '<code>' . htmlspecialchars($strPermKey, ENT_QUOTES, 'UTF-8') . '</code></span>';
|
||
}
|
||
|
||
/** Attributs HTML zone inspectee (data-ms1-perm). */
|
||
function fxEveAccesPermInspectZoneAttr($strPermKey)
|
||
{
|
||
if (!function_exists('fxAdminPermInspectModeActive') || !fxAdminPermInspectModeActive()) {
|
||
return '';
|
||
}
|
||
|
||
$strPermKey = trim((string)$strPermKey);
|
||
if ($strPermKey === '') {
|
||
return '';
|
||
}
|
||
|
||
return ' class="ms1-perm-inspect-zone" data-ms1-perm="'
|
||
. htmlspecialchars($strPermKey, ENT_QUOTES, 'UTF-8') . '"';
|
||
}
|
||
|
||
/**
|
||
* En mode inspecteur : badge apres un controle visible, ou seul si le controle est masque.
|
||
*/
|
||
function fxEveAccesPermInspectMark($strPermKey, $strHtml = '', $strContext = 'v2')
|
||
{
|
||
if (!function_exists('fxAdminPermInspectModeActive') || !fxAdminPermInspectModeActive()) {
|
||
return $strHtml;
|
||
}
|
||
|
||
$strBadge = fxEveAccesPermInspectBadge($strPermKey, $strContext);
|
||
if ($strHtml === '') {
|
||
return '<span class="ms1-perm-inspect-slot">' . $strBadge . '</span>';
|
||
}
|
||
|
||
return $strHtml . ' ' . $strBadge;
|
||
}
|