2020-06-01 21:13:02 +02:00
|
|
|
<?php namespace MapGuesser\Controller;
|
|
|
|
|
2020-06-05 22:22:02 +02:00
|
|
|
use DateTime;
|
2020-06-09 00:56:00 +02:00
|
|
|
use MapGuesser\Interfaces\Authentication\IUser;
|
2020-06-07 23:37:01 +02:00
|
|
|
use MapGuesser\Interfaces\Authorization\ISecured;
|
2020-06-09 00:56:00 +02:00
|
|
|
use MapGuesser\Interfaces\Request\IRequest;
|
2020-06-01 21:13:02 +02:00
|
|
|
use MapGuesser\Interfaces\Response\IContent;
|
2021-05-19 16:33:18 +02:00
|
|
|
use MapGuesser\PersistentData\Model\Challenge;
|
2020-06-19 18:52:07 +02:00
|
|
|
use MapGuesser\PersistentData\Model\Map;
|
2020-06-20 00:03:49 +02:00
|
|
|
use MapGuesser\PersistentData\Model\Place;
|
2021-05-29 00:57:59 +02:00
|
|
|
use MapGuesser\PersistentData\Model\PlaceInChallenge;
|
2020-06-19 18:52:07 +02:00
|
|
|
use MapGuesser\PersistentData\PersistentDataManager;
|
2021-05-19 16:33:18 +02:00
|
|
|
use MapGuesser\Repository\ChallengeRepository;
|
|
|
|
use MapGuesser\Repository\GuessRepository;
|
2020-06-06 02:18:12 +02:00
|
|
|
use MapGuesser\Repository\MapRepository;
|
2021-05-19 16:33:18 +02:00
|
|
|
use MapGuesser\Repository\PlaceInChallengeRepository;
|
2020-06-02 01:16:59 +02:00
|
|
|
use MapGuesser\Repository\PlaceRepository;
|
2021-05-19 16:33:18 +02:00
|
|
|
use MapGuesser\Repository\UserInChallengeRepository;
|
2021-05-06 20:09:05 +02:00
|
|
|
use MapGuesser\Repository\UserPlayedPlaceRepository;
|
2020-06-01 21:13:02 +02:00
|
|
|
use MapGuesser\Response\HtmlContent;
|
2020-06-02 21:44:01 +02:00
|
|
|
use MapGuesser\Response\JsonContent;
|
2020-06-01 21:13:02 +02:00
|
|
|
use MapGuesser\Util\Geo\Bounds;
|
2020-07-04 01:10:03 +02:00
|
|
|
use MapGuesser\Util\Panorama\Pov;
|
2020-06-01 21:13:02 +02:00
|
|
|
|
2020-06-07 23:37:01 +02:00
|
|
|
class MapAdminController implements ISecured
|
2020-06-01 21:13:02 +02:00
|
|
|
{
|
2020-06-10 23:14:19 +02:00
|
|
|
private static string $unnamedMapName = '[unnamed map]';
|
|
|
|
|
2020-06-09 00:56:00 +02:00
|
|
|
private IRequest $request;
|
|
|
|
|
2020-06-19 18:52:07 +02:00
|
|
|
private PersistentDataManager $pdm;
|
|
|
|
|
2020-06-06 02:18:12 +02:00
|
|
|
private MapRepository $mapRepository;
|
|
|
|
|
2020-06-02 01:16:59 +02:00
|
|
|
private PlaceRepository $placeRepository;
|
|
|
|
|
2021-05-06 20:09:05 +02:00
|
|
|
private UserPlayedPlaceRepository $userPlayedPlaceRepository;
|
|
|
|
|
2021-05-19 16:33:18 +02:00
|
|
|
private ChallengeRepository $challengeRepository;
|
|
|
|
|
|
|
|
private GuessRepository $guessRepository;
|
|
|
|
|
|
|
|
private PlaceInChallengeRepository $placeInChallengeRepository;
|
|
|
|
|
|
|
|
private UserInChallengeRepository $userInChallengeRepository;
|
|
|
|
|
2020-06-09 00:56:00 +02:00
|
|
|
public function __construct(IRequest $request)
|
2020-06-02 01:16:59 +02:00
|
|
|
{
|
2020-06-09 00:56:00 +02:00
|
|
|
$this->request = $request;
|
2020-06-19 18:52:07 +02:00
|
|
|
$this->pdm = new PersistentDataManager();
|
2020-06-06 02:18:12 +02:00
|
|
|
$this->mapRepository = new MapRepository();
|
2020-06-02 01:16:59 +02:00
|
|
|
$this->placeRepository = new PlaceRepository();
|
2021-05-06 20:09:05 +02:00
|
|
|
$this->userPlayedPlaceRepository = new UserPlayedPlaceRepository();
|
2021-05-19 16:33:18 +02:00
|
|
|
$this->challengeRepository = new ChallengeRepository();
|
|
|
|
$this->guessRepository = new GuessRepository();
|
|
|
|
$this->placeInChallengeRepository = new PlaceInChallengeRepository();
|
|
|
|
$this->userInChallengeRepository = new UserInChallengeRepository();
|
2020-06-02 01:16:59 +02:00
|
|
|
}
|
|
|
|
|
2020-06-07 23:37:01 +02:00
|
|
|
public function authorize(): bool
|
|
|
|
{
|
2020-06-09 00:56:00 +02:00
|
|
|
$user = $this->request->user();
|
2020-06-07 23:37:01 +02:00
|
|
|
|
2020-06-09 00:56:00 +02:00
|
|
|
return $user !== null && $user->hasPermission(IUser::PERMISSION_ADMIN);
|
2020-06-07 23:37:01 +02:00
|
|
|
}
|
|
|
|
|
2020-06-09 00:56:00 +02:00
|
|
|
public function getMapEditor(): IContent
|
2020-06-02 01:16:59 +02:00
|
|
|
{
|
2020-06-09 00:56:00 +02:00
|
|
|
$mapId = (int) $this->request->query('mapId');
|
2020-06-01 21:13:02 +02:00
|
|
|
|
2020-06-10 23:14:19 +02:00
|
|
|
if ($mapId) {
|
|
|
|
$map = $this->mapRepository->getById($mapId);
|
2020-06-20 00:03:49 +02:00
|
|
|
$places = $this->getPlaces($map);
|
2020-06-10 23:14:19 +02:00
|
|
|
} else {
|
2020-06-19 18:52:07 +02:00
|
|
|
$map = new Map();
|
|
|
|
$map->setName(self::$unnamedMapName);
|
2020-06-10 23:14:19 +02:00
|
|
|
$places = [];
|
|
|
|
}
|
2020-06-01 21:13:02 +02:00
|
|
|
|
2020-07-05 00:58:03 +02:00
|
|
|
return new HtmlContent('admin/map_editor', [
|
|
|
|
'mapId' => $mapId,
|
|
|
|
'mapName' => $map->getName(),
|
|
|
|
'mapDescription' => str_replace('<br>', "\n", $map->getDescription()),
|
2022-05-26 14:21:05 +02:00
|
|
|
'mapUnlisted' => $map->getUnlisted(),
|
2020-07-05 00:58:03 +02:00
|
|
|
'bounds' => $map->getBounds()->toArray(),
|
|
|
|
'places' => &$places
|
|
|
|
]);
|
2020-06-01 21:13:02 +02:00
|
|
|
}
|
|
|
|
|
2020-06-05 19:38:30 +02:00
|
|
|
public function getPlace(): IContent
|
2020-06-02 01:16:59 +02:00
|
|
|
{
|
2020-06-09 00:56:00 +02:00
|
|
|
$placeId = (int) $this->request->query('placeId');
|
2020-06-02 21:44:01 +02:00
|
|
|
|
2020-06-20 00:03:49 +02:00
|
|
|
$place = $this->placeRepository->getById($placeId);
|
2020-06-02 21:44:01 +02:00
|
|
|
|
2020-07-05 00:58:03 +02:00
|
|
|
return new JsonContent(['panoId' => $place->getFreshPanoId()]);
|
2020-06-02 21:44:01 +02:00
|
|
|
}
|
|
|
|
|
2020-06-05 19:38:30 +02:00
|
|
|
public function saveMap(): IContent
|
|
|
|
{
|
|
|
|
$mapId = (int) $this->request->query('mapId');
|
|
|
|
|
2020-06-14 02:36:23 +02:00
|
|
|
\Container::$dbConnection->startTransaction();
|
|
|
|
|
2020-06-19 18:52:07 +02:00
|
|
|
if ($mapId) {
|
|
|
|
$map = $this->mapRepository->getById($mapId);
|
|
|
|
} else {
|
|
|
|
$map = new Map();
|
|
|
|
$map->setName(self::$unnamedMapName);
|
|
|
|
$this->pdm->saveToDb($map);
|
2020-06-10 23:14:19 +02:00
|
|
|
}
|
|
|
|
|
2020-06-05 22:22:02 +02:00
|
|
|
if (isset($_POST['added'])) {
|
|
|
|
$addedIds = [];
|
|
|
|
foreach ($_POST['added'] as $placeRaw) {
|
|
|
|
$placeRaw = json_decode($placeRaw, true);
|
|
|
|
|
2020-06-20 00:03:49 +02:00
|
|
|
$place = new Place();
|
|
|
|
$place->setMap($map);
|
|
|
|
$place->setLat((float) $placeRaw['lat']);
|
|
|
|
$place->setLng((float) $placeRaw['lng']);
|
2020-07-04 01:10:03 +02:00
|
|
|
$place->setPov(new Pov(
|
|
|
|
(float) $placeRaw['pov']['heading'],
|
|
|
|
(float) $placeRaw['pov']['pitch'],
|
|
|
|
(float) $placeRaw['pov']['zoom']
|
|
|
|
));
|
2020-06-20 00:03:49 +02:00
|
|
|
|
|
|
|
if ($placeRaw['panoId'] === -1) {
|
|
|
|
$place->setPanoIdCachedTimestampDate(new DateTime('-1 day'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->pdm->saveToDb($place);
|
|
|
|
|
|
|
|
$addedIds[] = ['tempId' => $placeRaw['id'], 'id' => $place->getId()];
|
2020-06-05 22:22:02 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$addedIds = [];
|
|
|
|
}
|
2020-06-05 19:38:30 +02:00
|
|
|
|
2020-06-05 22:22:02 +02:00
|
|
|
if (isset($_POST['edited'])) {
|
|
|
|
foreach ($_POST['edited'] as $placeRaw) {
|
|
|
|
$placeRaw = json_decode($placeRaw, true);
|
|
|
|
|
2020-06-20 00:03:49 +02:00
|
|
|
$place = $this->placeRepository->getById((int) $placeRaw['id']);
|
|
|
|
$place->setLat((float) $placeRaw['lat']);
|
|
|
|
$place->setLng((float) $placeRaw['lng']);
|
2020-07-04 01:10:03 +02:00
|
|
|
$place->setPov(new Pov(
|
|
|
|
(float) $placeRaw['pov']['heading'],
|
|
|
|
(float) $placeRaw['pov']['pitch'],
|
|
|
|
(float) $placeRaw['pov']['zoom']
|
|
|
|
));
|
2020-06-20 00:03:49 +02:00
|
|
|
$place->setPanoIdCachedTimestampDate(new DateTime('-1 day'));
|
|
|
|
|
|
|
|
$this->pdm->saveToDb($place);
|
2020-06-05 22:22:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($_POST['deleted'])) {
|
|
|
|
foreach ($_POST['deleted'] as $placeRaw) {
|
|
|
|
$placeRaw = json_decode($placeRaw, true);
|
|
|
|
|
2020-06-20 00:03:49 +02:00
|
|
|
$place = $this->placeRepository->getById((int) $placeRaw['id']);
|
|
|
|
|
2021-05-06 20:09:05 +02:00
|
|
|
$this->deletePlace($place);
|
2020-06-05 22:22:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-20 00:03:49 +02:00
|
|
|
$mapBounds = $this->calculateMapBounds($map);
|
2020-06-05 22:22:02 +02:00
|
|
|
|
2020-06-19 18:52:07 +02:00
|
|
|
$map->setBounds($mapBounds);
|
|
|
|
$map->setArea($mapBounds->calculateApproximateArea());
|
2020-06-05 22:22:02 +02:00
|
|
|
|
2020-06-06 02:18:12 +02:00
|
|
|
if (isset($_POST['name'])) {
|
2020-06-19 18:52:07 +02:00
|
|
|
$map->setName($_POST['name'] ? $_POST['name'] : self::$unnamedMapName);
|
2020-06-06 02:18:12 +02:00
|
|
|
}
|
|
|
|
if (isset($_POST['description'])) {
|
2020-06-19 18:52:07 +02:00
|
|
|
$map->setDescription(str_replace(["\n", "\r\n"], '<br>', $_POST['description']));
|
2020-06-06 02:18:12 +02:00
|
|
|
}
|
2022-05-26 14:21:05 +02:00
|
|
|
if (isset($_POST['unlisted'])) {
|
|
|
|
$map->setUnlisted((bool)$_POST['unlisted']);
|
|
|
|
}
|
2020-06-06 02:18:12 +02:00
|
|
|
|
2020-06-19 18:52:07 +02:00
|
|
|
$this->pdm->saveToDb($map);
|
2020-06-05 22:22:02 +02:00
|
|
|
|
2020-06-14 02:36:23 +02:00
|
|
|
\Container::$dbConnection->commit();
|
|
|
|
|
2020-07-05 00:58:03 +02:00
|
|
|
return new JsonContent(['mapId' => $map->getId(), 'added' => $addedIds]);
|
2020-06-05 19:38:30 +02:00
|
|
|
}
|
2020-06-14 02:36:23 +02:00
|
|
|
|
2020-07-05 21:47:32 +02:00
|
|
|
public function deleteMap(): IContent
|
2020-07-04 01:10:03 +02:00
|
|
|
{
|
2020-06-14 02:36:23 +02:00
|
|
|
$mapId = (int) $this->request->query('mapId');
|
|
|
|
|
2020-06-19 18:52:07 +02:00
|
|
|
$map = $this->mapRepository->getById($mapId);
|
|
|
|
|
2020-06-14 02:36:23 +02:00
|
|
|
\Container::$dbConnection->startTransaction();
|
|
|
|
|
2020-06-20 00:03:49 +02:00
|
|
|
$this->deletePlaces($map);
|
2020-06-14 02:36:23 +02:00
|
|
|
|
2020-06-19 18:52:07 +02:00
|
|
|
$this->pdm->deleteFromDb($map);
|
2020-06-14 02:36:23 +02:00
|
|
|
|
|
|
|
\Container::$dbConnection->commit();
|
|
|
|
|
2020-07-05 00:58:03 +02:00
|
|
|
return new JsonContent(['success' => true]);
|
2020-06-14 02:36:23 +02:00
|
|
|
}
|
|
|
|
|
2021-05-06 20:09:05 +02:00
|
|
|
private function deletePlace(Place $place): void
|
|
|
|
{
|
|
|
|
foreach ($this->userPlayedPlaceRepository->getAllByPlace($place) as $userPlayedPlace) {
|
|
|
|
$this->pdm->deleteFromDb($userPlayedPlace);
|
|
|
|
}
|
|
|
|
|
2021-05-19 16:33:18 +02:00
|
|
|
foreach ($this->challengeRepository->getAllByPlace($place) as $challenge) {
|
|
|
|
$this->deleteChallenge($challenge);
|
|
|
|
}
|
|
|
|
|
2021-05-06 20:09:05 +02:00
|
|
|
$this->pdm->deleteFromDb($place);
|
|
|
|
}
|
|
|
|
|
2020-06-20 00:03:49 +02:00
|
|
|
private function deletePlaces(Map $map): void
|
2020-06-14 02:36:23 +02:00
|
|
|
{
|
2020-07-05 15:17:28 +02:00
|
|
|
foreach ($this->placeRepository->getAllForMap($map) as $place) {
|
2021-05-06 20:09:05 +02:00
|
|
|
$this->deletePlace($place);
|
2020-06-14 02:36:23 +02:00
|
|
|
}
|
|
|
|
}
|
2020-06-05 19:38:30 +02:00
|
|
|
|
2021-05-19 16:33:18 +02:00
|
|
|
private function deleteChallenge(Challenge $challenge): void
|
|
|
|
{
|
|
|
|
foreach ($this->userInChallengeRepository->getAllByChallenge($challenge) as $userInChallenge) {
|
|
|
|
$this->pdm->deleteFromDb($userInChallenge);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($this->guessRepository->getAllInChallenge($challenge, [PlaceInChallenge::class]) as $guess) {
|
|
|
|
$this->pdm->deleteFromDb($guess);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($this->placeInChallengeRepository->getAllByChallenge($challenge) as $placeInChallenge) {
|
|
|
|
$this->pdm->deleteFromDb($placeInChallenge);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->pdm->deleteFromDb($challenge);
|
|
|
|
}
|
|
|
|
|
2020-06-20 00:03:49 +02:00
|
|
|
private function calculateMapBounds(Map $map): Bounds
|
2020-06-05 22:22:02 +02:00
|
|
|
{
|
|
|
|
$bounds = new Bounds();
|
2020-07-05 15:17:28 +02:00
|
|
|
|
|
|
|
foreach ($this->placeRepository->getAllForMap($map) as $place) {
|
|
|
|
$bounds->extend($place->getPosition());
|
2020-06-05 22:22:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $bounds;
|
|
|
|
}
|
|
|
|
|
2020-06-20 00:03:49 +02:00
|
|
|
private function &getPlaces(Map $map): array
|
2020-06-01 21:13:02 +02:00
|
|
|
{
|
2020-06-02 01:16:59 +02:00
|
|
|
$places = [];
|
|
|
|
|
2020-07-05 15:17:28 +02:00
|
|
|
foreach ($this->placeRepository->getAllForMap($map) as $place) {
|
|
|
|
$noPano = $place->getPanoIdCachedTimestampDate() !== null && $place->getPanoIdCached() === null;
|
|
|
|
|
|
|
|
$placeId = $place->getId();
|
2020-06-02 01:16:59 +02:00
|
|
|
|
2020-07-05 15:17:28 +02:00
|
|
|
$places[$placeId] = [
|
|
|
|
'id' => $placeId,
|
|
|
|
'lat' => $place->getLat(),
|
|
|
|
'lng' => $place->getLng(),
|
2020-06-05 00:21:36 +02:00
|
|
|
'panoId' => null,
|
2020-07-05 15:17:28 +02:00
|
|
|
'pov' => $place->getPov()->toArray(),
|
2020-06-05 00:21:36 +02:00
|
|
|
'noPano' => $noPano
|
|
|
|
];
|
2020-06-02 01:16:59 +02:00
|
|
|
}
|
2020-06-01 21:13:02 +02:00
|
|
|
|
|
|
|
return $places;
|
|
|
|
}
|
|
|
|
}
|