From 6b5a24152e26da1ebd1fc3e08bd49c7f06b7e283 Mon Sep 17 00:00:00 2001 From: Skylar Ittner Date: Sat, 27 Apr 2019 18:58:44 -0600 Subject: [PATCH] Create POI API and importer script --- .gitignore | 4 + composer.json | 16 ++++ composer.lock | 122 +++++++++++++++++++++++++ database.mwb | Bin 0 -> 10155 bytes import_csv.php | 90 +++++++++++++++++++ index.php | 138 +++++++++++++++++++++++++++++ nbproject/project.properties | 7 ++ nbproject/project.xml | 9 ++ poi-types.csv | 167 +++++++++++++++++++++++++++++++++++ required.php | 80 +++++++++++++++++ settings.template.php | 36 ++++++++ 11 files changed, 669 insertions(+) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 database.mwb create mode 100644 import_csv.php create mode 100644 index.php create mode 100644 nbproject/project.properties create mode 100644 nbproject/project.xml create mode 100644 poi-types.csv create mode 100644 required.php create mode 100644 settings.template.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..87dc92a --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/settings.php +/database.mwb.bak +/vendor/ +/nbproject/private \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d13ac31 --- /dev/null +++ b/composer.json @@ -0,0 +1,16 @@ +{ + "name": "netsyms/points-of-interest-api", + "description": "Simple PHP API for getting OpenStreetMap points of interest as GeoJSON", + "type": "project", + "require": { + "catfan/medoo": "^1.6", + "anthonymartin/geo-location": "^1.0" + }, + "license": "MIT", + "authors": [ + { + "name": "Skylar Ittner", + "email": "admin@netsyms.com" + } + ] +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..da8bd82 --- /dev/null +++ b/composer.lock @@ -0,0 +1,122 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "7717ebd7c56c3d078f88c2c9aab56f61", + "packages": [ + { + "name": "anthonymartin/geo-location", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/anthonymartin/GeoLocation.php.git", + "reference": "50bf026f069296dfae11aa195d987854b2e75855" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/anthonymartin/GeoLocation.php/zipball/50bf026f069296dfae11aa195d987854b2e75855", + "reference": "50bf026f069296dfae11aa195d987854b2e75855", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "class", + "autoload": { + "psr-0": { + "AnthonyMartin": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "CC 3.0" + ], + "authors": [ + { + "name": "Anthony Martin", + "email": "anthony@replaycreative.com", + "homepage": "http://replaycreative.com", + "role": "Developer" + } + ], + "description": "Retrieve bounding coordinates, distances, longitude and latitude with GeoLocation.class.php", + "homepage": "https://github.com/anthonymartin/GeoLocation.php", + "keywords": [ + "bounding coordinates", + "distances", + "geocoding", + "geolocation" + ], + "time": "2016-09-17T18:05:14+00:00" + }, + { + "name": "catfan/medoo", + "version": "v1.6.1", + "source": { + "type": "git", + "url": "https://github.com/catfan/Medoo.git", + "reference": "53a02b300d673f716cb06bf0e24fd774ec53939f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/catfan/Medoo/zipball/53a02b300d673f716cb06bf0e24fd774ec53939f", + "reference": "53a02b300d673f716cb06bf0e24fd774ec53939f", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "php": ">=5.4" + }, + "suggest": { + "ext-pdo_dblib": "For MSSQL or Sybase database on Linux/UNIX platform", + "ext-pdo_mysql": "For MySQL or MariaDB database", + "ext-pdo_oci": "For Oracle database", + "ext-pdo_oci8": "For Oracle version 8 database", + "ext-pdo_pqsql": "For PostgreSQL database", + "ext-pdo_sqlite": "For SQLite database", + "ext-pdo_sqlsrv": "For MSSQL database" + }, + "type": "framework", + "autoload": { + "psr-4": { + "Medoo\\": "/src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Angel Lai", + "email": "angel@catfan.me" + } + ], + "description": "The lightest PHP database framework to accelerate development", + "homepage": "https://medoo.in", + "keywords": [ + "database", + "lightweight", + "mariadb", + "mssql", + "mysql", + "oracle", + "php framework", + "postgresql", + "sql", + "sqlite" + ], + "time": "2018-12-08T20:24:23+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/database.mwb b/database.mwb new file mode 100644 index 0000000000000000000000000000000000000000..247d5abc45cfadfdb96ed5f5f748f6e164f354c5 GIT binary patch literal 10155 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 literal 0 HcmV?d00001 diff --git a/import_csv.php b/import_csv.php new file mode 100644 index 0000000..49437af --- /dev/null +++ b/import_csv.php @@ -0,0 +1,90 @@ + $SETTINGS['database']['type'], + 'database_name' => $SETTINGS['database']['name'], + 'server' => $SETTINGS['database']['server'], + 'username' => $SETTINGS['database']['user'], + 'password' => $SETTINGS['database']['password'], + 'charset' => $SETTINGS['database']['charset'] + ]); +} catch (Exception $ex) { + die("Database error: $ex\n"); +} + + + +if (!file_exists($argv[1])) { + die("Please supply the filename of the CSV file to import.\n"); +} + +$current = 0; + +$handle = fopen($argv[1], "r"); +if ($handle) { + $batchinsert = []; + while (($line = fgets($handle)) !== false) { + $fields = explode("|", trim($line), 5); + + $batchinsert[] = [ + "osmid" => substr($fields[1], 1), + "typeid" => $fields[0], + "latitude" => $fields[2], + "longitude" => $fields[3], + "eletype" => $fields[1][0], + "name" => $fields[4] + ]; + + $current++; + if ($current % 100 == 0) { + $database->insert("poi", $batchinsert); + $error = $database->error(); + if ($error[1] != 0 && $error[0] != "23000") { + die("\nDatabase error $error[0]: $error[2]\n"); + } + $batchinsert = []; + echo " $current "; + } + } + + fclose($handle); + + echo "\nDone: $current records processed.\n"; +} else { + die("Error: could not open the file.\n"); +} \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..970b8d0 --- /dev/null +++ b/index.php @@ -0,0 +1,138 @@ + "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(); + +$geojson = getgeojson($results); + +if ($SETTINGS["debug"]) { + $geojson["query"] = $query; +} + +if (empty($_GET["pretty"])) { + exit(json_encode($geojson)); +} +exit(json_encode($geojson, JSON_PRETTY_PRINT)); diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 0000000..67f7bd3 --- /dev/null +++ b/nbproject/project.properties @@ -0,0 +1,7 @@ +include.path=${php.global.include.path} +php.version=PHP_72 +source.encoding=UTF-8 +src.dir=. +tags.asp=false +tags.short=false +web.root=. diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..93b156d --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,9 @@ + + + org.netbeans.modules.php.project + + + PointsOfInterestAPI + + + diff --git a/poi-types.csv b/poi-types.csv new file mode 100644 index 0000000..ea3399a --- /dev/null +++ b/poi-types.csv @@ -0,0 +1,167 @@ +1,ACCOMMO_ALPINEHUT +2,ACCOMMO_CAMPING +3,ACCOMMO_CARAVAN +4,ACCOMMO_CHALET +5,ACCOMMO_HOSTEL +6,ACCOMMO_HOTEL +7,ACCOMMO_MOTEL +8,AMENITY_COURT +9,AMENITY_FIRESTATION +11,AMENITY_LIBRARY +12,AMENITY_PLAYGROUND +13,AMENITY_POLICE +14,AMENITY_POSTOFFICE +15,AMENITY_PRISON +16,AMENITY_PUBLICBUILDING +17,AMENITY_TOWNHALL +18,BARRIER_BLOCKS +19,EDUCATION_COLLEGE +20,EDUCATION_NURSERY +21,EDUCATION_SCHOOL +22,EDUCATION_UNIVERSITY +23,FOOD_BAR +24,FOOD_BIERGARTEN +25,FOOD_CAFE +26,FOOD_FASTFOOD +27,FOOD_ICECREAM +28,FOOD_PUB +29,FOOD_RESTAURANT +30,HEALTH_DENTIST +31,HEALTH_DOCTORS +32,HEALTH_HOSPITALEMERGENCY +33,HEALTH_HOSPITAL +34,HEALTH_PHARMACY +35,HEALTH_VETERINARY +36,LANDUSE_ALLOTMENTS +37,LANDUSE_CONIFEROUSDECIDUOUS +38,LANDUSE_CONIFEROUS +39,LANDUSE_DECIDUOUS +40,LANDUSE_GRASS +41,LANDUSE_HILLS +42,LANDUSE_MILITARY +43,LANDUSE_QUARY +44,LANDUSE_SCRUB +45,LANDUSE_SWAMP +46,MONEY_BANK +47,MONEY_EXCHANGE +48,POW_BAHAI +49,POW_BUDDHIST +50,POW_CHRISTIAN +51,POW_HINDU +52,POW_ISLAMIC +53,POW_JAIN +54,POW_JEWISH +55,POW_SHINTO +56,POW_SIKH +58,POW_UNKOWN +59,POI_CAVE +60,POI_CRANE +61,POI_EMBASSY +62,POI_BUNKER +63,POI_MINE +64,POI_PEAK1 +65,POI_PEAK +66,POI_CITY +67,POI_HAMLET +68,POI_SUBURB +69,POI_TOWN +70,POI_VILLAGE +71,POI_TOWERCOMMUNICATION +72,POI_TOWERLOOKOUT +73,SHOP_ALCOHOL +74,SHOP_BAKERY +75,SHOP_BICYCLE +76,SHOP_BOOK +77,SHOP_BUTCHER +78,SHOP_CARREPAIR +79,SHOP_CAR +80,SHOP_CLOTHES +81,SHOP_COMPUTER +82,SHOP_CONFECTIONERY +83,SHOP_CONVENIENCE +84,SHOP_COPYSHOP +85,SHOP_DEPARTMENTSTORE +86,SHOP_DIY +87,SHOP_FISH +88,SHOP_FLORIST +89,SHOP_GARDENCENTRE +90,SHOP_GIFT +91,SHOP_GREENGROCER +92,SHOP_HAIRDRESSER +93,SHOP_HEARINGAIDS +94,SHOP_HIFI +95,SHOP_JEWELRY +96,SHOP_KIOSK +97,SHOP_LAUNDRETTE +98,SHOP_MARKETPLACE +99,SHOP_PHONE +100,SHOP_MOTORCYCLE +101,SHOP_MUSIC +102,SHOP_NEWSPAPER +103,SHOP_PET +104,SHOP_SHOES +105,SHOP_SUPERMARKET +106,SHOP_TOBACCO +107,SHOP_TOYS +108,SHOP_VENDINGMASCHINE +109,SHOP_VIDEORENTAL +110,SPORT_ARCHERY +111,SPORT_BASEBALL +112,SPORT_BASKETBALL +113,SPORT_BOWLING +114,SPORT_CANOE +115,SPORT_CRICKET +116,SPORT_DIVING +117,SPORT_FOOTBALL +118,SPORT_GOLF +119,SPORT_GYM +120,SPORT_GYMNASIUM +121,SPORT_CLIMBING +122,SPORT_HORSE +123,SPORT_ICESKATING +124,SPORT_LEISURECENTER +125,SPORT_MINIATURGOLF +126,SPORT_MOTORRACING +127,SPORT_SHOOTING +128,SPORT_SKATING +129,SPORT_SKIINGDOWNHILL +130,SPORT_SNOOKER +131,SPORT_SOCCER +132,SPORT_STADIUM +133,SPORT_SWIMMING +134,SPORT_TENNIS +135,SPORT_WATERSKI +136,SPORT_SURFING +137,TOURIST_ARCHAELOGICAL +138,TOURIST_ART +139,TOURIST_ATTRACTION +140,TOURIST_BATTLEFIELD +141,TOURIST_BEACH +142,TOURIST_CASTLE +143,TOURIST_CASTLE2 +144,TOURIST_CINEMA +145,TOURIST_FOUNTAIN +146,TOURIST_INFORMATION +147,TOURIST_MEMORIAL +148,TOURIST_MONUMENT +149,TOURIST_MUSEUM +150,TOURIST_NIGHTCLUB +151,TOURIST_RUINS +152,TOURIST_THEATRE +153,TOURIST_THEMEPARK +156,TOURIST_WINDMILL +157,TOURIST_WRECK +158,TOURIST_ZOO +159,TRANSPORT_TERMINAL +160,TRANSPORT_AIRPORT +161,TRANSPORT_BUSSTOP +162,TRANSPORT_FUEL +163,TRANSPORT_LIGHTHOUSE +164,TRANSPORT_MARINA +165,TRANSPORT_RENTALCAR +166,TRANSPORT_SUBWAY +167,TRANSPORT_STATION +168,TRANSPORT_TRAMSTOP +169,WATER_DAM +170,WATER_TOWER +171,WATER_WEIR diff --git a/required.php b/required.php new file mode 100644 index 0000000..650544c --- /dev/null +++ b/required.php @@ -0,0 +1,80 @@ + "ERROR", "message" => $msg])); +} + +// Database settings +// Also inits database and stuff +use Medoo\Medoo; + +$database; +try { + $database = new Medoo([ + 'database_type' => $SETTINGS['database']['type'], + 'database_name' => $SETTINGS['database']['name'], + 'server' => $SETTINGS['database']['server'], + 'username' => $SETTINGS['database']['user'], + 'password' => $SETTINGS['database']['password'], + 'charset' => $SETTINGS['database']['charset'] + ]); +} catch (Exception $ex) { + sendError("Database error. Try again later. $ex"); +} + + +if (!$SETTINGS['debug']) { + error_reporting(0); +} else { + error_reporting(E_ALL); + ini_set('display_errors', 'On'); +} + + +$VARS; +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $VARS = $_POST; + define("GET", false); +} else { + $VARS = $_GET; + define("GET", true); +} + + +/** + * Check if the previous database action had a problem. + * @param array $specials int=>string array with special response messages for SQL errors + */ +function checkDBError($specials = []) { + global $database; + $errors = $database->error(); + if (!is_null($errors[1])) { + foreach ($specials as $code => $text) { + if ($errors[1] == $code) { + sendError($text); + } + } + sendError("A database error occurred: " . $errors[2]); + } +} diff --git a/settings.template.php b/settings.template.php new file mode 100644 index 0000000..40074fb --- /dev/null +++ b/settings.template.php @@ -0,0 +1,36 @@ + false, + // Database connection settings + // See http://medoo.in/api/new for info + "database" => [ + "type" => "mysql", + "name" => "poidb", + "server" => "localhost", + "user" => "root", + "password" => "", + "charset" => "utf8" + ], + // Maximum number of results to return. + "max_results" => 1000, + // Default radius when searching by location, in kilometers + "default_radius" => 10, + // Name of the app. + "site_title" => "OSM Points of Interest", + // For supported values, see http://php.net/manual/en/timezones.php + "timezone" => "America/Denver" +];