Simple API and database schema for storing and retrieving OpenStreetMap POI data
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

143 lines
4.1 KiB

<?php
require_once __DIR__ . "/required.php";
function getgeojson($data) {
global $SETTINGS;
$geojson = [
"status" => "OK"
];
// If the data is an array, make a FeatureCollection
// If there's no results, make an empty FeatureCollection
if (count($data) == 0 || is_array($data[0])) {
$geojson["type"] = "FeatureCollection";
$geojson["results"] = count($data);
$geojson["max_results"] = $SETTINGS["max_results"];
$geojson["features"] = [];
foreach ($data as $item) {
$geojson["features"][] = [
"type" => "Feature",
"geometry" => [
"type" => "Point",
"coordinates" => [
$item["longitude"] * 1.0,
$item["latitude"] * 1.0
]
],
"properties" => [
"osmid" => $item["osmid"] * 1,
"name" => $item["name"],
"typeid" => $item["typeid"] * 1,
"type" => $item["type"],
"eletype" => $item["eletype"]
]
];
}
} else {
$geojson["type"] = "Feature";
$geojson["geometry"] = [
"type" => "Point",
"coordinates" => [
$data["longitude"] * 1.0,
$data["latitude"] * 1.0
]
];
$geojson["properties"] = [
"osmid" => $data["osmid"] * 1,
"name" => $data["name"],
"typeid" => $data["typeid"] * 1,
"type" => $data["type"],
"eletype" => $data["eletype"]
];
}
return $geojson;
}
$where = [];
$validations = [
"osmid" => "/[0-9]+/",
"typeid" => "/[1-9]+/",
"type" => "/[A-Z]+_[A-Z]+/",
"latitude" => "/[0-9]{0,3}\.[0-9]{2,10}/",
"longitude" => "/[0-9]{0,3}\.[0-9]{2,10}/",
"radius_km" => "/[0-9]+/",
"radius_mi" => "/[0-9]+/"
];
foreach ($validations as $name => $regex) {
if (!empty($_GET[$name])) {
if (is_array($_GET[$name])) {
foreach ($_GET[$name] as $t) {
if (!preg_match($regex, $t)) {
exit("[]");
}
}
} else {
if (!preg_match($regex, $_GET[$name])) {
exit("[]");
}
}
if (preg_match("/(osmid|typeid|type)/", $name)) {
$where[$name] = $_GET[$name];
}
}
}
// Calculate bounding box
use AnthonyMartin\GeoLocation\GeoLocation as GeoLocation;
if (!empty($_GET["latitude"]) && !empty($_GET["longitude"])) {
$userlocation = GeoLocation::fromDegrees($_GET["latitude"], $_GET["longitude"]);
$radius = $SETTINGS["default_radius"];
if (!empty($_GET["radius_km"])) {
$radius = $_GET["radius_km"] * 1.0;
} else if (!empty($_GET["radius_mi"])) {
$radius = $_GET["radius_mi"] / 0.62137;
}
$searchbounds = $userlocation->boundingCoordinates($radius, "kilometers");
$where["latitude[<>]"] = [$searchbounds[0]->getLatitudeInDegrees(), $searchbounds[1]->getLatitudeInDegrees()];
$where["longitude[<>]"] = [$searchbounds[0]->getLongitudeInDegrees(), $searchbounds[1]->getLongitudeInDegrees()];
}
// Remove database ambiguity
foreach ($where as $key => $value) {
if ($key == "typeid") {
$where["poi.typeid"] = $value;
unset($where["typeid"]);
}
}
if (count($where) > 1) {
$where = ["AND" => $where];
}
$where["LIMIT"] = $SETTINGS["max_results"];
ob_flush();
$database->debug()->select("poi", ["[>]types" => "typeid"], ["osmid", "poi.typeid", "type", "latitude", "longitude", "eletype", "name"], $where);
$query = ob_get_contents();
ob_clean();
$results = $database->query($query)->fetchAll();
// If we're looking for a specific location by OSM ID
if (!empty($where["osmid"])) {
$geojson = getgeojson($results[0]);
} else {
$geojson = getgeojson($results);
}
if ($SETTINGS["debug"]) {
$geojson["query"] = $query;
}
if (empty($_GET["pretty"])) {
exit(json_encode($geojson));
}
exit(json_encode($geojson, JSON_PRETTY_PRINT));