460 lines
14 KiB
PHP
Raw Normal View History

<?php
/**
* Fonctions d'accès à la base de données pour MH Wilds - Partage de Quêtes à Couronnes
*/
// Empêcher l'accès direct à ce fichier
if (!defined('SECURE_ACCESS')) {
header('HTTP/1.0 403 Forbidden');
exit;
}
/**
* Obtenir une connexion à la base de données SQLite
*
* @return PDO Instance de connexion à la base de données
*/
function get_db_connection() {
static $db = null;
if ($db === null) {
try {
// Vérifier si le fichier de base de données existe
$db_exists = file_exists(DB_PATH);
// Créer une nouvelle connexion PDO à la base de données SQLite
$db = new PDO('sqlite:' . DB_PATH);
// Configurer PDO pour lever des exceptions en cas d'erreur
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Activer les clés étrangères
$db->exec('PRAGMA foreign_keys = ON;');
// Si la base de données est nouvellement créée, initialiser le schéma
if (!$db_exists) {
init_database($db);
}
} catch (PDOException $e) {
// En mode débogage, afficher l'erreur
if (DEBUG_MODE) {
echo "Erreur de connexion à la base de données: " . $e->getMessage();
}
// Journaliser l'erreur
error_log("Erreur de connexion à la base de données: " . $e->getMessage());
die("Une erreur s'est produite lors de la connexion à la base de données.");
}
}
return $db;
}
/**
* Initialiser la base de données avec le schéma et les données initiales
*
* @param PDO $db Instance de connexion à la base de données
*/
function init_database($db) {
try {
// Charger le fichier de schéma SQL
$schema = file_get_contents(__DIR__ . '/../data/schema.sql');
// Exécuter toutes les requêtes SQL du schéma
$db->exec($schema);
return true;
} catch (PDOException $e) {
// En mode débogage, afficher l'erreur
if (DEBUG_MODE) {
echo "Erreur d'initialisation de la base de données: " . $e->getMessage();
}
// Journaliser l'erreur
error_log("Erreur d'initialisation de la base de données: " . $e->getMessage());
die("Une erreur s'est produite lors de l'initialisation de la base de données.");
}
}
/**
* ======== FONCTIONS D'ACCÈS AUX MONSTRES ========
*/
/**
* Récupérer tous les monstres
*
2025-03-09 20:56:01 +01:00
* @param string $sort_by Critère de tri ('name_asc', 'name_desc', 'quests_count', 'recent_quests')
* @return array Liste des monstres
*/
2025-03-09 20:56:01 +01:00
function get_all_monsters($sort_by = 'name_asc') {
$db = get_db_connection();
2025-03-09 20:56:01 +01:00
// Pour déboguer - log le paramètre de tri et la requête SQL
error_log("Tri demandé: " . $sort_by);
switch ($sort_by) {
case 'name_desc':
$sql = 'SELECT * FROM monsters ORDER BY name DESC';
$stmt = $db->query($sql);
error_log("SQL exécuté: " . $sql);
break;
case 'quests_count':
// Version compatible avec SQLite
$sql = '
SELECT m.*, COUNT(q.id) as quest_count
FROM monsters m
LEFT JOIN quests q ON m.id = q.monster_id
GROUP BY m.id
ORDER BY quest_count DESC, m.name ASC
';
$stmt = $db->query($sql);
error_log("SQL exécuté: " . $sql);
break;
case 'recent_quests':
// Version compatible avec SQLite
$sql = '
SELECT m.*,
CASE WHEN MAX(q.date) IS NULL THEN 0 ELSE 1 END as has_quests,
MAX(q.date) as latest_quest
FROM monsters m
LEFT JOIN quests q ON m.id = q.monster_id
GROUP BY m.id
ORDER BY has_quests DESC, latest_quest DESC, m.name ASC
';
$stmt = $db->query($sql);
error_log("SQL exécuté: " . $sql);
break;
case 'name_asc':
default:
$sql = 'SELECT * FROM monsters ORDER BY name ASC';
$stmt = $db->query($sql);
error_log("SQL exécuté: " . $sql);
break;
}
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Récupérer un monstre par son ID
*
* @param int $id ID du monstre
* @return array|false Données du monstre ou false si non trouvé
*/
function get_monster_by_id($id) {
$db = get_db_connection();
$stmt = $db->prepare('SELECT * FROM monsters WHERE id = :id');
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetch(PDO::FETCH_ASSOC);
}
/**
* Ajouter un nouveau monstre
*
* @param string $name Nom du monstre
* @param string $image Chemin de l'image
* @return int|false ID du nouveau monstre ou false en cas d'échec
*/
function add_monster($name, $image) {
$db = get_db_connection();
$stmt = $db->prepare('INSERT INTO monsters (name, image) VALUES (:name, :image)');
$stmt->bindParam(':name', $name);
$stmt->bindParam(':image', $image);
if ($stmt->execute()) {
return $db->lastInsertId();
}
return false;
}
/**
* Mettre à jour un monstre existant
*
* @param int $id ID du monstre
* @param string $name Nouveau nom
* @param string $image Nouveau chemin d'image
* @return bool Succès de la mise à jour
*/
function update_monster($id, $name, $image) {
$db = get_db_connection();
$stmt = $db->prepare('UPDATE monsters SET name = :name, image = :image WHERE id = :id');
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindParam(':name', $name);
$stmt->bindParam(':image', $image);
return $stmt->execute();
}
/**
* Supprimer un monstre
*
* @param int $id ID du monstre à supprimer
* @return bool Succès de la suppression
*/
function delete_monster($id) {
$db = get_db_connection();
$stmt = $db->prepare('DELETE FROM monsters WHERE id = :id');
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
return $stmt->execute();
}
/**
* ======== FONCTIONS D'ACCÈS AUX QUÊTES ========
*/
/**
* Récupérer toutes les quêtes pour un monstre spécifique
*
* @param int $monster_id ID du monstre
* @return array Liste des quêtes
*/
function get_quests_by_monster($monster_id) {
$db = get_db_connection();
$stmt = $db->prepare('SELECT * FROM quests WHERE monster_id = :monster_id ORDER BY date DESC');
$stmt->bindParam(':monster_id', $monster_id, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Récupérer toutes les quêtes d'un certain type (small/large) pour un monstre
*
* @param int $monster_id ID du monstre
* @param string $crown_type Type de couronne ('small' ou 'large')
* @return array Liste des quêtes
*/
function get_quests_by_monster_and_crown($monster_id, $crown_type) {
$db = get_db_connection();
$stmt = $db->prepare('SELECT * FROM quests WHERE monster_id = :monster_id AND crown_type = :crown_type ORDER BY date DESC');
$stmt->bindParam(':monster_id', $monster_id, PDO::PARAM_INT);
$stmt->bindParam(':crown_type', $crown_type);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Ajouter une nouvelle quête
*
* @param int $monster_id ID du monstre
* @param string $crown_type Type de couronne ('small' ou 'large')
* @param string $player_name Nom du joueur
* @param string $player_id ID du joueur en jeu
* @return int|false ID de la nouvelle quête ou false en cas d'échec
*/
function add_quest($monster_id, $crown_type, $player_name, $player_id) {
$db = get_db_connection();
$stmt = $db->prepare('INSERT INTO quests (monster_id, crown_type, player_name, player_id) VALUES (:monster_id, :crown_type, :player_name, :player_id)');
$stmt->bindParam(':monster_id', $monster_id, PDO::PARAM_INT);
$stmt->bindParam(':crown_type', $crown_type);
$stmt->bindParam(':player_name', $player_name);
$stmt->bindParam(':player_id', $player_id);
if ($stmt->execute()) {
return $db->lastInsertId();
}
return false;
}
/**
* Supprimer une quête
*
* @param int $id ID de la quête à supprimer
* @return bool Succès de la suppression
*/
function delete_quest($id) {
$db = get_db_connection();
$stmt = $db->prepare('DELETE FROM quests WHERE id = :id');
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
return $stmt->execute();
}
/**
* Nettoyer les quêtes expirées (plus vieilles que QUESTS_EXPIRATION_DAYS)
*
* @return int Nombre de quêtes supprimées
*/
function clean_old_quests() {
$db = get_db_connection();
$days = QUESTS_EXPIRATION_DAYS;
$stmt = $db->prepare("DELETE FROM quests WHERE date < datetime('now', '-{$days} days')");
$stmt->execute();
return $stmt->rowCount();
}
/**
* Compter les quêtes par type de couronne
*
* @return array Statistiques des quêtes
*/
function count_quests_by_crown_type() {
$db = get_db_connection();
$stmt = $db->query("
SELECT
COUNT(*) as total_quests,
SUM(CASE WHEN crown_type = 'small' THEN 1 ELSE 0 END) as small_crown_quests,
SUM(CASE WHEN crown_type = 'large' THEN 1 ELSE 0 END) as large_crown_quests
FROM quests
");
return $stmt->fetch(PDO::FETCH_ASSOC);
}
/**
* ======== FONCTIONS D'ACCÈS AUX ANNONCES ========
*/
/**
* Récupérer toutes les annonces
*
* @param bool $active_only Ne récupérer que les annonces actives
* @return array Liste des annonces
*/
function get_all_announcements($active_only = false) {
$db = get_db_connection();
$query = 'SELECT * FROM announcements';
if ($active_only) {
$query .= ' WHERE active = 1';
}
$query .= ' ORDER BY created_at ASC';
$stmt = $db->query($query);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Récupérer une annonce par son ID
*
* @param int $id ID de l'annonce
* @return array|false Données de l'annonce ou false si non trouvée
*/
function get_announcement_by_id($id) {
$db = get_db_connection();
$stmt = $db->prepare('SELECT * FROM announcements WHERE id = :id');
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetch(PDO::FETCH_ASSOC);
}
/**
* Ajouter une nouvelle annonce
*
* @param string $text Texte de l'annonce
* @param bool $active Statut actif de l'annonce
* @return int|false ID de la nouvelle annonce ou false en cas d'échec
*/
function add_announcement($text, $active = true) {
$db = get_db_connection();
$active_int = $active ? 1 : 0;
$stmt = $db->prepare('INSERT INTO announcements (text, active) VALUES (:text, :active)');
$stmt->bindParam(':text', $text);
$stmt->bindParam(':active', $active_int, PDO::PARAM_INT);
if ($stmt->execute()) {
return $db->lastInsertId();
}
return false;
}
/**
* Mettre à jour une annonce existante
*
* @param int $id ID de l'annonce
* @param string $text Nouveau texte
* @param bool $active Nouveau statut
* @return bool Succès de la mise à jour
*/
function update_announcement($id, $text, $active = true) {
$db = get_db_connection();
$active_int = $active ? 1 : 0;
$stmt = $db->prepare('UPDATE announcements SET text = :text, active = :active WHERE id = :id');
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindParam(':text', $text);
$stmt->bindParam(':active', $active_int, PDO::PARAM_INT);
return $stmt->execute();
}
/**
* Supprimer une annonce
*
* @param int $id ID de l'annonce à supprimer
* @return bool Succès de la suppression
*/
function delete_announcement($id) {
$db = get_db_connection();
$stmt = $db->prepare('DELETE FROM announcements WHERE id = :id');
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
return $stmt->execute();
}
/**
* ======== FONCTIONS D'AUTHENTIFICATION ========
*/
/**
* Vérifier les identifiants d'un utilisateur
*
* @param string $username Nom d'utilisateur
* @param string $password Mot de passe
* @return bool L'authentification est-elle valide
*/
function check_login($username, $password) {
$db = get_db_connection();
$stmt = $db->prepare('SELECT * FROM users WHERE username = :username');
$stmt->bindParam(':username', $username);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
return true;
}
return false;
}
/**
* Mettre à jour le mot de passe d'un utilisateur
*
* @param string $username Nom d'utilisateur
* @param string $new_password Nouveau mot de passe
* @return bool Succès de la mise à jour
*/
function update_user_password($username, $new_password) {
$db = get_db_connection();
// Hacher le nouveau mot de passe
$hashed_password = password_hash($new_password, PASSWORD_DEFAULT);
$stmt = $db->prepare('UPDATE users SET password = :password WHERE username = :username');
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $hashed_password);
return $stmt->execute();
}
/**
* Vérifier le mot de passe actuel d'un utilisateur
*
* @param string $username Nom d'utilisateur
* @param string $current_password Mot de passe actuel
* @return bool Le mot de passe est-il valide
*/
function verify_current_password($username, $current_password) {
$db = get_db_connection();
$stmt = $db->prepare('SELECT password FROM users WHERE username = :username');
$stmt->bindParam(':username', $username);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($current_password, $user['password'])) {
return true;
}
return false;
}