prepare("SELECT role FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
if (!$user) return null;
$role = $user['role'];
$level = 0;
try {
$stmt_lvl = $pdo->prepare("SELECT level FROM users WHERE id = ?");
$stmt_lvl->execute([$user_id]);
$level = (int)$stmt_lvl->fetchColumn();
} catch (Exception $e) {
// level column might not exist
}
if ($role === 'admin') {
$stmt = $pdo->prepare("SELECT * FROM grades WHERE user_type = 'admin' LIMIT 1");
$stmt->execute();
return $stmt->fetch();
} elseif ($role === 'gm') {
$stmt = $pdo->prepare("SELECT * FROM grades WHERE user_type = 'GM' LIMIT 1");
$stmt->execute();
return $stmt->fetch();
} else {
$stmt = $pdo->prepare("SELECT * FROM grades WHERE user_type = 'utilisateur' AND ? BETWEEN min_level AND max_level LIMIT 1");
$stmt->execute([$level]);
return $stmt->fetch();
}
}
require_once 'db/config.php';
session_start();
$db = db();
// Auth Check: Must be logged in and be admin
if (!isset($_SESSION['user_id'])) {
header("Location: auth.php?page=login");
exit;
}
$user_id = $_SESSION['user_id'];
$user_stmt = $db->prepare("SELECT role FROM users WHERE id = ?");
$user_stmt->execute([$user_id]);
$current_user = $user_stmt->fetch();
if (!$current_user || $current_user['role'] !== 'admin') {
die("Accès refusé. Cette console est réservée aux Administrateurs.");
}
// Default tab is now users as before, but let's see if we should change it to project_logs
$tab = isset($_GET['tab']) ? $_GET['tab'] : 'project_logs';
// --- HANDLERS ---
// Handle Player Resource Management
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'admin_manage_player_resources') {
$target_type = $_POST['target_type']; // 'single', 'multiple', 'all'
$player_ids = [];
if ($target_type === 'all') {
$stmt = $db->query("SELECT id FROM users");
$player_ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
} else {
$player_ids = isset($_POST['player_ids']) ? (array)$_POST['player_ids'] : [];
}
$resource_id = (int)$_POST['resource_id'];
$amount = (int)$_POST['amount'];
$operation = $_POST['operation']; // 'add', 'remove'
if ($operation === 'remove') {
$amount = -abs($amount);
} else {
$amount = abs($amount);
}
if (!empty($player_ids) && $resource_id > 0 && $amount !== 0) {
$db->beginTransaction();
try {
$stmt_check = $db->prepare("SELECT amount FROM user_resources WHERE user_id = ? AND resource_id = ?");
$stmt_insert = $db->prepare("INSERT INTO user_resources (user_id, resource_id, amount) VALUES (?, ?, ?)");
$stmt_update = $db->prepare("UPDATE user_resources SET amount = GREATEST(0, amount + ?) WHERE user_id = ? AND resource_id = ?");
foreach ($player_ids as $pid) {
$pid = (int)$pid;
$stmt_check->execute([$pid, $resource_id]);
$exists = $stmt_check->fetch();
if ($exists) {
$stmt_update->execute([$amount, $pid, $resource_id]);
} else {
$initial_qty = max(0, $amount);
$stmt_insert->execute([$pid, $resource_id, $initial_qty]);
}
}
$db->commit();
header("Location: admin.php?tab=player&success=1");
exit;
} catch (Exception $e) {
$db->rollBack();
header("Location: admin.php?tab=player&error=db");
exit;
}
} else {
header("Location: admin.php?tab=player&error=missing_fields");
exit;
}
}
// Handle User Role Update
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_user_role') {
$target_user_id = (int)$_POST['target_user_id'];
$new_role = $_POST['new_role'];
if (in_array($new_role, ['user', 'gm', 'admin'])) {
$stmt = $db->prepare("UPDATE users SET role = ? WHERE id = ?");
$stmt->execute([$new_role, $target_user_id]);
}
header("Location: admin.php?tab=users&success=1");
exit;
}
// Handle Celestial Object Type CRUD
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_object_type') {
$id = (int)$_POST['id'];
$name = $_POST["name"];
$slug = $_POST['slug'];
$icon = $_POST['icon'];
$description = $_POST['description'];
$status_profile_id = !empty($_POST['status_profile_id']) ? (int)$_POST['status_profile_id'] : null;
$modifier_ids = isset($_POST['modifiers']) ? $_POST['modifiers'] : [];
$image_url = null;
if ($id > 0) {
$stmt_img = $db->prepare("SELECT image_url FROM celestial_object_types WHERE id = ?");
$stmt_img->execute([$id]);
$image_url = $stmt_img->fetchColumn();
}
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
$ext = pathinfo($_FILES['image']["name"], PATHINFO_EXTENSION);
$filename = $slug . "_" . time() . "." . $ext;
$target = "assets/images/celestial/" . $filename;
if (move_uploaded_file($_FILES['image']['tmp_name'], $target)) {
$image_url = $target;
}
}
$orbital_enabled = isset($_POST["orbital_control_enabled"]) ? 1 : 0;
$terrestrial_enabled = isset($_POST["terrestrial_control_enabled"]) ? 1 : 0;
if ($id > 0) {
$stmt = $db->prepare("UPDATE celestial_object_types SET name = ?, slug = ?, icon = ?, description = ?, image_url = ?, orbital_control_enabled = ?, terrestrial_control_enabled = ?, status_profile_id = ? WHERE id = ?");
$stmt->execute([$name, $slug, $icon, $description, $image_url, $orbital_enabled, $terrestrial_enabled, $status_profile_id, $id]);
} else {
$stmt = $db->prepare("INSERT INTO celestial_object_types (name, slug, icon, description, image_url, orbital_control_enabled, terrestrial_control_enabled, status_profile_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$name, $slug, $icon, $description, $image_url, $orbital_enabled, $terrestrial_enabled, $status_profile_id]);
$id = $db->lastInsertId();
}
// Sync modifiers
$db->prepare("DELETE FROM celestial_object_type_modifiers WHERE celestial_object_type_id = ?")->execute([$id]);
if (!empty($modifier_ids)) {
$ins = $db->prepare("INSERT INTO celestial_object_type_modifiers (celestial_object_type_id, modifier_id) VALUES (?, ?)");
foreach ($modifier_ids as $mid) {
$ins->execute([$id, (int)$mid]);
}
}
header("Location: admin.php?tab=objects&success=1");
exit;
}
if (isset($_GET['delete_object'])) {
$id = (int)$_GET['delete_object'];
$db->prepare("DELETE FROM celestial_object_types WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=objects&success=1");
exit;
}
// Handle Title CRUD
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_title') {
$id = (int)$_POST['id'];
$name = $_POST["name"];
$slug = $_POST['slug'];
$color = $_POST["color"] ?? "#ffffff";
$allowed_user_type = $_POST['allowed_user_type'];
$required_level = (int)$_POST['required_level'];
if ($id > 0) {
$stmt = $db->prepare("UPDATE titles SET name = ?, slug = ?, allowed_user_type = ?, required_level = ?, color = ? WHERE id = ?");
$stmt->execute([$name, $slug, $allowed_user_type, $required_level, $color, $id]);
} else {
$stmt = $db->prepare("INSERT INTO titles (name, slug, allowed_user_type, required_level, color) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$name, $slug, $allowed_user_type, $required_level, $color]);
}
header("Location: admin.php?tab=badges&success=1");
exit;
}
// Handle Badge CRUD
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_badge') {
$id = (int)$_POST['id'];
$name = $_POST["name"];
$slug = $_POST['slug'];
$allowed_user_type = $_POST['allowed_user_type'];
$required_level = (int)$_POST['required_level'];
$image_url = null;
if ($id > 0) {
$stmt_img = $db->prepare("SELECT image_url FROM badges WHERE id = ?");
$stmt_img->execute([$id]);
$image_url = $stmt_img->fetchColumn();
}
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
$ext = pathinfo($_FILES['image']["name"], PATHINFO_EXTENSION);
$filename = "badge_" . $slug . "_" . time() . "." . $ext;
$target = "assets/images/badges/" . $filename;
if (!is_dir("assets/images/badges/")) mkdir("assets/images/badges/", 0775, true);
if (move_uploaded_file($_FILES['image']['tmp_name'], $target)) {
$image_url = $target;
}
}
if ($id > 0) {
$stmt = $db->prepare("UPDATE badges SET name = ?, slug = ?, allowed_user_type = ?, required_level = ?, image_url = ? WHERE id = ?");
$stmt->execute([$name, $slug, $allowed_user_type, $required_level, $image_url, $id]);
} else {
$stmt = $db->prepare("INSERT INTO badges (name, slug, allowed_user_type, required_level, image_url) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$name, $slug, $allowed_user_type, $required_level, $image_url]);
}
header("Location: admin.php?tab=badges&success=1");
exit;
}
// Handle Title/Badge Deletion
if (isset($_GET['delete_title'])) {
$id = (int)$_GET['delete_title'];
$db->prepare("DELETE FROM titles WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=badges&success=deleted");
exit;
}
if (isset($_GET['delete_badge'])) {
$id = (int)$_GET['delete_badge'];
$db->prepare("DELETE FROM badges WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=badges&success=deleted");
exit;
}
// Handle Status CRUD
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "upsert_status") {
$id = (int)$_POST["id"];
$name = $_POST["name"];
$slug = $_POST["slug"];
$color = $_POST["color"];
$description = $_POST["description"];
// Gérer le clignotement
if (isset($_POST["is_blinking"]) && $_POST["is_blinking"] === "on") {
if (strpos($color, ";blink") === false) {
$color .= ";blink";
}
} else {
$color = str_replace(";blink", "", $color);
}
if ($id > 0) {
$stmt = $db->prepare("UPDATE celestial_object_statuses SET name = ?, slug = ?, color = ?, description = ? WHERE id = ?");
$stmt->execute([$name, $slug, $color, $description, $id]);
} else {
$stmt = $db->prepare("INSERT INTO celestial_object_statuses (name, slug, color, description) VALUES (?, ?, ? , ?)");
$stmt->execute([$name, $slug, $color, $description]);
}
header("Location: admin.php?tab=statuses&success=1");
exit;
}
if (isset($_GET['delete_status'])) {
$id = (int)$_GET['delete_status'];
$db->prepare("DELETE FROM celestial_object_statuses WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=statuses&success=1");
exit;
}
// Handle Status Profile CRUD
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "upsert_status_profile") {
$id = (int)$_POST["id"];
$name = $_POST["name"];
$slug = $_POST["slug"];
if ($id > 0) {
$stmt = $db->prepare("UPDATE celestial_object_status_profiles SET name = ?, slug = ? WHERE id = ?");
$stmt->execute([$name, $slug, $id]);
} else {
$stmt = $db->prepare("INSERT INTO celestial_object_status_profiles (name, slug) VALUES (?, ?)");
$stmt->execute([$name, $slug]);
}
header("Location: admin.php?tab=statuses&success=1");
exit;
}
if (isset($_GET["delete_status_profile"])) {
$id = (int)$_GET["delete_status_profile"];
// Check if it is used
$count = $db->query("SELECT COUNT(*) FROM celestial_object_status_rules WHERE profile_id = $id")->fetchColumn();
$count2 = $db->query("SELECT COUNT(*) FROM celestial_object_types WHERE status_profile_id = $id")->fetchColumn();
if ($count == 0 && $count2 == 0) {
$db->prepare("DELETE FROM celestial_object_status_profiles WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=statuses&success=1");
} else {
header("Location: admin.php?tab=statuses&error=profile_in_use");
}
exit;
}
// Handle Status Rule CRUD
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_status_rule') {
$id = (int)$_POST['id'];
$name = $_POST["name"];
$status_id = (int)$_POST['status_id'];
$profile_id = (int)$_POST['profile_id'];
$priority = (int)$_POST['priority'];
$orbital_count_op = $_POST['orbital_count_op'] ?: null;
$orbital_count_val = $_POST['orbital_count_val'] !== '' ? (int)$_POST['orbital_count_val'] : null;
$terrestrial_count_op = $_POST['terrestrial_count_op'] ?: null;
$terrestrial_count_val = $_POST['terrestrial_count_val'] !== '' ? (int)$_POST['terrestrial_count_val'] : null;
$orbital_dominance = isset($_POST['orbital_dominance']) ? implode(',', (array)$_POST['orbital_dominance']) : null;
$terrestrial_dominance = isset($_POST['terrestrial_dominance']) ? implode(',', (array)$_POST['terrestrial_dominance']) : null;
$is_empty_case = isset($_POST['is_empty_case']) ? 1 : 0;
$combine_mode = $_POST['combine_mode'] ?? 'OR';
if ($id > 0) {
$stmt = $db->prepare("UPDATE celestial_object_status_rules SET name = ?, status_id = ?, profile_id = ?, priority = ?, orbital_count_op = ?, orbital_count_val = ?, terrestrial_count_op = ?, terrestrial_count_val = ?, orbital_dominance = ?, terrestrial_dominance = ?, is_empty_case = ?, combine_mode = ? WHERE id = ?");
$stmt->execute([$name, $status_id, $profile_id, $priority, $orbital_count_op, $orbital_count_val, $terrestrial_count_op, $terrestrial_count_val, $orbital_dominance, $terrestrial_dominance, $is_empty_case, $combine_mode, $id]);
} else {
$stmt = $db->prepare("INSERT INTO celestial_object_status_rules (name, status_id, profile_id, priority, orbital_count_op, orbital_count_val, terrestrial_count_op, terrestrial_count_val, orbital_dominance, terrestrial_dominance, is_empty_case, combine_mode) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$name, $status_id, $profile_id, $priority, $orbital_count_op, $orbital_count_val, $terrestrial_count_op, $terrestrial_count_val, $orbital_dominance, $terrestrial_dominance, $is_empty_case, $combine_mode]);
}
header("Location: admin.php?tab=statuses&success=1");
exit;
}
if (isset($_GET['delete_status_rule'])) {
$id = (int)$_GET['delete_status_rule'];
$db->prepare("DELETE FROM celestial_object_status_rules WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=statuses&success=1");
exit;
}
// Handle Settlement Type CRUD
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_settlement_type') {
$id = (int)$_POST['id'];
$name = $_POST["name"];
$slug = $_POST['slug'];
$description = $_POST['description'];
if ($id > 0) {
$stmt = $db->prepare("UPDATE settlement_types SET name = ?, slug = ?, description = ? WHERE id = ?");
$stmt->execute([$name, $slug, $description, $id]);
} else {
$stmt = $db->prepare("INSERT INTO settlement_types (name, slug, description) VALUES (?, ?, ?)");
$stmt->execute([$name, $slug, $description]);
}
header("Location: admin.php?tab=settlement_types&success=1");
exit;
}
if (isset($_GET['delete_settlement_type'])) {
$id = (int)$_GET['delete_settlement_type'];
$db->prepare("DELETE FROM settlement_types WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=settlement_types&success=1");
exit;
}
// Handle Modifiers CRUD
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_modifier') {
$id = (int)$_POST['id'];
$name = $_POST["name"];
$slug = $_POST['slug'];
$type = $_POST['type'];
$description = $_POST['description'];
if ($id > 0) {
$stmt = $db->prepare("UPDATE modifiers SET name = ?, slug = ?, type = ?, description = ? WHERE id = ?");
$stmt->execute([$name, $slug, $type, $description, $id]);
} else {
$stmt = $db->prepare("INSERT INTO modifiers (name, slug, type, description) VALUES (?, ?, ?, ?)");
$stmt->execute([$name, $slug, $type, $description]);
}
header("Location: admin.php?tab=modifiers&success=1");
exit;
}
if (isset($_GET['delete_modifier'])) {
$id = (int)$_GET['delete_modifier'];
$db->prepare("DELETE FROM modifiers WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=modifiers&success=1");
exit;
}
// Handle Faction CRUD
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_faction') {
$id = (int)$_POST['id'];
$name = $_POST["name"];
$slug = $_POST['slug'];
$fa_icon = $_POST['fa_icon'];
$color = $_POST['color'];
$image_url = null;
$alliance_ids = isset($_POST['alliances']) ? $_POST['alliances'] : [];
if ($id > 0) {
$stmt_img = $db->prepare("SELECT image_url FROM factions WHERE id = ?");
$stmt_img->execute([$id]);
$image_url = $stmt_img->fetchColumn();
}
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
$ext = pathinfo($_FILES['image']["name"], PATHINFO_EXTENSION);
$filename = "faction_" . time() . "." . $ext;
$target = "assets/images/factions/" . $filename;
if (move_uploaded_file($_FILES['image']['tmp_name'], $target)) {
$image_url = $target;
}
}
if ($id > 0) {
$stmt = $db->prepare("UPDATE factions SET name = ?, slug = ?, image_url = ?, fa_icon = ?, color = ? WHERE id = ?");
$stmt->execute([$name, $slug, $image_url, $fa_icon, $color, $id]);
} else {
$stmt = $db->prepare("INSERT INTO factions (name, slug, image_url, fa_icon, color) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$name, $slug, $image_url, $fa_icon, $color]);
$id = $db->lastInsertId();
}
// Handle Alliances (Reciprocal)
$db->prepare("DELETE FROM faction_alliances WHERE faction_id_1 = ? OR faction_id_2 = ?")->execute([$id, $id]);
foreach ($alliance_ids as $ally_id) {
$f1 = min((int)$id, (int)$ally_id);
$f2 = max((int)$id, (int)$ally_id);
if ($f1 === $f2) continue;
$db->prepare("INSERT IGNORE INTO faction_alliances (faction_id_1, faction_id_2) VALUES (?, ?)")->execute([$f1, $f2]);
}
header("Location: admin.php?tab=factions&success=1");
exit;
}
if (isset($_GET['delete_faction'])) {
$id = (int)$_GET['delete_faction'];
$db->prepare("DELETE FROM factions WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=factions&success=1");
exit;
}
// Handle Levels CRUD
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "upsert_level") {
$id = (int)$_POST["id"];
$name = $_POST["name"];
$slug = $_POST["slug"];
$resource_id = (int)$_POST["resource_id"];
$required_quantity = (int)$_POST["required_quantity"];
if ($required_quantity <= 0) {
header("Location: admin.php?tab=levels&error=invalid_amount");
exit;
}
if ($id > 0) {
$stmt = $db->prepare("UPDATE levels SET name = ?, slug = ?, resource_id = ?, required_quantity = ? WHERE id = ?");
$stmt->execute([$name, $slug, $resource_id, $required_quantity, $id]);
} else {
$stmt = $db->prepare("INSERT INTO levels (name, slug, resource_id, required_quantity) VALUES (?, ?, ?, ?)");
$stmt->execute([$name, $slug, $resource_id, $required_quantity]);
}
header("Location: admin.php?tab=levels&success=1");
exit;
}
if (isset($_GET["delete_level"])) {
$id = (int)$_GET["delete_level"];
$db->prepare("DELETE FROM levels WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=levels&success=1");
exit;
}
// Handle Resource CRUD
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_resource') {
$id = (int)$_POST['id'];
$name = $_POST["name"];
$slug = $_POST['slug'];
$icon = $_POST['icon'];
$description = $_POST['description'];
$show_in_header = isset($_POST["show_in_header"]) ? 1 : 0;
$image_url = null;
if ($id > 0) {
$stmt_img = $db->prepare("SELECT image_url FROM game_resources WHERE id = ?");
$stmt_img->execute([$id]);
$image_url = $stmt_img->fetchColumn();
}
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
$ext = pathinfo($_FILES['image']["name"], PATHINFO_EXTENSION);
$filename = "res_" . $slug . "_" . time() . "." . $ext;
if (!is_dir("assets/images/resources")) {
mkdir("assets/images/resources", 0775, true);
}
$target = "assets/images/resources/" . $filename;
if (move_uploaded_file($_FILES['image']['tmp_name'], $target)) {
$image_url = $target;
}
}
if ($id > 0) {
$stmt = $db->prepare("UPDATE game_resources SET name = ?, slug = ?, icon = ?, description = ?, image_url = ?, show_in_header = ? WHERE id = ?");
$stmt->execute([$name, $slug, $icon, $description, $image_url, $show_in_header, $id]);
} else {
$stmt = $db->prepare("INSERT INTO game_resources (name, slug, icon, description, image_url, show_in_header) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([$name, $slug, $icon, $description, $image_url, $show_in_header]);
}
header("Location: admin.php?tab=resources&success=1");
exit;
}
if (isset($_GET['delete_resource'])) {
$id = (int)$_GET['delete_resource'];
$db->prepare("DELETE FROM game_resources WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=resources&success=1");
exit;
}
// Handle Guild System Config
error_log(print_r($_POST, true));
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "update_guild_requirements") {
$db->exec("DELETE FROM guild_creation_requirements");
$stmt = $db->prepare("INSERT INTO guild_creation_requirements (resource_id, amount) VALUES (?, ?)");
foreach ($_POST as $key => $value) {
if (strpos($key, "res_") === 0 && (int)$value >= 0) {
$res_id = (int)str_replace("res_", "", $key);
$stmt->execute([$res_id, (int)$value]);
}
}
if (isset($_POST['guild_member_limit'])) {
$stmt = $db->prepare("UPDATE guild_restrictions SET value = ? WHERE restriction_key = 'member_limit'");
$stmt->execute([(int)$_POST['guild_member_limit']]);
}
header("Location: admin.php?tab=guilds&success=1");
exit;
}
// Handle Lootbox CRUD
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_grade') {
$id = (int)$_POST['id'];
$name = trim($_POST["name"]);
$slug = trim($_POST['slug']);
$user_type = $_POST['user_type'];
$min_level = ($user_type === 'utilisateur') ? (int)$_POST['min_level'] : null;
$max_level = ($user_type === 'utilisateur') ? (int)$_POST['max_level'] : null;
if ($user_type === 'utilisateur' && $min_level > $max_level) {
header('Location: ?tab=ranks&error=invalid_range');
exit;
}
// Check for overlap if user_type is 'utilisateur'
if ($user_type === 'utilisateur') {
$check = db()->prepare("SELECT id FROM grades WHERE user_type = 'utilisateur' AND id != ? AND NOT (max_level < ? OR min_level > ?)");
$check->execute([$id, $min_level, $max_level]);
if ($check->fetch()) {
header('Location: ?tab=ranks&error=overlap_levels');
exit;
}
}
try {
$image_url = null;
if (!empty($_FILES["image"]["name"])) {
$ext = pathinfo($_FILES["image"]["name"], PATHINFO_EXTENSION);
$filename = "grade_" . time() . "_" . uniqid() . "." . $ext;
if (!is_dir("assets/images/grades/")) mkdir("assets/images/grades/", 0775, true);
move_uploaded_file($_FILES["image"]["tmp_name"], "assets/images/grades/" . $filename);
$image_url = "assets/images/grades/" . $filename;
}
if ($id > 0) {
$stmt = db()->prepare("UPDATE grades SET name = ?, slug = ?, user_type = ?, min_level = ?, max_level = ?, image_url = COALESCE(?, image_url) WHERE id = ?");
$stmt->execute([$name, $slug, $user_type, $min_level, $max_level, $image_url, $id]);
} else {
$stmt = db()->prepare("INSERT INTO grades (name, slug, user_type, min_level, max_level, image_url) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([$name, $slug, $user_type, $min_level, $max_level, $image_url]);
}
header('Location: ?tab=ranks&success=1');
exit;
} catch (PDOException $e) {
header('Location: ?tab=ranks&error=db');
exit;
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'upsert_lootbox') {
$id = (int)$_POST['id'];
$name = $_POST["name"];
$slug = $_POST['slug'];
$description = $_POST['description'];
if ($id > 0) {
$stmt = $db->prepare("UPDATE lootboxes SET name = ?, slug = ?, description = ? WHERE id = ?");
$stmt->execute([$name, $slug, $description, $id]);
} else {
$stmt = $db->prepare("INSERT INTO lootboxes (name, slug, description) VALUES (?, ?, ?)");
$stmt->execute([$name, $slug, $description]);
$id = $db->lastInsertId();
}
// Handle Rolls
$db->prepare("DELETE FROM lootbox_rolls WHERE lootbox_id = ?")->execute([$id]);
if (isset($_POST['rolls_count']) && is_array($_POST['rolls_count'])) {
$ins_roll = $db->prepare("INSERT INTO lootbox_rolls (lootbox_id, roll_count, probability) VALUES (?, ?, ?)");
foreach ($_POST['rolls_count'] as $idx => $rc) {
$prob = (float)$_POST['rolls_prob'][$idx];
if ($prob > 0) {
$ins_roll->execute([$id, (int)$rc, $prob]);
}
}
}
// Handle Items
$db->prepare("DELETE FROM lootbox_items WHERE lootbox_id = ?")->execute([$id]);
if (isset($_POST['item_slug']) && is_array($_POST['item_slug'])) {
$ins_item = $db->prepare("INSERT INTO lootbox_items (lootbox_id, resource_slug, probability, quantity_min, quantity_max, is_guaranteed) VALUES (?, ?, ?, ?, ?, ?)");
foreach ($_POST['item_slug'] as $idx => $islug) {
$is_guaranteed = isset($_POST['item_is_guaranteed'][$idx]) ? (int)$_POST['item_is_guaranteed'][$idx] : 0;
$iprob = $is_guaranteed ? 100.00 : (float)$_POST['item_prob'][$idx];
if ($is_guaranteed || $iprob > 0) {
$qmin = (int)$_POST['item_qmin'][$idx];
$qmax = (int)$_POST['item_qmax'][$idx];
$ins_item->execute([$id, $islug ?: null, $iprob, $qmin, $qmax, $is_guaranteed]);
}
}
}
header("Location: admin.php?tab=lootboxes&success=1");
exit;
}
if (isset($_GET['delete_lootbox'])) {
$id = (int)$_GET['delete_lootbox'];
$db->prepare("DELETE FROM lootboxes WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=lootboxes&success=1");
exit;
}
// Handle Project Log CRUD
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "upsert_project_log") {
$id = (int)$_POST["id"];
$version = $_POST["version"];
$title = $_POST["title"];
$content_log = $_POST["content"];
if ($id > 0) {
$stmt = $db->prepare("UPDATE project_logs SET version = ?, title = ?, content = ? WHERE id = ?");
$stmt->execute([$version, $title, $content_log, $id]);
} else {
$stmt = $db->prepare("INSERT INTO project_logs (version, title, content) VALUES (?, ?, ?)");
$stmt->execute([$version, $title, $content_log]);
}
header("Location: admin.php?tab=project_logs&success=1");
exit;
}
if (isset($_GET['delete_grade'])) {
$id = (int)$_GET['delete_grade'];
$stmt = db()->prepare("DELETE FROM grades WHERE id = ?");
$stmt->execute([$id]);
header('Location: ?tab=ranks&success=deleted');
exit;
}
if (isset($_GET["delete_project_log"])) {
$id = (int)$_GET["delete_project_log"];
$db->prepare("DELETE FROM project_logs WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=project_logs&success=1");
exit;
}
// Handle Unit CRUD
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["action"]) && $_POST["action"] === "upsert_unit") {
$id = (int)$_POST["id"];
$name = $_POST["name"];
$slug = $_POST["slug"];
$faction_id = !empty($_POST["faction_id"]) ? (int)$_POST["faction_id"] : null;
$can_be_destroyed = isset($_POST["can_be_destroyed"]) ? 1 : 0;
$can_be_captured = isset($_POST["can_be_captured"]) ? 1 : 0;
// Fallback for legacy fields if not in form
$points_per_hit = isset($_POST["points_per_hit"]) ? (int)$_POST["points_per_hit"] : 0;
$bonus_destruction = isset($_POST["bonus_destruction"]) ? (int)$_POST["bonus_destruction"] : 0;
$bonus_capture = isset($_POST["bonus_capture"]) ? (int)$_POST["bonus_capture"] : 0;
$grid_data = $_POST["grid_data"];
$cost_resource_id = !empty($_POST["cost_resource_id"]) ? (int)$_POST["cost_resource_id"] : null;
$cost_amount = (int)$_POST["cost_amount"];
$destruction_resource_id = !empty($_POST["destruction_resource_id"]) ? (int)$_POST["destruction_resource_id"] : null;
$destruction_amount = (int)$_POST["destruction_amount"];
$capture_resource_id = !empty($_POST["capture_resource_id"]) ? (int)$_POST["capture_resource_id"] : null;
$capture_amount = (int)$_POST["capture_amount"];
$image_url = null;
if ($id > 0) {
$stmt_img = $db->prepare("SELECT image_url FROM units WHERE id = ?");
$stmt_img->execute([$id]);
$image_url = $stmt_img->fetchColumn();
}
if (isset($_FILES["image"]) && $_FILES["image"]["error"] === UPLOAD_ERR_OK) {
$ext = pathinfo($_FILES["image"]["name"], PATHINFO_EXTENSION);
$filename = "unit_" . $slug . "_" . time() . "." . $ext;
$target = "assets/images/units/" . $filename;
if (!is_dir("assets/images/units/")) mkdir("assets/images/units/", 0775, true);
if (move_uploaded_file($_FILES["image"]["tmp_name"], $target)) {
$image_url = $target;
}
}
if ($id > 0) {
$stmt = $db->prepare("UPDATE units SET name = ?, slug = ?, faction_id = ?, can_be_destroyed = ?, can_be_captured = ?, points_per_hit = ?, bonus_destruction = ?, bonus_capture = ?, grid_data = ?, image_url = ?, cost_resource_id = ?, cost_amount = ?, destruction_resource_id = ?, destruction_amount = ?, capture_resource_id = ?, capture_amount = ? WHERE id = ?");
$stmt->execute([$name, $slug, $faction_id, $can_be_destroyed, $can_be_captured, $points_per_hit, $bonus_destruction, $bonus_capture, $grid_data, $image_url, $cost_resource_id, $cost_amount, $destruction_resource_id, $destruction_amount, $capture_resource_id, $capture_amount, $id]);
} else {
$stmt = $db->prepare("INSERT INTO units (name, slug, faction_id, can_be_destroyed, can_be_captured, points_per_hit, bonus_destruction, bonus_capture, grid_data, image_url, cost_resource_id, cost_amount, destruction_resource_id, destruction_amount, capture_resource_id, capture_amount) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$name, $slug, $faction_id, $can_be_destroyed, $can_be_captured, $points_per_hit, $bonus_destruction, $bonus_capture, $grid_data, $image_url, $cost_resource_id, $cost_amount, $destruction_resource_id, $destruction_amount, $capture_resource_id, $capture_amount]);
$id = $db->lastInsertId();
}
// Handle Rewards
$db->prepare("DELETE FROM unit_rewards WHERE unit_id = ?")->execute([$id]);
if (isset($_POST["reward_action"]) && is_array($_POST["reward_action"])) {
$ins_rw = $db->prepare("INSERT INTO unit_rewards (unit_id, action_type, lootbox_id) VALUES (?, ?, ?)");
foreach ($_POST["reward_action"] as $idx => $action) {
$lb_id = (int)$_POST["reward_lootbox_id"][$idx];
if ($lb_id > 0) {
$ins_rw->execute([$id, $action, $lb_id]);
}
}
}
header("Location: admin.php?tab=units&success=1");
exit;
}
if (isset($_GET["delete_unit"])) {
$id = (int)$_GET["delete_unit"];
$db->prepare("DELETE FROM units WHERE id = ?")->execute([$id]);
header("Location: admin.php?tab=units&success=1");
exit;
}
// --- DATA FETCHING ---
$users_list = [];
$objects_list = [];
$statuses_list = [];
$status_rules_list = [];
$status_profiles_list = [];
$settlement_types_list = [];
$modifiers_list = [];
$factions_list = [];
$resources_list = [];
$lootboxes_list = [];
$project_logs_list = [];
$units_list = [];
$titles_list = [];
$badges_list = [];
$levels_list = [];
$ranks_list = [];
$guild_requirements = [];
$guild_member_limit = 50;
if ($tab === 'users') {
$users_list = $db->query("SELECT id, username, email, role FROM users ORDER BY username ASC")->fetchAll();
} elseif ($tab === 'player') {
$users_list = $db->query("SELECT id, username FROM users ORDER BY username ASC")->fetchAll();
$resources_list = $db->query("SELECT id, name FROM game_resources ORDER BY name ASC")->fetchAll();
} elseif ($tab === 'objects') {
$objects_list = $db->query("SELECT * FROM celestial_object_types ORDER BY name ASC")->fetchAll();
foreach ($objects_list as &$obj) {
$stmt = $db->prepare("SELECT modifier_id FROM celestial_object_type_modifiers WHERE celestial_object_type_id = ?");
$stmt->execute([$obj['id']]);
$obj['modifier_ids'] = $stmt->fetchAll(PDO::FETCH_COLUMN);
}
unset($obj);
$modifiers_list = $db->query("SELECT * FROM modifiers ORDER BY type, name ASC")->fetchAll();
$status_profiles_list = $db->query("SELECT * FROM celestial_object_status_profiles ORDER BY name ASC")->fetchAll();
} elseif ($tab === 'statuses') {
$statuses_list = $db->query("SELECT * FROM celestial_object_statuses ORDER BY name ASC")->fetchAll();
$status_rules_list = $db->query("SELECT r.*, s.name as status_name, p.name as profile_name FROM celestial_object_status_rules r JOIN celestial_object_statuses s ON r.status_id = s.id LEFT JOIN celestial_object_status_profiles p ON r.profile_id = p.id ORDER BY r.profile_id, r.priority DESC, r.name ASC")->fetchAll();
$status_profiles_list = $db->query("SELECT * FROM celestial_object_status_profiles ORDER BY name ASC")->fetchAll();
$factions_list = $db->query("SELECT * FROM factions ORDER BY name ASC")->fetchAll();
} elseif ($tab === 'settlement_types') {
$settlement_types_list = $db->query("SELECT * FROM settlement_types ORDER BY name ASC")->fetchAll();
} elseif ($tab === 'modifiers') {
$modifiers_list = $db->query("SELECT * FROM modifiers ORDER BY type, name ASC")->fetchAll();
} elseif ($tab === 'factions') {
$factions_list = $db->query("SELECT * FROM factions ORDER BY name ASC")->fetchAll();
foreach ($factions_list as &$f) {
$stmt = $db->prepare("SELECT faction_id_1 as ally_id FROM faction_alliances WHERE faction_id_2 = ? UNION SELECT faction_id_2 as ally_id FROM faction_alliances WHERE faction_id_1 = ?");
$stmt->execute([$f['id'], $f['id']]);
$f['alliance_ids'] = $stmt->fetchAll(PDO::FETCH_COLUMN);
}
unset($f);
} elseif ($tab === 'levels') {
$levels_list = $db->query("SELECT l.*, r.name as resource_name FROM levels l JOIN game_resources r ON l.resource_id = r.id ORDER BY l.required_quantity ASC")->fetchAll();
$resources_list = $db->query("SELECT id, name FROM game_resources ORDER BY name ASC")->fetchAll();
$lootboxes_list = $db->query("SELECT id, name FROM lootboxes ORDER BY name ASC")->fetchAll();
} elseif ($tab === 'resources') {
$resources_list = $db->query("SELECT * FROM game_resources ORDER BY name ASC")->fetchAll();
} elseif ($tab === 'project_logs') {
$project_logs_list = $db->query("SELECT * FROM project_logs ORDER BY created_at DESC")->fetchAll();
} elseif ($tab === 'badges') {
$titles_list = $db->query("SELECT * FROM titles ORDER BY name ASC")->fetchAll();
$badges_list = $db->query("SELECT * FROM badges ORDER BY name ASC")->fetchAll();
} elseif ($tab === 'ranks') {
$ranks_list = $db->query("SELECT * FROM grades ORDER BY user_type DESC, min_level ASC")->fetchAll();
} elseif ($tab === 'lootboxes') {
$lootboxes_list = $db->query("SELECT * FROM lootboxes ORDER BY name ASC")->fetchAll();
$resources_list = $db->query("SELECT name, slug FROM game_resources ORDER BY name ASC")->fetchAll();
foreach ($lootboxes_list as &$lb) {
$stmt_r = $db->prepare("SELECT * FROM lootbox_rolls WHERE lootbox_id = ?");
$stmt_r->execute([$lb['id']]);
$lb['rolls'] = $stmt_r->fetchAll();
$stmt_i = $db->prepare("SELECT * FROM lootbox_items WHERE lootbox_id = ?");
$stmt_i->execute([$lb['id']]);
$lb['items'] = $stmt_i->fetchAll();
}
unset($lb);
} elseif ($tab === 'guilds') {
$guild_requirements = $db->query("SELECT r.id, r.name, r.icon, gr.amount FROM game_resources r LEFT JOIN guild_creation_requirements gr ON r.id = gr.resource_id")->fetchAll();
$stmt = $db->query("SELECT value FROM guild_restrictions WHERE restriction_key = 'member_limit'");
$guild_member_limit = $stmt->fetchColumn() ?: 50;
}
elseif ($tab === "units") {
$units_list = $db->query("SELECT u.*, f.name as faction_name FROM units u LEFT JOIN factions f ON u.faction_id = f.id ORDER BY u.name ASC")->fetchAll();
foreach ($units_list as &$unit) {
$stmt_rw = $db->prepare("SELECT action_type, lootbox_id, resource_id, amount FROM unit_rewards WHERE unit_id = ?");
$stmt_rw->execute([$unit["id"]]);
$unit["rewards"] = $stmt_rw->fetchAll();
}
unset($unit);
$factions_list = $db->query("SELECT id, name FROM factions ORDER BY name ASC")->fetchAll();
$resources_list = $db->query("SELECT id, name FROM game_resources ORDER BY name ASC")->fetchAll();
$lootboxes_list = $db->query("SELECT id, name FROM lootboxes ORDER BY name ASC")->fetchAll();
}
?>
Console Admin - Nexus
Erreur : La quantité doit être un nombre strictement positif.
Erreur Base de Données : L'opération a échoué.
Erreur : Veuillez remplir tous les champs et sélectionner au moins un joueur.
Opération effectuée avec succès.
Gestion des Joueurs (Gameplay)
Gestion des Rôles
| Utilisateur | Email | Rôle Actuel | Nouveau Rôle |
|
|
|
|
Gestion des Unités
| Image |
Nom / Slug |
Faction |
Propriétés |
Récompenses |
Actions |
| Aucune unité configurée. |
|
|
|
Coût:
● Destructible
● Capturable
|
Destr: +
Capt: +
:
Lootbox:
|
Supprimer
|
Gestion des Niveaux
| Nom |
Slug |
Ressource requise |
Quantité requise |
Actions |
| Aucun niveau configuré. |
|
|
|
|
Supprimer
|
Gestion des Grades
Erreur : Les intervalles de niveaux pour les grades utilisateurs ne doivent pas se chevaucher.
Erreur : Le niveau maximum doit être supérieur ou égal au niveau minimum.
| Visuel |
Nom |
Slug |
Type |
Intervalle Niveau |
Actions |
| Aucun grade configuré. |
" style="width:40px;"> | |
|
|
-
N/A
|
Supprimer
|
Gestion des Guildes
Titres & Badges
Objets Célestes
| Visuel | Nom | Contrôles | Règles | Bonus/Malus | Actions |
?v=" style="max-width: 40px; max-height: 40px; display: block; margin: 0 auto;">
|
|
ORBITAL
TERRESTRE
|
Fixe";
foreach($status_profiles_list as $p) if($p['id'] == $o['status_profile_id']) $p_name = htmlspecialchars($p["name"]);
echo $p_name;
?>
|
prepare("SELECT m.name, m.type FROM modifiers m JOIN celestial_object_type_modifiers cotm ON m.id = cotm.modifier_id WHERE cotm.celestial_object_type_id = ?");
$stmt->execute([$o['id']]);
$m_list = $stmt->fetchAll();
foreach ($m_list as $ml): ?>
|
Supprimer
|
Gestion des Bonus & Malus
| Type | Nom | Description | Slug | Actions |
|
|
|
|
|
Supprimer
|
Statuts / États
| Profile | Priorité | Nom / Condition | Statut | Actions |
|
|
Toujours vrai';
?>
|
|
Supprimer
|
Lieux et points d’intérêt
Gestion des Factions
| Couleur | Visuel | Nom | Slug | Alliances | Actions |
|
?v=" style="max-width: 40px; max-height: 40px;">
|
|
|
prepare("SELECT f.name FROM factions f JOIN faction_alliances fa ON (f.id = fa.faction_id_1 OR f.id = fa.faction_id_2) WHERE (fa.faction_id_1 = ? OR fa.faction_id_2 = ?) AND f.id != ?");
$stmt->execute([$f['id'], $f['id'], $f['id']]);
$allies = $stmt->fetchAll(PDO::FETCH_COLUMN);
if(empty($allies)) echo 'Aucune';
foreach($allies as $ally) echo '' . htmlspecialchars($ally) . '';
?>
|
Supprimer
|
Gestion des Ressources
| Visuel | Header | Nom | Slug | Actions |
?v=" style="max-width: 30px; max-height: 30px;">
|
|
|
|
Supprimer
|
Système de Lootboxes
| Nom | Slug | Tirages Possibles | Nombre d'items | Actions |
|
|
|
|
Supprimer
|
Journal de Bord du Projet