234 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			234 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php namespace MapGuesser\Controller;
 | 
						|
 | 
						|
use DateTime;
 | 
						|
use MapGuesser\Interfaces\Authentication\IUser;
 | 
						|
use MapGuesser\Interfaces\Authorization\ISecured;
 | 
						|
use MapGuesser\Interfaces\Request\IRequest;
 | 
						|
use MapGuesser\Interfaces\Response\IContent;
 | 
						|
use MapGuesser\PersistentData\Model\Map;
 | 
						|
use MapGuesser\PersistentData\Model\Place;
 | 
						|
use MapGuesser\PersistentData\PersistentDataManager;
 | 
						|
use MapGuesser\Repository\MapRepository;
 | 
						|
use MapGuesser\Repository\PlaceRepository;
 | 
						|
use MapGuesser\Repository\UserPlayedPlaceRepository;
 | 
						|
use MapGuesser\Response\HtmlContent;
 | 
						|
use MapGuesser\Response\JsonContent;
 | 
						|
use MapGuesser\Util\Geo\Bounds;
 | 
						|
use MapGuesser\Util\Panorama\Pov;
 | 
						|
 | 
						|
class MapAdminController implements ISecured
 | 
						|
{
 | 
						|
    private static string $unnamedMapName = '[unnamed map]';
 | 
						|
 | 
						|
    private IRequest $request;
 | 
						|
 | 
						|
    private PersistentDataManager $pdm;
 | 
						|
 | 
						|
    private MapRepository $mapRepository;
 | 
						|
 | 
						|
    private PlaceRepository $placeRepository;
 | 
						|
 | 
						|
    private UserPlayedPlaceRepository $userPlayedPlaceRepository;
 | 
						|
 | 
						|
    public function __construct(IRequest $request)
 | 
						|
    {
 | 
						|
        $this->request = $request;
 | 
						|
        $this->pdm = new PersistentDataManager();
 | 
						|
        $this->mapRepository = new MapRepository();
 | 
						|
        $this->placeRepository = new PlaceRepository();
 | 
						|
        $this->userPlayedPlaceRepository = new UserPlayedPlaceRepository();
 | 
						|
    }
 | 
						|
 | 
						|
    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('<br>', "\n", $map->getDescription()),
 | 
						|
            '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"], '<br>', $_POST['description']));
 | 
						|
        }
 | 
						|
 | 
						|
        $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);
 | 
						|
        }
 | 
						|
 | 
						|
        $this->pdm->deleteFromDb($place);
 | 
						|
    }
 | 
						|
 | 
						|
    private function deletePlaces(Map $map): void
 | 
						|
    {
 | 
						|
        foreach ($this->placeRepository->getAllForMap($map) as $place) {
 | 
						|
            $this->deletePlace($place);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    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;
 | 
						|
    }
 | 
						|
}
 |