'actif'], 'membres'); * * @param string $baseSql Requête SQL de base (peut contenir {TENANT_FILTER} comme placeholder) * @param array $params Paramètres de la requête * @param string $tableAlias Alias de la table principale pour le filtrage * @return string Requête SQL complète avec filtrage tenant */ function buildTenantQuery($baseSql, $params = [], $tableAlias = '') { // Tables système qui ne nécessitent pas de filtre $systemTables = ['eglises', 'groupes', 'utilisateurs', 'permissions', 'element_budget', 'parametres_ent', 'logo', 'enregistrement', 'journalisation']; // Vérifier si c'est une table système foreach ($systemTables as $table) { if (preg_match('/\b' . preg_quote($table, '/') . '\b/i', $baseSql)) { return $baseSql; // Pas de filtre pour les tables système } } // Si la requête contient déjà un filtre eglise_id explicite, ne pas ajouter if (preg_match('/\beglise_id\s*[=<>]/i', $baseSql) || preg_match('/\beglise_id\s+IN/i', $baseSql)) { return $baseSql; } // Si la requête contient le placeholder {TENANT_FILTER}, le remplacer if (strpos($baseSql, '{TENANT_FILTER}') !== false) { if (empty($tableAlias)) { // Détecter l'alias de la table principale if (preg_match('/FROM\s+[a-zA-Z_]+\s+(?:AS\s+)?([a-zA-Z_]+)/i', $baseSql, $matches)) { $tableAlias = $matches[1]; } elseif (preg_match('/FROM\s+([a-zA-Z_]+)/i', $baseSql, $matches)) { $tableAlias = $matches[1]; } } $tenantFilter = MultiTenant::getWhereClause($tableAlias); return str_replace('{TENANT_FILTER}', $tenantFilter, $baseSql); } // Sinon, ajouter automatiquement le filtre if (isset($_SESSION['niveau_acces']) && isset($_SESSION['eglise_id'])) { if (empty($tableAlias)) { // Détecter l'alias de la table principale if (preg_match('/FROM\s+[a-zA-Z_]+\s+(?:AS\s+)?([a-zA-Z_]+)/i', $baseSql, $matches)) { $tableAlias = $matches[1]; } elseif (preg_match('/FROM\s+([a-zA-Z_]+)/i', $baseSql, $matches)) { $tableAlias = $matches[1]; } } $tenantFilter = MultiTenant::getWhereClause($tableAlias); if ($tenantFilter !== '1=1') { // Ajouter le filtre dans la clause WHERE existante ou créer une nouvelle clause WHERE if (preg_match('/WHERE\s+/i', $baseSql)) { // Ajouter AND avant ORDER BY, GROUP BY ou LIMIT $baseSql = preg_replace('/(WHERE\s+.*?)(\s+(?:ORDER|GROUP|LIMIT|$))/is', '$1 AND ' . $tenantFilter . '$2', $baseSql); } else { // Ajouter la clause WHERE avant ORDER BY, GROUP BY ou LIMIT if (preg_match('/FROM\s+([a-zA-Z_]+)/i', $baseSql, $matches)) { $table = $matches[1]; $baseSql = preg_replace('/(FROM\s+' . preg_quote($table, '/') . '\s*(?:AS\s+[a-zA-Z_]+)?)\s*((?:ORDER|GROUP|LIMIT|$))/is', '$1 WHERE ' . $tenantFilter . ' $2', $baseSql); } } } } return $baseSql; } /** * Exécute une requête SELECT avec filtrage multi-tenant explicite utilisant MultiTenant::getWhereClause() * * @param PDO $connexion Connexion à la base de données * @param string $sql Requête SQL (peut contenir {TENANT_FILTER} comme placeholder) * @param array $params Paramètres de la requête * @param string $tableAlias Alias de la table principale (optionnel) * @return array Résultats de la requête */ function queryTenantExplicit($connexion, $sql, $params = [], $tableAlias = '') { require_once __DIR__ . '/tenant_functions.php'; // Construire la requête avec filtrage tenant $sql = buildTenantQuery($sql, $params, $tableAlias); // Préparer et exécuter $stmt = $connexion->prepare($sql); // Binder les paramètres du filtre multi-tenant if (isset($_SESSION['niveau_acces']) && isset($_SESSION['eglise_id'])) { MultiTenant::bindTenantParams($stmt); } // Binder les autres paramètres foreach ($params as $key => $value) { $type = is_int($value) ? PDO::PARAM_INT : (is_bool($value) ? PDO::PARAM_BOOL : PDO::PARAM_STR); if (is_string($key) && $key[0] !== ':') { $key = ':' . $key; } $stmt->bindValue($key, $value, $type); } $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_OBJ); } /** * Exécute une requête SELECT avec filtrage multi-tenant et retourne un seul résultat * * @param PDO $connexion Connexion à la base de données * @param string $sql Requête SQL (peut contenir {TENANT_FILTER} comme placeholder) * @param array $params Paramètres de la requête * @param string $tableAlias Alias de la table principale (optionnel) * @return object|null Résultat unique ou null */ function queryTenantFirstExplicit($connexion, $sql, $params = [], $tableAlias = '') { require_once __DIR__ . '/tenant_functions.php'; // Construire la requête avec filtrage tenant $sql = buildTenantQuery($sql, $params, $tableAlias); // Préparer et exécuter $stmt = $connexion->prepare($sql); // Binder les paramètres du filtre multi-tenant if (isset($_SESSION['niveau_acces']) && isset($_SESSION['eglise_id'])) { MultiTenant::bindTenantParams($stmt); } // Binder les autres paramètres foreach ($params as $key => $value) { $type = is_int($value) ? PDO::PARAM_INT : (is_bool($value) ? PDO::PARAM_BOOL : PDO::PARAM_STR); if (is_string($key) && $key[0] !== ':') { $key = ':' . $key; } $stmt->bindValue($key, $value, $type); } $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_OBJ); return $result ?: null; }