mapguesser/src/Repository/PlaceRepository.php

148 lines
4.4 KiB
PHP
Raw Normal View History

<?php namespace MapGuesser\Repository;
use MapGuesser\Util\Geo\Position;
use MapGuesser\Database\Query\Select;
use MapGuesser\Database\Query\Modify;
use MapGuesser\Http\Request;
use MapGuesser\Interfaces\Database\IResultSet;
use DateTime;
use DateInterval;
class PlaceRepository
{
public function getById(int $placeId)
{
$place = $this->selectFromDbById($placeId);
$panoId = $this->requestPanoId($place);
$position = new Position($place['lat'], $place['lng']);
return [
'position' => $position,
'panoId' => $panoId
];
}
public function getForMapWithValidPano(int $mapId, array $exclude = []): array
{
$placesWithoutPano = [];
do {
$place = $this->selectFromDbForMap($mapId, $exclude);
$panoId = $this->requestPanoId($place);
if ($panoId === null) {
$placesWithoutPano[] = $place['id'];
}
} while ($panoId === null);
$position = new Position($place['lat'], $place['lng']);
return [
'placesWithoutPano' => $placesWithoutPano,
'placeId' => $place['id'],
'position' => $position,
'panoId' => $panoId
];
}
public function addToMap(int $mapId, array $place): int
{
$modify = new Modify(\Container::$dbConnection, 'places');
$modify->set('map_id', $mapId);
$modify->fill($place);
$modify->save();
return $modify->getId();
}
public function modify(int $id, array $place): void
{
$modify = new Modify(\Container::$dbConnection, 'places');
$modify->setId($id);
$modify->set('pano_id_cached', null);
$modify->set('pano_id_cached_timestamp', null);
$modify->fill($place);
$modify->save();
}
public function delete(int $id): void
{
$modify = new Modify(\Container::$dbConnection, 'places');
$modify->setId($id);
$modify->delete();
}
private function selectFromDbById(int $placeId): array
{
$select = new Select(\Container::$dbConnection, 'places');
$select->columns(['id', 'lat', 'lng', 'pano_id_cached', 'pano_id_cached_timestamp']);
$select->whereId($placeId);
$place = $select->execute()->fetch(IResultSet::FETCH_ASSOC);
return $place;
}
private function selectFromDbForMap(int $mapId, array $exclude): array
{
$select = new Select(\Container::$dbConnection, 'places');
$select->columns(['id', 'lat', 'lng', 'pano_id_cached', 'pano_id_cached_timestamp']);
$select->where('id', 'NOT IN', $exclude);
$select->where('map_id', '=', $mapId);
$numberOfPlaces = $select->count(); // TODO: what if 0
$randomOffset = random_int(0, $numberOfPlaces - 1);
$select->orderBy('id');
$select->limit(1, $randomOffset);
$place = $select->execute()->fetch(IResultSet::FETCH_ASSOC);
return $place;
}
private function requestPanoId(array $place, bool $canBeIndoor = false): ?string
{
if (
$place['pano_id_cached_timestamp'] &&
(new DateTime($place['pano_id_cached_timestamp']))->add(new DateInterval('P1D')) > new DateTime()
) {
return $place['pano_id_cached'];
}
$request = new Request('https://maps.googleapis.com/maps/api/streetview/metadata', Request::HTTP_GET);
$request->setQuery([
'key' => $_ENV['GOOGLE_MAPS_SERVER_API_KEY'],
'location' => $place['lat'] . ',' . $place['lng'],
'source' => $canBeIndoor ? 'default' : 'outdoor'
]);
$response = $request->send();
$panoData = json_decode($response->getBody(), true);
$panoId = $panoData['status'] === 'OK' ? $panoData['pano_id'] : null;
// enable indoor panos if no outdoor found
if ($panoId === null && !$canBeIndoor) {
return $this->requestPanoId($place, true);
}
$this->saveCachedPanoId($place['id'], $panoId);
return $panoId;
}
private function saveCachedPanoId(int $placeId, ?string $panoId): void
{
$modify = new Modify(\Container::$dbConnection, 'places');
$modify->setId($placeId);
$modify->set('pano_id_cached', $panoId);
$modify->set('pano_id_cached_timestamp', (new DateTime())->format('Y-m-d H:i:s'));
$modify->save();
}
}