HomeController.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. <?php
  2. /**
  3. * Classe HomeController
  4. *
  5. * Gère les actions liées à la page d'accueil.
  6. */
  7. if (!class_exists('HomeController')) {
  8. class HomeController
  9. {
  10. /**
  11. * Affiche la page d'accueil.
  12. */
  13. public static function index()
  14. {
  15. $data = [
  16. 'title' => 'Bienvenue dans l\'application',
  17. 'content' => 'Ceci est le contenu principal de la page d\'accueil.',
  18. 'loaded_map' => null,
  19. 'map_data' => null
  20. ];
  21. // Vérifier si une carte doit être chargée
  22. if (isset($_GET['load']) && is_numeric($_GET['load'])) {
  23. $mapId = (int) $_GET['load'];
  24. $map = MapModel::findMap($mapId);
  25. $mapRow = MapModel::getRowById($mapId);
  26. if ($map && $mapRow) {
  27. // Récupérer le template depuis les données JSON
  28. $mapJsonData = json_decode($mapRow['data'], true) ?: [];
  29. $template = $mapJsonData['template'] ?? 'neutral';
  30. // Charger les définitions de tuiles du template
  31. require_once __DIR__ . '/../Models/Templates/TemplateFactory.php';
  32. $templateClass = TemplateFactory::get($template);
  33. $tileDefinitions = $templateClass ? $templateClass::tileDefinitions() : [];
  34. // Obtenir les données des hexagones
  35. $hexes = [];
  36. foreach ($map->getAllHexagons() as $q => $row) {
  37. foreach ($row as $r => $hexagon) {
  38. $tile = $hexagon->getTile();
  39. $hexes[] = [
  40. 'q' => $hexagon->getQ(),
  41. 'r' => $hexagon->getR(),
  42. 'tile' => $tile ? [
  43. 'type' => $tile->getType(),
  44. 'properties' => $tile->getAllProperties()
  45. ] : null
  46. ];
  47. }
  48. }
  49. $data['loaded_map'] = $map;
  50. $data['map_data'] = [
  51. 'id' => $mapId,
  52. 'name' => $map->getName(),
  53. 'width' => $map->getWidth(),
  54. 'height' => $map->getHeight(),
  55. 'created_at' => $map->getCreatedAt(),
  56. 'updated_at' => $map->getUpdatedAt(),
  57. 'statistics' => $map->getStatistics(),
  58. 'template' => $template,
  59. 'tileDefinitions' => $tileDefinitions,
  60. 'hexes' => $hexes
  61. ];
  62. $data['title'] = $map->getName() . ' - Map Generator';
  63. } else {
  64. $data['load_error'] = 'Carte non trouvée (ID: ' . $mapId . '). Vérifiez que l\'ID est correct.';
  65. }
  66. }
  67. Renderer::render('home', $data);
  68. }
  69. /**
  70. * Affiche le formulaire de création d'un nouveau projet.
  71. */
  72. public static function newProject()
  73. {
  74. $data = [
  75. 'title' => 'Nouveau projet - Map Generator',
  76. 'page' => 'new_project'
  77. ];
  78. // Découvrir les templates disponibles
  79. require_once __DIR__ . '/../Models/Templates/TemplateFactory.php';
  80. $templates = TemplateFactory::listAvailable();
  81. $data['templates'] = $templates;
  82. Renderer::render('projects/new', $data);
  83. }
  84. /**
  85. * Crée un nouveau projet (endpoint POST)
  86. * Accepte form POST classique ou JSON
  87. */
  88. public static function createProject()
  89. {
  90. if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  91. http_response_code(405);
  92. echo json_encode(['success' => false, 'message' => 'Méthode non autorisée']);
  93. return;
  94. }
  95. $contentType = $_SERVER['CONTENT_TYPE'] ?? '';
  96. if (strpos($contentType, 'application/json') !== false) {
  97. $raw = file_get_contents('php://input');
  98. $input = json_decode($raw, true) ?: [];
  99. } else {
  100. $input = $_POST;
  101. }
  102. $name = isset($input['name']) ? trim($input['name']) : '';
  103. $description = $input['description'] ?? null;
  104. $template = $input['template'] ?? null;
  105. if (!$name) {
  106. http_response_code(400);
  107. echo json_encode(['success' => false, 'message' => 'Le nom est requis']);
  108. return;
  109. }
  110. // Si un radius est envoyé, créer la map via radius
  111. $radius = isset($input['radius']) ? (int) $input['radius'] : null;
  112. $map = null;
  113. if ($radius && $radius > 0) {
  114. $map = Map::fromRadius($name, $radius);
  115. } else {
  116. // Fallback: utiliser width/height
  117. $width = isset($input['width']) ? (int) $input['width'] : 10;
  118. $height = isset($input['height']) ? (int) $input['height'] : 10;
  119. $map = new Map($name, $width, $height);
  120. }
  121. // Appliquer le template si fourni (ou template neutre par défaut)
  122. require_once __DIR__ . '/../Models/Templates/TemplateFactory.php';
  123. $templateClass = TemplateFactory::get($template);
  124. if (class_exists($templateClass) && method_exists($templateClass, 'applyTemplate')) {
  125. $templateClass::applyTemplate($map);
  126. }
  127. $created = MapModel::create($map, $description, $template, $radius);
  128. // Détecter AJAX
  129. $isAjax = false;
  130. $xrw = $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '';
  131. if (strtolower($xrw) === 'xmlhttprequest' || strpos($contentType, 'application/json') !== false) {
  132. $isAjax = true;
  133. }
  134. if ($created) {
  135. if ($isAjax) {
  136. echo json_encode(['success' => true, 'id' => $created]);
  137. } else {
  138. header('Location: /projects');
  139. }
  140. } else {
  141. if ($isAjax) {
  142. http_response_code(500);
  143. echo json_encode(['success' => false, 'message' => 'Erreur lors de la création']);
  144. } else {
  145. header('Location: /projects');
  146. }
  147. }
  148. }
  149. /**
  150. * Affiche la liste des projets (cartes) disponibles.
  151. */
  152. public static function projects()
  153. {
  154. // Récupérer la liste des cartes depuis la base de données
  155. $maps = MapModel::paginate(1, 20)['data']; // Récupérer les 20 premières cartes
  156. // Récupérer les statistiques globales
  157. $stats = MapModel::getGlobalStats();
  158. $data = [
  159. 'title' => 'Mes projets - Map Generator',
  160. 'page' => 'projects',
  161. 'maps' => $maps,
  162. 'stats' => $stats
  163. ];
  164. Renderer::render('projects/index', $data);
  165. }
  166. /**
  167. * Affiche le formulaire d'édition pour une carte existante
  168. * @param int $id
  169. */
  170. public static function editProject(int $id)
  171. {
  172. // Charger la map via MapModel
  173. $map = MapModel::findMap($id);
  174. if (!$map) {
  175. http_response_code(404);
  176. echo 'Carte non trouvée';
  177. return;
  178. }
  179. // Préparer les données de la view
  180. require_once __DIR__ . '/../Models/Templates/TemplateFactory.php';
  181. $templates = TemplateFactory::listAvailable();
  182. // Récupérer la row brute pour extraire les métadonnées JSON
  183. $rawRow = null;
  184. try {
  185. $rawRow = MapModel::getRowById($id);
  186. } catch (Throwable $e) {
  187. $rawRow = null;
  188. }
  189. $templateId = null;
  190. $radiusVal = null;
  191. if (!empty($rawRow['data'])) {
  192. $decoded = is_string($rawRow['data']) ? json_decode($rawRow['data'], true) : $rawRow['data'];
  193. if (is_array($decoded)) {
  194. $templateId = $decoded['template'] ?? null;
  195. $radiusVal = isset($decoded['radius']) ? (int)$decoded['radius'] : null;
  196. }
  197. }
  198. $data = [
  199. 'title' => 'Édition de la carte - ' . $map->getName(),
  200. 'page' => 'projects_edit',
  201. 'map' => $map,
  202. 'templates' => $templates,
  203. 'templateId' => $templateId,
  204. 'radiusVal' => $radiusVal,
  205. 'mapId' => $id,
  206. 'mapDescription' => $rawRow['description'] ?? ''
  207. ];
  208. Renderer::render('projects/edit', $data);
  209. }
  210. /**
  211. * Traite la mise à jour d'une carte (POST)
  212. */
  213. public static function updateProject()
  214. {
  215. if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  216. http_response_code(405);
  217. echo json_encode(['success' => false, 'message' => 'Méthode non autorisée']);
  218. return;
  219. }
  220. $input = $_POST;
  221. $id = isset($input['id']) ? (int)$input['id'] : null;
  222. if (!$id) {
  223. http_response_code(400);
  224. echo json_encode(['success' => false, 'message' => 'ID manquant']);
  225. return;
  226. }
  227. $name = isset($input['name']) ? trim($input['name']) : '';
  228. $description = $input['description'] ?? null;
  229. $template = $input['template'] ?? null;
  230. $radius = isset($input['radius']) ? (int)$input['radius'] : null;
  231. $existing = MapModel::findMap($id);
  232. if (!$existing) {
  233. http_response_code(404);
  234. echo json_encode(['success' => false, 'message' => 'Carte non trouvée']);
  235. return;
  236. }
  237. // Par défaut, préserver le contenu existant
  238. $map = $existing;
  239. // Récupérer la row brute pour comparer le radius existant
  240. $existingRow = MapModel::getRowById($id);
  241. $existingRadius = null;
  242. if (!empty($existingRow['data'])) {
  243. $decoded = is_string($existingRow['data']) ? json_decode($existingRow['data'], true) : $existingRow['data'];
  244. if (is_array($decoded) && isset($decoded['radius'])) {
  245. $existingRadius = (int)$decoded['radius'];
  246. }
  247. }
  248. // Si l'utilisateur a fourni un radius et qu'il est différent de l'existant, reconstruire la map
  249. if ($radius && $radius > 0 && $radius !== $existingRadius) {
  250. $map = Map::fromRadius($name ?: $existing->getName(), $radius);
  251. } else {
  252. // Ne pas reconstruire : mettre à jour seulement le nom si fourni
  253. if (!empty($name)) {
  254. $map->setName($name);
  255. }
  256. }
  257. // Appliquer le template si fourni
  258. require_once __DIR__ . '/../Models/Templates/TemplateFactory.php';
  259. $templateClass = TemplateFactory::get($template);
  260. if (class_exists($templateClass) && method_exists($templateClass, 'applyTemplate')) {
  261. $templateClass::applyTemplate($map);
  262. }
  263. // Mettre à jour
  264. $ok = MapModel::update($id, $map, $description, $template, $radius);
  265. if ($ok) {
  266. header('Location: /projects');
  267. } else {
  268. http_response_code(500);
  269. echo 'Erreur lors de la mise à jour';
  270. }
  271. }
  272. /**
  273. * Supprime une carte (endpoint POST)
  274. * Accepte JSON (AJAX) ou form POST standard.
  275. */
  276. public static function deleteProject()
  277. {
  278. // Méthode attendue: POST
  279. if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  280. http_response_code(405);
  281. echo json_encode(['success' => false, 'message' => 'Méthode non autorisée']);
  282. return;
  283. }
  284. // Lire input JSON si présent
  285. $input = [];
  286. $contentType = $_SERVER['CONTENT_TYPE'] ?? '';
  287. if (strpos($contentType, 'application/json') !== false) {
  288. $raw = file_get_contents('php://input');
  289. $input = json_decode($raw, true) ?: [];
  290. } else {
  291. $input = $_POST;
  292. }
  293. $id = isset($input['id']) ? (int) $input['id'] : null;
  294. if (!$id) {
  295. http_response_code(400);
  296. echo json_encode(['success' => false, 'message' => 'ID manquant']);
  297. return;
  298. }
  299. // Vérifier existence
  300. if (!MapModel::exists($id)) {
  301. http_response_code(404);
  302. echo json_encode(['success' => false, 'message' => 'Carte non trouvée']);
  303. return;
  304. }
  305. $deleted = MapModel::delete($id);
  306. // Détecter si la requête est AJAX
  307. $isAjax = false;
  308. $xrw = $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '';
  309. if (strtolower($xrw) === 'xmlhttprequest' || strpos($contentType, 'application/json') !== false) {
  310. $isAjax = true;
  311. }
  312. if ($isAjax) {
  313. if ($deleted) {
  314. echo json_encode(['success' => true]);
  315. } else {
  316. http_response_code(500);
  317. echo json_encode(['success' => false, 'message' => 'Erreur lors de la suppression']);
  318. }
  319. return;
  320. }
  321. // Pour les requêtes classiques (form POST), utiliser les messages flash en session avant redirection
  322. if (session_status() === PHP_SESSION_NONE) {
  323. session_start();
  324. }
  325. if ($deleted) {
  326. $_SESSION['flash'][] = ['type' => 'success', 'message' => 'La carte a été supprimée avec succès.'];
  327. } else {
  328. $_SESSION['flash'][] = ['type' => 'error', 'message' => 'Une erreur est survenue lors de la suppression de la carte.'];
  329. }
  330. header('Location: /projects');
  331. return;
  332. }
  333. }
  334. }