diff --git a/inc_tableau_eve_acces.php b/inc_tableau_eve_acces.php
index 5c759e6..a8b8bf6 100644
--- a/inc_tableau_eve_acces.php
+++ b/inc_tableau_eve_acces.php
@@ -16,16 +16,54 @@ if (isset($_GET['promoteur_eve_id'])) {
$intEveId = intval(base64_decode(urldecode($_GET['promoteur_eve_id'])));
}
-$strRedirect = $vDomaine . (($strLangue === 'en') ? '/account' : '/compte');
+$strLangue = ($strLangue === 'en') ? 'en' : 'fr';
+$strBasePath = ($strLangue === 'en') ? '/account' : '/compte';
+$strRedirect = $vDomaine . $strBasePath;
if (!empty($_GET['promoteur_eve_id'])) {
$strRedirect .= '/inc_tableau_promoteur?promoteur_eve_id=' . urlencode($_GET['promoteur_eve_id']);
}
+$intActor = intval($_SESSION['com_id'] ?? 0);
+if (!empty($_SESSION['usa_id'])) {
+ $intActor = intval($_SESSION['usa_id']);
+}
+
if ($intEveId <= 0
|| (empty($_SESSION['com_id']) && empty($_SESSION['usa_id']))
- || !fxEveAccesCanTeamInvite($_SESSION['com_id'] ?? 0, $intEveId)) {
+ || !fxEveAccesCanTeamInvite($intActor, $intEveId)) {
header('Location: ' . $strRedirect);
exit;
}
-fxEveAccesPromoteurRenderPage($intEveId, $strLangue);
+$strFlash = '';
+$strError = '';
+$strSelfUrl = $vDomaine . $strBasePath . '/inc_tableau_eve_acces?promoteur_eve_id='
+ . urlencode(base64_encode($intEveId)) . '&lng=' . $strLangue;
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ $strAction = (string)($_POST['eve_acces_action'] ?? '');
+
+ if ($strAction === 'invite') {
+ $arrResult = fxEveAccesPromoteurInvite($intEveId, $intActor, $_POST, $strLangue);
+ if (($arrResult['state'] ?? '') === 'success') {
+ header('Location: ' . $strSelfUrl . '&ok=' . urlencode($arrResult['message']));
+ exit;
+ }
+ $strError = $arrResult['message'] ?? fxEveAccesPromoteurT('eve_acces_promoteur_err_generic', $strLangue);
+ } elseif ($strAction === 'revoke') {
+ $arrResult = fxEveAccesPromoteurRevoke(intval($_POST['ea_id'] ?? 0), $intActor, $intEveId);
+ if (($arrResult['state'] ?? '') === 'success') {
+ header('Location: ' . $strSelfUrl . '&ok=' . urlencode(
+ fxEveAccesPromoteurT('eve_acces_promoteur_ok_revoked', $strLangue)
+ ));
+ exit;
+ }
+ $strError = fxEveAccesPromoteurT('eve_acces_promoteur_err_revoke', $strLangue);
+ }
+}
+
+if (!empty($_GET['ok'])) {
+ $strFlash = (string)$_GET['ok'];
+}
+
+fxEveAccesPromoteurRenderPage($intEveId, $strLangue, $strFlash, $strError);
diff --git a/php/inc_fx_eve_acces.php b/php/inc_fx_eve_acces.php
index 9dd299f..2277509 100644
--- a/php/inc_fx_eve_acces.php
+++ b/php/inc_fx_eve_acces.php
@@ -93,6 +93,74 @@ function fxEveAccesGetRoles($blnActifOnly = true)
return $objDatabase->fxGetResults($sql);
}
+/** Kits proposables par un promoteur (role_delegable = 1, hors migration_legacy). */
+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();
+ }
+
+ $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'
+ 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;
+ }
+
+ $row = $objDatabase->fxGetRow(
+ "SELECT role_id, role_code, role_delegable, role_actif
+ 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;
+ }
+
+ return intval($row['role_delegable'] ?? 0) === 1;
+}
+
+function fxEveAccesCanTeamManage($intComId, $intEveId)
+{
+ if (fxEveAccesIsSuperAdminSession()) {
+ return true;
+ }
+
+ 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)
{
@@ -121,7 +189,7 @@ function fxEveAccesListByEveId($intEveId, $blnActifOnly = true)
}
$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_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
FROM inscriptions_eve_acces ea
@@ -697,9 +765,19 @@ function fxEveAccesGrant($intComId, $intEveId, $intRoleId, $intExpireDays, $intG
$intEaId = intval($objDatabase->fxGetVar(
"SELECT ea_id FROM inscriptions_eve_acces
- WHERE com_id = $intComId AND eve_id = $intEveId LIMIT 1"
+ 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');
}
diff --git a/php/inc_fx_eve_acces_promoteur.php b/php/inc_fx_eve_acces_promoteur.php
index d68bcd5..720ffb4 100644
--- a/php/inc_fx_eve_acces_promoteur.php
+++ b/php/inc_fx_eve_acces_promoteur.php
@@ -33,6 +33,43 @@ function fxEveAccesPromoteurT($strClef, $strLangue = 'fr')
'eve_acces_promoteur_col_statut' => array('fr' => 'Statut', 'en' => 'Status'),
'eve_acces_promoteur_col_depuis' => array('fr' => 'Depuis', 'en' => 'Since'),
'eve_acces_promoteur_col_expire' => array('fr' => 'Expire', 'en' => 'Expires'),
+ 'eve_acces_promoteur_col_action' => array('fr' => 'Action', 'en' => 'Action'),
+ 'eve_acces_promoteur_field_courriel' => array('fr' => 'Courriel', 'en' => 'Email'),
+ 'eve_acces_promoteur_field_prenom' => array('fr' => 'Prénom', 'en' => 'First name'),
+ 'eve_acces_promoteur_field_nom' => array('fr' => 'Nom', 'en' => 'Last name'),
+ 'eve_acces_promoteur_field_kit' => array('fr' => 'Kit d\'accès', 'en' => 'Access kit'),
+ 'eve_acces_promoteur_field_jours' => array('fr' => 'Durée (jours)', 'en' => 'Duration (days)'),
+ 'eve_acces_promoteur_jours_help' => array(
+ 'fr' => '0 = sans expiration. Utilisé surtout pour les nouveaux accès.',
+ 'en' => '0 = no expiration. Mainly for new access grants.',
+ ),
+ 'eve_acces_promoteur_btn_invite' => array('fr' => 'Assigner l\'accès', 'en' => 'Grant access'),
+ 'eve_acces_promoteur_btn_revoke' => array('fr' => 'Retirer', 'en' => 'Revoke'),
+ 'eve_acces_promoteur_no_kits' => array(
+ 'fr' => 'Aucun kit délégable disponible. Demandez à un super admin d\'activer « délégable » sur un kit.',
+ 'en' => 'No delegable kit available. Ask a super admin to mark a kit as delegable.',
+ ),
+ 'eve_acces_promoteur_ok_existing' => array(
+ 'fr' => 'Accès assigné au compte existant. Un courriel a été envoyé.',
+ 'en' => 'Access granted to the existing account. An email was sent.',
+ ),
+ 'eve_acces_promoteur_ok_created' => array(
+ 'fr' => 'Compte créé et accès assigné. Un courriel avec le lien de mot de passe a été envoyé.',
+ 'en' => 'Account created and access granted. An email with the password link was sent.',
+ ),
+ 'eve_acces_promoteur_ok_revoked' => array('fr' => 'Accès retiré.', 'en' => 'Access revoked.'),
+ 'eve_acces_promoteur_err_courriel' => array('fr' => 'Courriel invalide.', 'en' => 'Invalid email.'),
+ 'eve_acces_promoteur_err_kit' => array('fr' => 'Kit non autorisé.', 'en' => 'Kit not allowed.'),
+ 'eve_acces_promoteur_err_nom' => array(
+ 'fr' => 'Prénom et nom requis pour créer un nouveau compte.',
+ 'en' => 'First and last name required to create a new account.',
+ ),
+ 'eve_acces_promoteur_err_inactive' => array(
+ 'fr' => 'Un compte existe avec ce courriel mais il est inactif. Contactez le support.',
+ 'en' => 'An account exists with this email but it is inactive. Contact support.',
+ ),
+ 'eve_acces_promoteur_err_revoke' => array('fr' => 'Retrait impossible.', 'en' => 'Unable to revoke.'),
+ 'eve_acces_promoteur_err_generic' => array('fr' => 'Une erreur est survenue.', 'en' => 'An error occurred.'),
);
$strLang = ($strLangue === 'en') ? 'en' : 'fr';
if (isset($arrFallback[$strClef][$strLang])) {
@@ -63,8 +100,361 @@ function fxEveAccesPromoteurMenuLabel($strLangue = 'fr')
return fxEveAccesPromoteurT('tableau_promoteur_menu_eve_acces', $strLangue);
}
-/** MSIN-4401 — rendu page promoteur (liste + emplacement invitation). */
-function fxEveAccesPromoteurRenderPage($intEveId, $strLangue = 'fr')
+function fxEveAccesPromoteurHasInviteTeamColumn()
+{
+ global $objDatabase;
+
+ static $blnHas = null;
+ if ($blnHas !== null) {
+ return $blnHas;
+ }
+
+ $tab = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_comptes LIKE 'com_invite_team'");
+ $blnHas = ($tab != null && count($tab) > 0);
+
+ return $blnHas;
+}
+
+/**
+ * MSIN-4401 — crée un compte MS1 minimal pour invitation promoteur.
+ *
+ * @return array{state:string,message?:string,com_id?:int,reset_token?:string}
+ */
+function fxEveAccesPromoteurCreateCompteInvite($strCourriel, $strPrenom, $strNom, $strLangue, $intGrantedBy)
+{
+ global $objDatabase;
+
+ $strCourriel = trim(strtolower((string)$strCourriel));
+ $strPrenom = trim((string)$strPrenom);
+ $strNom = trim((string)$strNom);
+ $strLangue = ($strLangue === 'en') ? 'en' : 'fr';
+
+ if ($strCourriel === '' || !filter_var($strCourriel, FILTER_VALIDATE_EMAIL)) {
+ return array('state' => 'error', 'message' => 'courriel');
+ }
+ if ($strPrenom === '' || $strNom === '') {
+ return array('state' => 'error', 'message' => 'nom');
+ }
+
+ $strToken = uniqid('inv', true);
+ $strPasswordHash = password_hash(bin2hex(random_bytes(16)), PASSWORD_DEFAULT);
+ $strNow = fxGetDateTime();
+ $strInviteFlag = fxEveAccesPromoteurHasInviteTeamColumn()
+ ? ', com_invite_team = 1'
+ : '';
+
+ $blnHasConfirme = false;
+ $tabConfirme = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_comptes LIKE 'com_confirme'");
+ if ($tabConfirme != null && count($tabConfirme) > 0) {
+ $blnHasConfirme = true;
+ }
+ $blnHasResetDate = false;
+ $tabResetDate = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_comptes LIKE 'com_reset_date'");
+ if ($tabResetDate != null && count($tabResetDate) > 0) {
+ $blnHasResetDate = true;
+ }
+
+ $blnHasNoteInterne = false;
+ $tabNote = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_comptes LIKE 'com_note_interne'");
+ if ($tabNote != null && count($tabNote) > 0) {
+ $blnHasNoteInterne = true;
+ }
+ $blnHasResetToken = false;
+ $tabResetTok = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_comptes LIKE 'com_reset_token'");
+ if ($tabResetTok != null && count($tabResetTok) > 0) {
+ $blnHasResetToken = true;
+ }
+
+ $sql = "INSERT INTO inscriptions_comptes SET
+ com_prenom = '" . $objDatabase->fxEscape($strPrenom) . "',
+ com_nom = '" . $objDatabase->fxEscape($strNom) . "',
+ com_courriel = '" . $objDatabase->fxEscape($strCourriel) . "',
+ com_login = '" . $objDatabase->fxEscape($strCourriel) . "',
+ com_password = '" . $objDatabase->fxEscape($strPasswordHash) . "',
+ com_langue = '" . $objDatabase->fxEscape($strLangue) . "',
+ com_actif = 1,
+ com_creation = '" . $objDatabase->fxEscape($strNow) . "'
+ $strInviteFlag";
+
+ if ($blnHasConfirme) {
+ $sql .= ', com_confirme = 1';
+ }
+ if ($blnHasResetToken) {
+ $sql .= ", com_reset_token = '" . $objDatabase->fxEscape($strToken) . "'";
+ }
+ if ($blnHasResetDate) {
+ $sql .= ", com_reset_date = '" . $objDatabase->fxEscape($strNow) . "'";
+ }
+ if ($blnHasNoteInterne) {
+ $sql .= ", com_note_interne = 'MSIN-4401 invitation promoteur (par com_id "
+ . intval($intGrantedBy) . ")'";
+ }
+
+ if ($objDatabase->fxQuery($sql) === false) {
+ return array('state' => 'error', 'message' => 'insert');
+ }
+
+ $intComId = intval($objDatabase->fxGetVar(
+ "SELECT com_id FROM inscriptions_comptes
+ WHERE com_courriel = '" . $objDatabase->fxEscape($strCourriel) . "'
+ ORDER BY com_id DESC LIMIT 1"
+ ));
+
+ if ($intComId <= 0) {
+ return array('state' => 'error', 'message' => 'insert');
+ }
+
+ return array(
+ 'state' => 'success',
+ 'com_id' => $intComId,
+ 'reset_token' => $strToken,
+ );
+}
+
+function fxEveAccesPromoteurSendInviteMail($arrCompte, $arrEve, $arrRole, $strLangue, $blnNewAccount, $strResetToken = '')
+{
+ global $vDomaine, $vEmail, $vClient;
+
+ if (!function_exists('fxSendMail')) {
+ require_once __DIR__ . '/inc_mail.php';
+ }
+ if (!function_exists('fxGetMailFormat')) {
+ require_once __DIR__ . '/inc_fonctions.php';
+ }
+
+ $strLangue = ($strLangue === 'en') ? 'en' : 'fr';
+ $strEveNom = fxUnescape($arrEve['eve_nom_' . $strLangue] ?? ($arrEve['eve_nom_fr'] ?? ''));
+ $strKit = ($strLangue === 'en')
+ ? ($arrRole['role_label_en'] ?? $arrRole['role_label_fr'] ?? '')
+ : ($arrRole['role_label_fr'] ?? '');
+ $strPrenom = fxUnescape($arrCompte['com_prenom'] ?? '');
+ $strLogin = $arrCompte['com_login'] ?? $arrCompte['com_courriel'];
+ $intEveId = intval($arrEve['eve_id'] ?? 0);
+ $strEveParam = urlencode(base64_encode($intEveId));
+ $strComptePath = ($strLangue === 'en') ? '/account' : '/compte';
+ $strAccessUrl = $vDomaine . $strComptePath . '/inc_tableau_eve_acces?promoteur_eve_id=' . $strEveParam;
+
+ if ($blnNewAccount && $strResetToken !== '') {
+ if ($strLangue === 'fr') {
+ $subject = 'Accès promoteur — créez votre mot de passe';
+ $message = 'Bonjour ' . $strPrenom . ',
'
+ . 'Un accès vous a été accordé pour ' . htmlspecialchars($strEveNom, ENT_QUOTES, 'UTF-8') . ''
+ . ' (kit : ' . htmlspecialchars($strKit, ENT_QUOTES, 'UTF-8') . ').
'
+ . 'Un compte a été créé avec le courriel ' . htmlspecialchars($strLogin, ENT_QUOTES, 'UTF-8') . '.
'
+ . 'Cliquez ci-dessous pour choisir votre mot de passe, puis connectez-vous.';
+ $attachment_label = 'Choisir mon mot de passe';
+ } else {
+ $subject = 'Promoter access — set your password';
+ $message = 'Hello ' . $strPrenom . ',
'
+ . 'You were granted access to ' . htmlspecialchars($strEveNom, ENT_QUOTES, 'UTF-8') . ''
+ . ' (kit: ' . htmlspecialchars($strKit, ENT_QUOTES, 'UTF-8') . ').
'
+ . 'An account was created with ' . htmlspecialchars($strLogin, ENT_QUOTES, 'UTF-8') . '.
'
+ . 'Click below to set your password, then sign in.';
+ $attachment_label = 'Set my password';
+ }
+ $attachment_url = $vDomaine . $strComptePath . '/reset?t=' . urlencode($strResetToken)
+ . '&m=' . urlencode($arrCompte['com_courriel'])
+ . '&id=' . intval($arrCompte['com_id']);
+ } else {
+ if ($strLangue === 'fr') {
+ $subject = 'Nouvel accès — ' . $strEveNom;
+ $message = 'Bonjour ' . $strPrenom . ',
'
+ . 'Un accès vous a été accordé pour ' . htmlspecialchars($strEveNom, ENT_QUOTES, 'UTF-8') . ''
+ . ' (kit : ' . htmlspecialchars($strKit, ENT_QUOTES, 'UTF-8') . ').
'
+ . 'Connectez-vous avec votre compte existant (' . htmlspecialchars($strLogin, ENT_QUOTES, 'UTF-8') . ').';
+ $attachment_label = 'Ouvrir mon compte';
+ } else {
+ $subject = 'New access — ' . $strEveNom;
+ $message = 'Hello ' . $strPrenom . ',
'
+ . 'You were granted access to ' . htmlspecialchars($strEveNom, ENT_QUOTES, 'UTF-8') . ''
+ . ' (kit: ' . htmlspecialchars($strKit, ENT_QUOTES, 'UTF-8') . ').
'
+ . 'Sign in with your existing account (' . htmlspecialchars($strLogin, ENT_QUOTES, 'UTF-8') . ').';
+ $attachment_label = 'Open my account';
+ }
+ $attachment_url = $vDomaine . $strComptePath;
+ }
+
+ $body = fxGetMailFormat(false, false, true, false, $strLangue);
+ $body = str_replace('%logo%', $vDomaine . '/images/logoms1inscription.png', $body);
+ $body = str_replace('%to_mail%', $arrCompte['com_courriel'], $body);
+ $body = str_replace('%subject%', $subject, $body);
+ $body = str_replace('%message%', $message, $body);
+ $body = str_replace('%attachment_url%', $attachment_url, $body);
+ $body = str_replace('%attachment_label%', $attachment_label, $body);
+
+ fxSendMail(
+ $subject,
+ $body,
+ $arrCompte['com_courriel'],
+ trim(($arrCompte['com_prenom'] ?? '') . ' ' . ($arrCompte['com_nom'] ?? '')),
+ $vEmail,
+ $vClient,
+ 1,
+ 0
+ );
+
+ return true;
+}
+
+/**
+ * MSIN-4401 — invitation / assignation par promoteur.
+ *
+ * @return array{state:string,message:string,created?:bool}
+ */
+function fxEveAccesPromoteurInvite($intEveId, $intGrantedBy, $arrPost, $strLangue = 'fr')
+{
+ global $objDatabase;
+
+ $intEveId = intval($intEveId);
+ $intGrantedBy = intval($intGrantedBy);
+ $strLangue = ($strLangue === 'en') ? 'en' : 'fr';
+
+ if (!fxEveAccesCanTeamInvite($intGrantedBy, $intEveId)) {
+ return array('state' => 'error', 'message' => fxEveAccesPromoteurT('eve_acces_promoteur_err_generic', $strLangue));
+ }
+
+ $strCourriel = trim(strtolower((string)($arrPost['invite_courriel'] ?? '')));
+ $strPrenom = trim((string)($arrPost['invite_prenom'] ?? ''));
+ $strNom = trim((string)($arrPost['invite_nom'] ?? ''));
+ $intRoleId = intval($arrPost['invite_role_id'] ?? 0);
+ $intJours = intval($arrPost['invite_jours'] ?? 0);
+ if ($intJours < 0) {
+ $intJours = 0;
+ }
+ if ($intJours > 3650) {
+ $intJours = 3650;
+ }
+
+ if ($strCourriel === '' || !filter_var($strCourriel, FILTER_VALIDATE_EMAIL)) {
+ return array('state' => 'error', 'message' => fxEveAccesPromoteurT('eve_acces_promoteur_err_courriel', $strLangue));
+ }
+ if (!fxEveAccesRoleIsDelegable($intRoleId)) {
+ return array('state' => 'error', 'message' => fxEveAccesPromoteurT('eve_acces_promoteur_err_kit', $strLangue));
+ }
+
+ $arrEve = $objDatabase->fxGetRow(
+ 'SELECT eve_id, eve_nom_fr, eve_nom_en FROM inscriptions_evenements WHERE eve_id = ' . $intEveId . ' LIMIT 1'
+ );
+ $arrRole = $objDatabase->fxGetRow(
+ 'SELECT role_id, role_code, role_label_fr, role_label_en FROM inscriptions_eve_roles WHERE role_id = ' . $intRoleId . ' LIMIT 1'
+ );
+ if ($arrEve === null || $arrRole === null) {
+ return array('state' => 'error', 'message' => fxEveAccesPromoteurT('eve_acces_promoteur_err_generic', $strLangue));
+ }
+
+ $rowExisting = $objDatabase->fxGetRow(
+ "SELECT com_id, com_prenom, com_nom, com_courriel, com_login, com_actif
+ FROM inscriptions_comptes
+ WHERE com_courriel = '" . $objDatabase->fxEscape($strCourriel) . "'
+ ORDER BY com_actif DESC, com_id DESC
+ LIMIT 1"
+ );
+
+ $blnCreated = false;
+ $strResetToken = '';
+ $arrCompte = null;
+
+ if ($rowExisting !== null) {
+ if (intval($rowExisting['com_actif']) !== 1) {
+ return array('state' => 'error', 'message' => fxEveAccesPromoteurT('eve_acces_promoteur_err_inactive', $strLangue));
+ }
+ $arrCompte = $rowExisting;
+ if ($strPrenom !== '' && trim((string)$arrCompte['com_prenom']) === '') {
+ $objDatabase->fxQuery(
+ "UPDATE inscriptions_comptes SET com_prenom = '" . $objDatabase->fxEscape($strPrenom) . "'
+ WHERE com_id = " . intval($arrCompte['com_id'])
+ );
+ $arrCompte['com_prenom'] = $strPrenom;
+ }
+ if ($strNom !== '' && trim((string)$arrCompte['com_nom']) === '') {
+ $objDatabase->fxQuery(
+ "UPDATE inscriptions_comptes SET com_nom = '" . $objDatabase->fxEscape($strNom) . "'
+ WHERE com_id = " . intval($arrCompte['com_id'])
+ );
+ $arrCompte['com_nom'] = $strNom;
+ }
+ } else {
+ if ($strPrenom === '' || $strNom === '') {
+ return array('state' => 'error', 'message' => fxEveAccesPromoteurT('eve_acces_promoteur_err_nom', $strLangue));
+ }
+ $arrCreate = fxEveAccesPromoteurCreateCompteInvite(
+ $strCourriel,
+ $strPrenom,
+ $strNom,
+ $strLangue,
+ $intGrantedBy
+ );
+ if (($arrCreate['state'] ?? '') !== 'success') {
+ return array('state' => 'error', 'message' => fxEveAccesPromoteurT('eve_acces_promoteur_err_generic', $strLangue));
+ }
+ $blnCreated = true;
+ $strResetToken = (string)($arrCreate['reset_token'] ?? '');
+ $arrCompte = array(
+ 'com_id' => intval($arrCreate['com_id']),
+ 'com_prenom' => $strPrenom,
+ 'com_nom' => $strNom,
+ 'com_courriel' => $strCourriel,
+ 'com_login' => $strCourriel,
+ );
+ }
+
+ $arrGrant = fxEveAccesGrant(
+ intval($arrCompte['com_id']),
+ $intEveId,
+ $intRoleId,
+ $intJours,
+ $intGrantedBy,
+ 'MSIN-4401 invitation promoteur'
+ );
+
+ if (($arrGrant['state'] ?? '') !== 'success') {
+ return array(
+ 'state' => 'error',
+ 'message' => $arrGrant['message'] ?? fxEveAccesPromoteurT('eve_acces_promoteur_err_generic', $strLangue),
+ );
+ }
+
+ fxEveAccesPromoteurSendInviteMail($arrCompte, $arrEve, $arrRole, $strLangue, $blnCreated, $strResetToken);
+
+ return array(
+ 'state' => 'success',
+ 'created' => $blnCreated,
+ 'message' => $blnCreated
+ ? fxEveAccesPromoteurT('eve_acces_promoteur_ok_created', $strLangue)
+ : fxEveAccesPromoteurT('eve_acces_promoteur_ok_existing', $strLangue),
+ );
+}
+
+/**
+ * MSIN-4401 — révocation par le promoteur (team.manage ou auteur du grant / super admin).
+ */
+function fxEveAccesPromoteurRevoke($intEaId, $intActorComId, $intEveId)
+{
+ global $objDatabase;
+
+ $intEaId = intval($intEaId);
+ $intActorComId = intval($intActorComId);
+ $intEveId = intval($intEveId);
+
+ $tab = $objDatabase->fxGetRow(
+ 'SELECT * FROM inscriptions_eve_acces WHERE ea_id = ' . $intEaId . ' LIMIT 1'
+ );
+ if ($tab === null || intval($tab['eve_id']) !== $intEveId) {
+ return array('state' => 'error');
+ }
+
+ $blnOk = fxEveAccesCanTeamManage($intActorComId, $intEveId)
+ || (intval($tab['ea_granted_by'] ?? 0) === $intActorComId && fxEveAccesCanTeamInvite($intActorComId, $intEveId));
+
+ if (!$blnOk) {
+ return array('state' => 'error');
+ }
+
+ return fxEveAccesRevoke($intEaId, $intActorComId);
+}
+
+/** MSIN-4401 — rendu page promoteur (invitation + liste). */
+function fxEveAccesPromoteurRenderPage($intEveId, $strLangue = 'fr', $strFlash = '', $strError = '')
{
global $vDomaine;
@@ -75,6 +465,11 @@ function fxEveAccesPromoteurRenderPage($intEveId, $strLangue = 'fr')
? fxGetPromoteurBackUrl($intEveId, $strPage)
: ($vDomaine . $strPage);
+ $intActor = intval($_SESSION['com_id'] ?? 0);
+ if (!empty($_SESSION['usa_id'])) {
+ $intActor = intval($_SESSION['usa_id']);
+ }
+
$arrEve = function_exists('fxGetEvenementsId') ? fxGetEvenementsId($intEveId) : null;
$strEveNom = '';
if (is_array($arrEve) && !empty($arrEve['eve_nom_' . $strLangue])) {
@@ -82,7 +477,11 @@ function fxEveAccesPromoteurRenderPage($intEveId, $strLangue = 'fr')
}
$arrRows = fxEveAccesListByEveId($intEveId, true);
+ $arrRoles = fxEveAccesGetDelegableRoles();
$strRoleLabelKey = ($strLangue === 'en') ? 'role_label_en' : 'role_label_fr';
+ $blnCanManage = fxEveAccesCanTeamManage($intActor, $intEveId);
+ $strFormAction = $vDomaine . $strPage . '/inc_tableau_eve_acces?promoteur_eve_id='
+ . urlencode(base64_encode($intEveId)) . '&lng=' . $strLangue;
echo '
' . fxEveAccesPromoteurEsc(fxEveAccesPromoteurT('eve_acces_promoteur_intro', $strLangue)) . '
'; echo '' . fxEveAccesPromoteurEsc(fxEveAccesPromoteurT('eve_acces_promoteur_invite_soon', $strLangue)) . '
'; + + if (count($arrRoles) === 0) { + echo '' . fxEveAccesPromoteurEsc(fxEveAccesPromoteurT('eve_acces_promoteur_no_kits', $strLangue)) . '
'; + } else { + echo ''; + } + echo '