460 lines
14 KiB
PHP
460 lines
14 KiB
PHP
<?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
|
|
*
|
|
* @param string $sort_by Critère de tri ('name_asc', 'name_desc', 'quests_count', 'recent_quests')
|
|
* @return array Liste des monstres
|
|
*/
|
|
function get_all_monsters($sort_by = 'name_asc') {
|
|
$db = get_db_connection();
|
|
|
|
// 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;
|
|
} |