Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6f8735da8 | ||
|
|
6a9f7eddc1 | ||
|
|
af52ac3787 | ||
|
|
0481274335 | ||
|
|
618f2a4d48 | ||
|
|
e817a34a3a | ||
|
|
4dde24b70a | ||
|
|
2d91f94f0c | ||
|
|
dd2905286b | ||
|
|
12d24bfddf | ||
|
|
338537c774 |
No files matched your search
@@ -0,0 +1,6 @@
|
||||
ALTER TABLE
|
||||
`places`
|
||||
ADD
|
||||
`pano_id_cached` varchar(255) NULL DEFAULT NULL,
|
||||
ADD
|
||||
`pano_id_cached_timestamp` timestamp NULL DEFAULT NULL;
|
||||
@@ -135,7 +135,7 @@
|
||||
Core.resetGame();
|
||||
};
|
||||
|
||||
xhr.open('GET', '/game/' + mapId + '/position.json', true);
|
||||
xhr.open('GET', '/game/' + mapId + '/json', true);
|
||||
xhr.send();
|
||||
},
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
panorama: null,
|
||||
selectedMarker: null,
|
||||
|
||||
getPlace: function (placeId) {
|
||||
getPlace: function (placeId, marker) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = 'json';
|
||||
xhr.onload = function () {
|
||||
@@ -12,6 +12,9 @@
|
||||
|
||||
if (!this.response.panoId) {
|
||||
document.getElementById('noPano').style.visibility = 'visible';
|
||||
|
||||
marker.noPano = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,11 +44,7 @@
|
||||
MapEditor.resetSelected();
|
||||
MapEditor.selectedMarker = marker;
|
||||
|
||||
marker.setIcon(L.icon({
|
||||
iconUrl: '/static/img/markers/marker-blue.svg',
|
||||
iconSize: [24, 32],
|
||||
iconAnchor: [12, 32]
|
||||
}));
|
||||
marker.setIcon(IconCollection.iconBlue);
|
||||
marker.setZIndexOffset(2000);
|
||||
|
||||
MapEditor.map.invalidateSize(true);
|
||||
@@ -53,7 +52,7 @@
|
||||
|
||||
MapEditor.panorama.setVisible(false);
|
||||
|
||||
MapEditor.getPlace(marker.placeId);
|
||||
MapEditor.getPlace(marker.placeId, marker);
|
||||
},
|
||||
|
||||
resetSelected: function () {
|
||||
@@ -61,15 +60,29 @@
|
||||
return;
|
||||
}
|
||||
|
||||
MapEditor.selectedMarker.setIcon(L.icon({
|
||||
iconUrl: '/static/img/markers/marker-green.svg',
|
||||
iconSize: [24, 32],
|
||||
iconAnchor: [12, 32]
|
||||
}));
|
||||
MapEditor.selectedMarker.setIcon(MapEditor.selectedMarker.noPano ? IconCollection.iconRed : IconCollection.iconGreen);
|
||||
MapEditor.selectedMarker.setZIndexOffset(1000);
|
||||
}
|
||||
};
|
||||
|
||||
var IconCollection = {
|
||||
iconGreen: L.icon({
|
||||
iconUrl: '/static/img/markers/marker-green.svg',
|
||||
iconSize: [24, 32],
|
||||
iconAnchor: [12, 32]
|
||||
}),
|
||||
iconRed: L.icon({
|
||||
iconUrl: '/static/img/markers/marker-red.svg',
|
||||
iconSize: [24, 32],
|
||||
iconAnchor: [12, 32]
|
||||
}),
|
||||
iconBlue: L.icon({
|
||||
iconUrl: '/static/img/markers/marker-blue.svg',
|
||||
iconSize: [24, 32],
|
||||
iconAnchor: [12, 32]
|
||||
}),
|
||||
};
|
||||
|
||||
var Util = {
|
||||
getHighResData: function () {
|
||||
if (window.devicePixelRatio >= 4) {
|
||||
@@ -102,11 +115,7 @@
|
||||
|
||||
for (var i = 0; i < places.length; ++i) {
|
||||
var marker = L.marker({ lat: places[i].lat, lng: places[i].lng }, {
|
||||
icon: L.icon({
|
||||
iconUrl: '/static/img/markers/marker-green.svg',
|
||||
iconSize: [24, 32],
|
||||
iconAnchor: [12, 32]
|
||||
}),
|
||||
icon: places[i].noPano ? IconCollection.iconRed : IconCollection.iconGreen,
|
||||
zIndexOffset: 1000
|
||||
})
|
||||
.addTo(MapEditor.map)
|
||||
@@ -119,6 +128,7 @@
|
||||
});
|
||||
|
||||
marker.placeId = places[i].id;
|
||||
marker.noPano = places[i].noPano;
|
||||
}
|
||||
|
||||
MapEditor.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
|
||||
|
||||
Executable
+152
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
# Usage: ./deploy-to-multiple-worktrees.py REPO_PATH WORKTREE_DEVELOPMENT_PATH WORKTREE_PRODUCTION_PATH
|
||||
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
WORKTREE_REGEX = r"^worktree (.*)\nHEAD ([a-f0-9]*)\n(?:branch refs\/heads\/(.*)|detached)$"
|
||||
|
||||
if len(sys.argv) < 4:
|
||||
print("Usage: ./deploy-to-multiple-worktrees.py REPO_PATH WORKTREE_DEVELOPMENT_PATH WORKTREE_PRODUCTION_PATH")
|
||||
exit(1)
|
||||
|
||||
REPO = os.path.abspath(sys.argv[1])
|
||||
WORKTREE_DEVELOPMENT = os.path.abspath(sys.argv[2])
|
||||
WORKTREE_PRODUCTION = os.path.abspath(sys.argv[3])
|
||||
|
||||
class Worktree:
|
||||
def __init__(self, path, branch, revision, version):
|
||||
self.path = path
|
||||
self.branch = branch
|
||||
self.revision = revision
|
||||
self.version = version
|
||||
self.newRevision = None
|
||||
self.newVersion = None
|
||||
|
||||
def getDataForWorktrees():
|
||||
ret = subprocess.check_output(["git", "worktree", "list", "--porcelain"], cwd=REPO).decode().strip()
|
||||
blocks = ret.split("\n\n")
|
||||
|
||||
worktrees = []
|
||||
|
||||
for block in blocks:
|
||||
matches = re.search(WORKTREE_REGEX, block)
|
||||
|
||||
if matches:
|
||||
path = matches.group(1)
|
||||
revision = matches.group(2)
|
||||
branch = matches.group(3)
|
||||
version = getVersion(revision)
|
||||
|
||||
worktrees.append(Worktree(path, branch, revision, version))
|
||||
|
||||
return worktrees
|
||||
|
||||
def findWorktree(path):
|
||||
for worktree in worktrees:
|
||||
if worktree.path == path:
|
||||
return worktree
|
||||
|
||||
return None
|
||||
|
||||
def getVersion(branch):
|
||||
return subprocess.check_output(["git", "describe", "--tags", "--always", "--match", "Release_*", branch], cwd=REPO).decode().strip()
|
||||
|
||||
def getRevisionForRef(ref):
|
||||
return subprocess.check_output(["git", "rev-list", "-1", ref], cwd=REPO).decode().strip()
|
||||
|
||||
def getLatestReleaseTag():
|
||||
return subprocess.check_output(["git", "for-each-ref", "refs/tags/Release*", "--count=1", "--sort=-creatordate", "--format=%(refname:short)"], cwd=REPO).decode().strip()
|
||||
|
||||
def updateRepoFromRemote():
|
||||
subprocess.call(["git", "fetch", "origin", "--prune"], cwd=REPO)
|
||||
|
||||
def checkoutWorktree(worktreePath, ref):
|
||||
subprocess.call(["git", "checkout", "-f", ref], cwd=worktreePath)
|
||||
|
||||
def cleanWorktree(worktreePath):
|
||||
subprocess.call(["git", "clean", "-f", "-d"], cwd=worktreePath)
|
||||
|
||||
def updateAppInWorktree(worktreePath):
|
||||
subprocess.call([worktreePath + "/scripts/update.sh"], cwd=worktreePath)
|
||||
|
||||
def updateAppVersionInWorktree(worktreePath):
|
||||
pass
|
||||
#subprocess.call([worktreePath + "/scripts/update-version.sh"], cwd=worktreePath)
|
||||
|
||||
worktrees = getDataForWorktrees()
|
||||
|
||||
updateRepoFromRemote()
|
||||
|
||||
print("Repo is updated from origin")
|
||||
|
||||
print("----------------------------------------------")
|
||||
print("----------------------------------------------")
|
||||
|
||||
developmentWorktree = findWorktree(WORKTREE_DEVELOPMENT)
|
||||
|
||||
developmentWorktree.newRevision = getRevisionForRef(developmentWorktree.branch)
|
||||
developmentWorktree.newVersion = getVersion(developmentWorktree.revision)
|
||||
|
||||
print("DEVELOPMENT (" + developmentWorktree.path + ") is on branch " + developmentWorktree.branch)
|
||||
print(developmentWorktree.revision + " = " + developmentWorktree.branch + " (" + developmentWorktree.version + ")")
|
||||
print(developmentWorktree.newRevision + " = origin/" + developmentWorktree.branch + " (" + developmentWorktree.newVersion + ")")
|
||||
|
||||
if developmentWorktree.revision != developmentWorktree.newRevision:
|
||||
print("-> DEVELOPMENT (" + developmentWorktree.path + ") will be UPDATED")
|
||||
print("----------------------------------------------")
|
||||
|
||||
checkoutWorktree(developmentWorktree.path, developmentWorktree.branch)
|
||||
cleanWorktree(developmentWorktree.path)
|
||||
|
||||
print(developmentWorktree.path + " is checked out to " + developmentWorktree.branch + " and cleaned")
|
||||
|
||||
updateAppInWorktree(developmentWorktree.path)
|
||||
updateAppVersionInWorktree(developmentWorktree.path)
|
||||
|
||||
print("MapGuesser is updated in " + developmentWorktree.path)
|
||||
elif developmentWorktree.version != developmentWorktree.newVersion:
|
||||
print("-> DEVELOPMENT " + developmentWorktree.path + "'s version info will be UPDATED")
|
||||
|
||||
checkoutWorktree(developmentWorktree.path, developmentWorktree.branch)
|
||||
|
||||
print(developmentWorktree.path + " is checked out to " + developmentWorktree.branch)
|
||||
|
||||
updateAppVersionInWorktree(developmentWorktree.path)
|
||||
|
||||
print("MapGuesser version is updated in " + developmentWorktree.path)
|
||||
else:
|
||||
print("-> DEVELOPMENT (" + developmentWorktree.path + ") WON'T be updated")
|
||||
|
||||
print("----------------------------------------------")
|
||||
print("----------------------------------------------")
|
||||
|
||||
productionWorktree = findWorktree(WORKTREE_PRODUCTION)
|
||||
|
||||
productionWorktree.newVersion = getLatestReleaseTag()
|
||||
productionWorktree.newRevision = getRevisionForRef(productionWorktree.newVersion)
|
||||
|
||||
print("PRODUCTION (" + productionWorktree.path + ")")
|
||||
print(productionWorktree.revision + " = " + productionWorktree.version)
|
||||
print(productionWorktree.newRevision + " = " + productionWorktree.newVersion)
|
||||
|
||||
if productionWorktree.revision != productionWorktree.newRevision:
|
||||
print("-> PRODUCTION (" + productionWorktree.path + ") will be UPDATED")
|
||||
|
||||
checkoutWorktree(productionWorktree.path, productionWorktree.newRevision)
|
||||
cleanWorktree(productionWorktree.path)
|
||||
|
||||
print(productionWorktree.path + " is checked out to " + productionWorktree.newRevision + " and cleaned")
|
||||
|
||||
updateAppInWorktree(productionWorktree.path)
|
||||
updateAppVersionInWorktree(productionWorktree.path)
|
||||
|
||||
print("MapGuesser is updated in " + productionWorktree.path)
|
||||
else:
|
||||
print("-> PRODUCTION (" + productionWorktree.path + ") WON'T be updated")
|
||||
|
||||
print("----------------------------------------------")
|
||||
print("----------------------------------------------")
|
||||
@@ -1,22 +1,31 @@
|
||||
<?php namespace MapGuesser\Controller;
|
||||
|
||||
use MapGuesser\Database\Query\Select;
|
||||
use MapGuesser\Http\Request;
|
||||
use MapGuesser\Interfaces\Database\IResultSet;
|
||||
use MapGuesser\Interfaces\Response\IContent;
|
||||
use MapGuesser\Repository\PlaceRepository;
|
||||
use MapGuesser\Response\HtmlContent;
|
||||
use MapGuesser\Response\JsonContent;
|
||||
use MapGuesser\Util\Geo\Bounds;
|
||||
|
||||
class MapAdminController
|
||||
{
|
||||
public function getMaps(): IContent {
|
||||
private PlaceRepository $placeRepository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->placeRepository = new PlaceRepository();
|
||||
}
|
||||
|
||||
public function getMaps(): IContent
|
||||
{
|
||||
//TODO
|
||||
|
||||
return new HtmlContent('admin/maps');
|
||||
}
|
||||
|
||||
public function getMapEditor(array $parameters): IContent {
|
||||
public function getMapEditor(array $parameters): IContent
|
||||
{
|
||||
$mapId = (int) $parameters['mapId'];
|
||||
|
||||
$bounds = $this->getMapBounds($mapId);
|
||||
@@ -27,33 +36,13 @@ class MapAdminController
|
||||
return new HtmlContent('admin/map_editor', $data);
|
||||
}
|
||||
|
||||
public function getPlace(array $parameters) {
|
||||
public function getPlace(array $parameters)
|
||||
{
|
||||
$placeId = (int) $parameters['placeId'];
|
||||
|
||||
$select = new Select(\Container::$dbConnection, 'places');
|
||||
$select->columns(['id', 'lat', 'lng']);
|
||||
$select->whereId($placeId);
|
||||
$placeData = $this->placeRepository->getById($placeId);
|
||||
|
||||
$place = $select->execute()->fetch(IResultSet::FETCH_ASSOC);
|
||||
|
||||
$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' => 'outdoor'
|
||||
]);
|
||||
|
||||
$response = $request->send();
|
||||
|
||||
$panoData = json_decode($response->getBody(), true);
|
||||
|
||||
if ($panoData['status'] !== 'OK') {
|
||||
$panoId = null;
|
||||
} else {
|
||||
$panoId = $panoData['pano_id'];
|
||||
}
|
||||
|
||||
$data = ['panoId' => $panoId];
|
||||
$data = ['panoId' => $placeData['panoId']];
|
||||
return new JsonContent($data);
|
||||
}
|
||||
|
||||
@@ -73,12 +62,19 @@ class MapAdminController
|
||||
private function &getPlaces(int $mapId): array
|
||||
{
|
||||
$select = new Select(\Container::$dbConnection, 'places');
|
||||
$select->columns(['id', 'lat', 'lng']);
|
||||
$select->columns(['id', 'lat', 'lng', 'pano_id_cached', 'pano_id_cached_timestamp']);
|
||||
$select->where('map_id', '=', $mapId);
|
||||
$select->orderBy('lng');
|
||||
//$select->limit(100);
|
||||
|
||||
$places = $select->execute()->fetchAll(IResultSet::FETCH_ASSOC);
|
||||
$result = $select->execute();
|
||||
|
||||
$places = [];
|
||||
|
||||
while ($place = $result->fetch(IResultSet::FETCH_ASSOC)) {
|
||||
$noPano = $place['pano_id_cached_timestamp'] && $place['pano_id_cached'] === null;
|
||||
|
||||
$places[] = ['id' => $place['id'], 'lat' => $place['lat'], 'lng' => $place['lng'], 'noPano' => $noPano];
|
||||
}
|
||||
|
||||
return $places;
|
||||
}
|
||||
|
||||
@@ -1,28 +1,33 @@
|
||||
<?php namespace MapGuesser\Controller;
|
||||
|
||||
use MapGuesser\Database\Query\Select;
|
||||
use MapGuesser\Http\Request;
|
||||
use MapGuesser\Interfaces\Database\IResultSet;
|
||||
use MapGuesser\Util\Geo\Position;
|
||||
use MapGuesser\Response\JsonContent;
|
||||
use MapGuesser\Interfaces\Response\IContent;
|
||||
use MapGuesser\Repository\PlaceRepository;
|
||||
|
||||
class PositionController
|
||||
{
|
||||
const NUMBER_OF_ROUNDS = 5;
|
||||
const MAX_SCORE = 1000;
|
||||
|
||||
private PlaceRepository $placeRepository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->placeRepository = new PlaceRepository();
|
||||
}
|
||||
|
||||
public function getPosition(array $parameters): IContent
|
||||
{
|
||||
$mapId = (int) $parameters['mapId'];
|
||||
|
||||
if (!isset($_SESSION['state']) || $_SESSION['state']['mapId'] !== $mapId) {
|
||||
$data = ['error' => 'No valid session found!'];
|
||||
$data = ['error' => 'no_session_found'];
|
||||
return new JsonContent($data);
|
||||
}
|
||||
|
||||
if (count($_SESSION['state']['rounds']) === 0) {
|
||||
$newPosition = $this->getNewPosition($mapId);
|
||||
$newPosition = $this->placeRepository->getForMapWithValidPano($mapId);
|
||||
$_SESSION['state']['rounds'][] = $newPosition;
|
||||
|
||||
$data = ['panoId' => $newPosition['panoId']];
|
||||
@@ -55,7 +60,7 @@ class PositionController
|
||||
$mapId = (int) $parameters['mapId'];
|
||||
|
||||
if (!isset($_SESSION['state']) || $_SESSION['state']['mapId'] !== $mapId) {
|
||||
$data = ['error' => 'No valid session found!'];
|
||||
$data = ['error' => 'no_session_found'];
|
||||
return new JsonContent($data);
|
||||
}
|
||||
|
||||
@@ -79,7 +84,7 @@ class PositionController
|
||||
$exclude = array_merge($exclude, $round['placesWithoutPano'], [$round['placeId']]);
|
||||
}
|
||||
|
||||
$newPosition = $this->getNewPosition($mapId, $exclude);
|
||||
$newPosition = $this->placeRepository->getForMapWithValidPano($mapId, $exclude);
|
||||
$_SESSION['state']['rounds'][] = $newPosition;
|
||||
|
||||
$panoId = $newPosition['panoId'];
|
||||
@@ -100,66 +105,6 @@ class PositionController
|
||||
return new JsonContent($data);
|
||||
}
|
||||
|
||||
private function getNewPosition(int $mapId, array $exclude = []): array
|
||||
{
|
||||
$placesWithoutPano = [];
|
||||
|
||||
do {
|
||||
$place = $this->selectNewPlace($mapId, $exclude);
|
||||
$position = new Position($place['lat'], $place['lng']);
|
||||
$panoId = $this->getPanorama($position);
|
||||
|
||||
if ($panoId === null) {
|
||||
$placesWithoutPano[] = $place['id'];
|
||||
}
|
||||
} while ($panoId === null);
|
||||
|
||||
return [
|
||||
'placesWithoutPano' => $placesWithoutPano,
|
||||
'placeId' => $place['id'],
|
||||
'position' => $position,
|
||||
'panoId' => $panoId
|
||||
];
|
||||
}
|
||||
|
||||
private function selectNewPlace(int $mapId, array $exclude): array
|
||||
{
|
||||
$select = new Select(\Container::$dbConnection, 'places');
|
||||
$select->columns(['id', 'lat', 'lng']);
|
||||
$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 getPanorama(Position $position): ?string
|
||||
{
|
||||
$request = new Request('https://maps.googleapis.com/maps/api/streetview/metadata', Request::HTTP_GET);
|
||||
$request->setQuery([
|
||||
'key' => $_ENV['GOOGLE_MAPS_SERVER_API_KEY'],
|
||||
'location' => $position->getLat() . ',' . $position->getLng(),
|
||||
'source' => 'outdoor'
|
||||
]);
|
||||
|
||||
$response = $request->send();
|
||||
|
||||
$panoData = json_decode($response->getBody(), true);
|
||||
|
||||
if ($panoData['status'] !== 'OK') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $panoData['pano_id'];
|
||||
}
|
||||
|
||||
private function calculateDistance(Position $realPosition, Position $guessPosition): float
|
||||
{
|
||||
return $realPosition->calculateDistanceTo($guessPosition);
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
<?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
|
||||
];
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user