Files
genshin-world/src/Controller/RegionController.php
2025-07-15 01:15:37 +02:00

180 lines
7.2 KiB
PHP

<?php
namespace App\Controller;
use App\Entity\Grid;
use App\Entity\Region;
use App\Kernel;
use App\Repository\GridRepository;
use App\Repository\MapRepository;
use App\Repository\NodeRepository;
use App\Repository\RegionRepository;
use App\Repository\WorldmarkCategoryRepository;
use App\Repository\WorldmarkRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class RegionController extends AbstractController {
public function __construct(private EntityManagerInterface $_em,
private RegionRepository $regionRepository,
private GridRepository $gridRepository,
private MapRepository $mapRepository,
private WorldmarkCategoryRepository $worldmarkCategoryRepository,
private WorldmarkRepository $worldmarkRepository,
private NodeRepository $nodeRepository) {}
#[Route('/worldmap', name: 'fo_worldmap_redirect_a', methods: ['GET'])]
public function redirectA(): RedirectResponse {
return $this->redirectToRoute('fo_region_show', array('slug'=>'mondstadt'), Response::HTTP_MOVED_PERMANENTLY);
}
#[Route('/worldmap/{slug}', name: 'fo_worldmap_redirect_b', methods: ['GET'])]
public function redirectB(Region $region): RedirectResponse {
return $this->redirectToRoute('fo_region_show', array('slug'=>$region->getSlug()), Response::HTTP_MOVED_PERMANENTLY);
}
#[Route('/{slug}', name: 'fo_region_show', methods: ['GET'])]
public function show(Request $request, ?Region $region): Response {
$version = $request->query->get('v');
if(!$version
|| !in_array(floatval($version), Kernel::SUPPORTED_GAME_VERSION)
|| (floatval($version) < Kernel::GAME_VERSION && !$this->isGranted('ROLE_ADMIN'))
|| (floatval($version) > Kernel::GAME_VERSION && !$this->isGranted('ROLE_CONTRIBUTOR'))) {
$version = Kernel::GAME_VERSION;
} else {
$version = floatval($version);
}
if(!$region
|| $region->getVersion() > $version
|| !$region->getIsActive() && !$this->isGranted('ROLE_CONTRIBUTOR')) {
throw $this->createNotFoundException();
}
$_region = $region->getIsAlias() ? $region->getParentRegion() : $region;
$cells = $this->gridRepository->getGridCells($_region);
$maps = $this->mapRepository->getCellsMap($cells, $version);
$grid = $this->gridRepository->buildWorldmap($version, $cells, $maps, true);
$worldmarks = $this->worldmarkRepository->getRegionWorldmarks($_region, $version);
$nodes = $this->nodeRepository->getGridNodes($cells, $worldmarks, $version, $this->isGranted('ROLE_ADMIN'));
$worldmarksData = array();
foreach($worldmarks as $worldmark) {
if(!array_key_exists($worldmark->getCategory()->getSlug(), $worldmarksData)) {
$worldmarksData[$worldmark->getCategory()->getSlug()]['_data'] = $worldmark->getCategory();
$worldmarksData[$worldmark->getCategory()->getSlug()]['_worldmarks'] = array();
}
$worldmarksData[$worldmark->getCategory()->getSlug()]['_worldmarks'][] = $worldmark;
}
$nodesData = array();
foreach($nodes as $node) {
$nodesData["grid_{$node->getGrid()->getId()}"][] = $node;
}
return $this->render('woldmap/show.html.twig', array(
// 'title' => "Genshin Impact interactive map of {$_region->getName()}",
'title' => "{$_region->getName()} interactive map - Genshin Impact - Genshin World",
'region' => $_region,
'regionSlug' => $region->getSlug(),
'version' => $version,
'grid' => $grid,
'worldmarksData' => $worldmarksData,
'nodes' => $nodesData,
'anchor' => $region->getIsAlias() ? $region->getAnchor() : null,
'filter'=>$request->get('filter'),
));
}
#[Route('/dashboard/regions', name: 'bo_region_index', methods: ['GET'])]
public function index(): Response {
$this->denyAccessUnlessGranted('ROLE_ADMIN');
return $this->render('_dashboard/region/index.html.twig', array(
'title' => "Dashboard: Regions index",
));
}
#[Route('/dashboard/regions/new', name: 'bo_region_new', methods: ['GET', 'POST'])]
public function new(Request $request): Response {
$this->denyAccessUnlessGranted('ROLE_ADMIN');
$region = new Region();
$form = $this->regionRepository->getForm('bo_region_new', $region);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$this->_em->persist($region);
if($region->getIsAlias()) {
$region->setGridHeight(0);
$region->setGridWidth(0);
}
if($region->getGridHeight() > 0 && $region->getGridWidth() > 0) {
for($row = 1; $row <= $region->getGridHeight(); $row++) {
for($col = 1; $col <= $region->getGridWidth(); $col++) {
$grid = new Grid();
$grid->setRegion($region)
->setRow($row)
->setCol($col);
$this->_em->persist($grid);
}
}
}
$this->_em->flush();
return $this->redirectToRoute('bo_region_index', array(), Response::HTTP_SEE_OTHER);
}
return $this->renderForm('_dashboard/region/new.html.twig', array(
'title' => "Dashboard: Create region",
'region' => $region,
'form' => $form,
));
}
#[Route('/dashboard/regions/region-{id}', name: 'bo_region_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Region $region): Response {
$this->denyAccessUnlessGranted('ROLE_ADMIN');
$form = $this->regionRepository->getForm('bo_region_edit', $region);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$this->_em->flush();
return $this->redirectToRoute('bo_region_index', array(), Response::HTTP_SEE_OTHER);
}
return $this->renderForm('_dashboard/region/edit.html.twig', array(
'title' => "Dashboard: Edit region",
'region' => $region,
'form' => $form,
));
}
#[Route('/dashboard/regions/delete-{id}', name: 'bo_region_delete', methods: ['POST'])]
public function delete(Request $request, Region $region): RedirectResponse {
$this->denyAccessUnlessGranted('ROLE_ADMIN');
if($this->isCsrfTokenValid('delete'.$region->getId(), $request->request->get('_token'))) {
$this->_em->remove($region);
$this->_em->flush();
}
return $this->redirectToRoute('bo_region_index', array(), Response::HTTP_SEE_OTHER);
}
}