request = $request; $this->pdm = new PersistentDataManager(); $this->mapRepository = new MapRepository(); $this->placeRepository = new PlaceRepository(); $this->userPlayedPlaceRepository = new UserPlayedPlaceRepository(); $this->challengeRepository = new ChallengeRepository(); $this->guessRepository = new GuessRepository(); $this->placeInChallengeRepository = new PlaceInChallengeRepository(); $this->userInChallengeRepository = new UserInChallengeRepository(); } public function authorize(): bool { $user = $this->request->user(); return $user !== null && $user->hasPermission(IUser::PERMISSION_ADMIN); } public function getMapEditor(): IContent { $mapId = (int) $this->request->query('mapId'); if ($mapId) { $map = $this->mapRepository->getById($mapId); $places = $this->getPlaces($map); } else { $map = new Map(); $map->setName(self::$unnamedMapName); $places = []; } return new HtmlContent('admin/map_editor', [ 'mapId' => $mapId, 'mapName' => $map->getName(), 'mapDescription' => str_replace('
', "\n", $map->getDescription()), 'mapUnlisted' => $map->getUnlisted(), 'bounds' => $map->getBounds()->toArray(), 'places' => &$places ]); } public function getPlace(): IContent { $placeId = (int) $this->request->query('placeId'); $place = $this->placeRepository->getById($placeId); return new JsonContent(['panoId' => $place->getFreshPanoId()]); } public function saveMap(): IContent { $mapId = (int) $this->request->query('mapId'); \Container::$dbConnection->startTransaction(); if ($mapId) { $map = $this->mapRepository->getById($mapId); } else { $map = new Map(); $map->setName(self::$unnamedMapName); $this->pdm->saveToDb($map); } if (isset($_POST['added'])) { $addedIds = []; foreach ($_POST['added'] as $placeRaw) { $placeRaw = json_decode($placeRaw, true); $place = new Place(); $place->setMap($map); $place->setLat((float) $placeRaw['lat']); $place->setLng((float) $placeRaw['lng']); $place->setPov(new Pov( (float) $placeRaw['pov']['heading'], (float) $placeRaw['pov']['pitch'], (float) $placeRaw['pov']['zoom'] )); if ($placeRaw['panoId'] === -1) { $place->setPanoIdCachedTimestampDate(new DateTime('-1 day')); } $this->pdm->saveToDb($place); $addedIds[] = ['tempId' => $placeRaw['id'], 'id' => $place->getId()]; } } else { $addedIds = []; } if (isset($_POST['edited'])) { foreach ($_POST['edited'] as $placeRaw) { $placeRaw = json_decode($placeRaw, true); $place = $this->placeRepository->getById((int) $placeRaw['id']); $place->setLat((float) $placeRaw['lat']); $place->setLng((float) $placeRaw['lng']); $place->setPov(new Pov( (float) $placeRaw['pov']['heading'], (float) $placeRaw['pov']['pitch'], (float) $placeRaw['pov']['zoom'] )); $place->setPanoIdCachedTimestampDate(new DateTime('-1 day')); $this->pdm->saveToDb($place); } } if (isset($_POST['deleted'])) { foreach ($_POST['deleted'] as $placeRaw) { $placeRaw = json_decode($placeRaw, true); $place = $this->placeRepository->getById((int) $placeRaw['id']); $this->deletePlace($place); } } $mapBounds = $this->calculateMapBounds($map); $map->setBounds($mapBounds); $map->setArea($mapBounds->calculateApproximateArea()); if (isset($_POST['name'])) { $map->setName($_POST['name'] ? $_POST['name'] : self::$unnamedMapName); } if (isset($_POST['description'])) { $map->setDescription(str_replace(["\n", "\r\n"], '
', $_POST['description'])); } if (isset($_POST['unlisted'])) { $map->setUnlisted((bool)$_POST['unlisted']); } $this->pdm->saveToDb($map); \Container::$dbConnection->commit(); return new JsonContent(['mapId' => $map->getId(), 'added' => $addedIds]); } public function deleteMap(): IContent { $mapId = (int) $this->request->query('mapId'); $map = $this->mapRepository->getById($mapId); \Container::$dbConnection->startTransaction(); $this->deletePlaces($map); $this->pdm->deleteFromDb($map); \Container::$dbConnection->commit(); return new JsonContent(['success' => true]); } private function deletePlace(Place $place): void { foreach ($this->userPlayedPlaceRepository->getAllByPlace($place) as $userPlayedPlace) { $this->pdm->deleteFromDb($userPlayedPlace); } foreach ($this->challengeRepository->getAllByPlace($place) as $challenge) { $this->deleteChallenge($challenge); } $this->pdm->deleteFromDb($place); } private function deletePlaces(Map $map): void { foreach ($this->placeRepository->getAllForMap($map) as $place) { $this->deletePlace($place); } } 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); } private function calculateMapBounds(Map $map): Bounds { $bounds = new Bounds(); foreach ($this->placeRepository->getAllForMap($map) as $place) { $bounds->extend($place->getPosition()); } return $bounds; } private function &getPlaces(Map $map): array { $places = []; foreach ($this->placeRepository->getAllForMap($map) as $place) { $noPano = $place->getPanoIdCachedTimestampDate() !== null && $place->getPanoIdCached() === null; $placeId = $place->getId(); $places[$placeId] = [ 'id' => $placeId, 'lat' => $place->getLat(), 'lng' => $place->getLng(), 'panoId' => null, 'pov' => $place->getPov()->toArray(), 'noPano' => $noPano ]; } return $places; } }