mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-15 19:07:58 +00:00
CONST_BasePath is split into separate configuration variables for binaries, libraries and data. These variables as well as the installation path are now set in the executable directly and no longer configurable via project settings. This is the first step towards an installable software. The executables should know per installation where to find their necessary data to execute. Project configuration needs to be restricted to settings that really concern the specific Nominatim installation.
251 lines
10 KiB
PHP
251 lines
10 KiB
PHP
<?php
|
|
|
|
require_once(CONST_LibDir.'/init-website.php');
|
|
require_once(CONST_LibDir.'/log.php');
|
|
require_once(CONST_LibDir.'/output.php');
|
|
require_once(CONST_LibDir.'/AddressDetails.php');
|
|
ini_set('memory_limit', '200M');
|
|
|
|
$oParams = new Nominatim\ParameterParser();
|
|
|
|
$sOutputFormat = $oParams->getSet('format', array('json'), 'json');
|
|
set_exception_handler_by_format($sOutputFormat);
|
|
|
|
$aLangPrefOrder = $oParams->getPreferredLanguages();
|
|
|
|
$sPlaceId = $oParams->getString('place_id');
|
|
$sOsmType = $oParams->getSet('osmtype', array('N', 'W', 'R'));
|
|
$iOsmId = $oParams->getInt('osmid', -1);
|
|
$sClass = $oParams->getString('class');
|
|
|
|
$bIncludeKeywords = $oParams->getBool('keywords', false);
|
|
$bIncludeAddressDetails = $oParams->getBool('addressdetails', false);
|
|
$bIncludeLinkedPlaces = $oParams->getBool('linkedplaces', true);
|
|
$bIncludeHierarchy = $oParams->getBool('hierarchy', false);
|
|
$bGroupHierarchy = $oParams->getBool('group_hierarchy', false);
|
|
$bIncludePolygonAsGeoJSON = $oParams->getBool('polygon_geojson', false);
|
|
|
|
$oDB = new Nominatim\DB();
|
|
$oDB->connect();
|
|
|
|
$sLanguagePrefArraySQL = $oDB->getArraySQL($oDB->getDBQuotedList($aLangPrefOrder));
|
|
|
|
if ($sOsmType && $iOsmId > 0) {
|
|
$sSQL = 'SELECT place_id FROM placex WHERE osm_type = :type AND osm_id = :id';
|
|
$aSQLParams = array(':type' => $sOsmType, ':id' => $iOsmId);
|
|
// osm_type and osm_id are not unique enough
|
|
if ($sClass) {
|
|
$sSQL .= ' AND class= :class';
|
|
$aSQLParams[':class'] = $sClass;
|
|
}
|
|
$sSQL .= ' ORDER BY class ASC';
|
|
$sPlaceId = $oDB->getOne($sSQL, $aSQLParams);
|
|
|
|
|
|
// Nothing? Maybe it's an interpolation.
|
|
// XXX Simply returns the first parent street it finds. It should
|
|
// get a house number and get the right interpolation.
|
|
if (!$sPlaceId && $sOsmType == 'W' && (!$sClass || $sClass == 'place')) {
|
|
$sSQL = 'SELECT place_id FROM location_property_osmline'
|
|
.' WHERE osm_id = :id LIMIT 1';
|
|
$sPlaceId = $oDB->getOne($sSQL, array(':id' => $iOsmId));
|
|
}
|
|
|
|
// Be nice about our error messages for broken geometry
|
|
|
|
if (!$sPlaceId) {
|
|
$sSQL = 'SELECT ';
|
|
$sSQL .= ' osm_type, ';
|
|
$sSQL .= ' osm_id, ';
|
|
$sSQL .= ' errormessage, ';
|
|
$sSQL .= ' class, ';
|
|
$sSQL .= ' type, ';
|
|
$sSQL .= " get_name_by_language(name,$sLanguagePrefArraySQL) AS localname,";
|
|
$sSQL .= ' ST_AsText(prevgeometry) AS prevgeom, ';
|
|
$sSQL .= ' ST_AsText(newgeometry) AS newgeom';
|
|
$sSQL .= ' FROM import_polygon_error ';
|
|
$sSQL .= ' WHERE osm_type = :type';
|
|
$sSQL .= ' AND osm_id = :id';
|
|
$sSQL .= ' ORDER BY updated DESC';
|
|
$sSQL .= ' LIMIT 1';
|
|
$aPointDetails = $oDB->getRow($sSQL, array(':type' => $sOsmType, ':id' => $iOsmId));
|
|
if ($aPointDetails) {
|
|
if (preg_match('/\[(-?\d+\.\d+) (-?\d+\.\d+)\]/', $aPointDetails['errormessage'], $aMatches)) {
|
|
$aPointDetails['error_x'] = $aMatches[1];
|
|
$aPointDetails['error_y'] = $aMatches[2];
|
|
} else {
|
|
$aPointDetails['error_x'] = 0;
|
|
$aPointDetails['error_y'] = 0;
|
|
}
|
|
include(CONST_LibDir.'/template/details-error-'.$sOutputFormat.'.php');
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if ($sPlaceId === false) userError('Please select a place id');
|
|
|
|
$iPlaceID = (int)$sPlaceId;
|
|
|
|
if (CONST_Use_US_Tiger_Data) {
|
|
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_tiger WHERE place_id = '.$iPlaceID);
|
|
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
|
|
}
|
|
|
|
// interpolated house numbers
|
|
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_osmline WHERE place_id = '.$iPlaceID);
|
|
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
|
|
|
|
// artificial postcodes
|
|
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_postcode WHERE place_id = '.$iPlaceID);
|
|
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
|
|
|
|
if (CONST_Use_Aux_Location_data) {
|
|
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_aux WHERE place_id = '.$iPlaceID);
|
|
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
|
|
}
|
|
|
|
$hLog = logStart($oDB, 'details', $_SERVER['QUERY_STRING'], $aLangPrefOrder);
|
|
|
|
// Get the details for this point
|
|
$sSQL = 'SELECT place_id, osm_type, osm_id, class, type, name, admin_level,';
|
|
$sSQL .= ' housenumber, postcode, country_code,';
|
|
$sSQL .= ' importance, wikipedia,';
|
|
$sSQL .= ' ROUND(EXTRACT(epoch FROM indexed_date)) AS indexed_epoch,';
|
|
$sSQL .= ' parent_place_id, ';
|
|
$sSQL .= ' rank_address, ';
|
|
$sSQL .= ' rank_search, ';
|
|
$sSQL .= " get_name_by_language(name,$sLanguagePrefArraySQL) AS localname, ";
|
|
$sSQL .= " ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') AS isarea, ";
|
|
$sSQL .= ' ST_y(centroid) AS lat, ';
|
|
$sSQL .= ' ST_x(centroid) AS lon, ';
|
|
$sSQL .= ' CASE ';
|
|
$sSQL .= ' WHEN importance = 0 OR importance IS NULL ';
|
|
$sSQL .= ' THEN 0.75-(rank_search::float/40) ';
|
|
$sSQL .= ' ELSE importance ';
|
|
$sSQL .= ' END as calculated_importance, ';
|
|
if ($bIncludePolygonAsGeoJSON) {
|
|
$sSQL .= ' ST_AsGeoJSON(CASE ';
|
|
$sSQL .= ' WHEN ST_NPoints(geometry) > 5000 ';
|
|
$sSQL .= ' THEN ST_SimplifyPreserveTopology(geometry, 0.0001) ';
|
|
$sSQL .= ' ELSE geometry ';
|
|
$sSQL .= ' END) as asgeojson';
|
|
} else {
|
|
$sSQL .= ' ST_AsGeoJSON(centroid) as asgeojson';
|
|
}
|
|
$sSQL .= ' FROM placex ';
|
|
$sSQL .= " WHERE place_id = $iPlaceID";
|
|
|
|
$aPointDetails = $oDB->getRow($sSQL, null, 'Could not get details of place object.');
|
|
|
|
if (!$aPointDetails) {
|
|
userError('Unknown place id.');
|
|
}
|
|
|
|
$aPointDetails['localname'] = $aPointDetails['localname']?$aPointDetails['localname']:$aPointDetails['housenumber'];
|
|
$aPointDetails['rank_search_label'] = getSearchRankLabel($aPointDetails['rank_search']); // only used in HTML format
|
|
|
|
// Get all alternative names (languages, etc)
|
|
$sSQL = 'SELECT (each(name)).key,(each(name)).value FROM placex ';
|
|
$sSQL .= "WHERE place_id = $iPlaceID ORDER BY (each(name)).key";
|
|
$aPointDetails['aNames'] = $oDB->getAssoc($sSQL);
|
|
|
|
// Address tags
|
|
$sSQL = 'SELECT (each(address)).key as key,(each(address)).value FROM placex ';
|
|
$sSQL .= "WHERE place_id = $iPlaceID ORDER BY key";
|
|
$aPointDetails['aAddressTags'] = $oDB->getAssoc($sSQL);
|
|
|
|
// Extra tags
|
|
$sSQL = 'SELECT (each(extratags)).key,(each(extratags)).value FROM placex ';
|
|
$sSQL .= "WHERE place_id = $iPlaceID ORDER BY (each(extratags)).key";
|
|
$aPointDetails['aExtraTags'] = $oDB->getAssoc($sSQL);
|
|
|
|
// Address
|
|
$aAddressLines = false;
|
|
if ($bIncludeAddressDetails) {
|
|
$oDetails = new Nominatim\AddressDetails($oDB, $iPlaceID, -1, $sLanguagePrefArraySQL);
|
|
$aAddressLines = $oDetails->getAddressDetails(true);
|
|
}
|
|
|
|
// Linked places
|
|
$aLinkedLines = false;
|
|
if ($bIncludeLinkedPlaces) {
|
|
$sSQL = 'SELECT placex.place_id, osm_type, osm_id, class, type, housenumber,';
|
|
$sSQL .= ' admin_level, rank_address, ';
|
|
$sSQL .= " ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') AS isarea,";
|
|
$sSQL .= " ST_DistanceSpheroid(geometry, placegeometry, 'SPHEROID[\"WGS 84\",6378137,298.257223563, AUTHORITY[\"EPSG\",\"7030\"]]') AS distance, ";
|
|
$sSQL .= " get_name_by_language(name,$sLanguagePrefArraySQL) AS localname, ";
|
|
$sSQL .= ' length(name::text) AS namelength ';
|
|
$sSQL .= ' FROM ';
|
|
$sSQL .= ' placex, ';
|
|
$sSQL .= ' ( ';
|
|
$sSQL .= ' SELECT centroid AS placegeometry ';
|
|
$sSQL .= ' FROM placex ';
|
|
$sSQL .= " WHERE place_id = $iPlaceID ";
|
|
$sSQL .= ' ) AS x';
|
|
$sSQL .= " WHERE linked_place_id = $iPlaceID";
|
|
$sSQL .= ' ORDER BY ';
|
|
$sSQL .= ' rank_address ASC, ';
|
|
$sSQL .= ' rank_search ASC, ';
|
|
$sSQL .= " get_name_by_language(name, $sLanguagePrefArraySQL), ";
|
|
$sSQL .= ' housenumber';
|
|
$aLinkedLines = $oDB->getAll($sSQL);
|
|
}
|
|
|
|
// All places this is an imediate parent of
|
|
$aHierarchyLines = false;
|
|
if ($bIncludeHierarchy) {
|
|
$sSQL = 'SELECT obj.place_id, osm_type, osm_id, class, type, housenumber,';
|
|
$sSQL .= " admin_level, rank_address, ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') AS isarea,";
|
|
$sSQL .= " ST_DistanceSpheroid(geometry, placegeometry, 'SPHEROID[\"WGS 84\",6378137,298.257223563, AUTHORITY[\"EPSG\",\"7030\"]]') AS distance, ";
|
|
$sSQL .= " get_name_by_language(name,$sLanguagePrefArraySQL) AS localname, ";
|
|
$sSQL .= ' length(name::text) AS namelength ';
|
|
$sSQL .= ' FROM ';
|
|
$sSQL .= ' ( ';
|
|
$sSQL .= ' SELECT placex.place_id, osm_type, osm_id, class, type, housenumber, admin_level, rank_address, rank_search, geometry, name ';
|
|
$sSQL .= ' FROM placex ';
|
|
$sSQL .= " WHERE parent_place_id = $iPlaceID ";
|
|
$sSQL .= ' ORDER BY ';
|
|
$sSQL .= ' rank_address ASC, ';
|
|
$sSQL .= ' rank_search ASC ';
|
|
$sSQL .= ' LIMIT 500 ';
|
|
$sSQL .= ' ) AS obj,';
|
|
$sSQL .= ' ( ';
|
|
$sSQL .= ' SELECT centroid AS placegeometry ';
|
|
$sSQL .= ' FROM placex ';
|
|
$sSQL .= " WHERE place_id = $iPlaceID ";
|
|
$sSQL .= ' ) AS x';
|
|
$sSQL .= ' ORDER BY ';
|
|
$sSQL .= ' rank_address ASC, ';
|
|
$sSQL .= ' rank_search ASC, ';
|
|
$sSQL .= ' localname, ';
|
|
$sSQL .= ' housenumber';
|
|
$aHierarchyLines = $oDB->getAll($sSQL);
|
|
}
|
|
|
|
$aPlaceSearchNameKeywords = false;
|
|
$aPlaceSearchAddressKeywords = false;
|
|
if ($bIncludeKeywords) {
|
|
$sSQL = "SELECT * FROM search_name WHERE place_id = $iPlaceID";
|
|
$aPlaceSearchName = $oDB->getRow($sSQL);
|
|
|
|
if (!empty($aPlaceSearchName)) {
|
|
$sWordIds = substr($aPlaceSearchName['name_vector'], 1, -1);
|
|
if (!empty($sWordIds)) {
|
|
$sSQL = 'SELECT * FROM word WHERE word_id in ('.$sWordIds.')';
|
|
$aPlaceSearchNameKeywords = $oDB->getAll($sSQL);
|
|
}
|
|
|
|
$sWordIds = substr($aPlaceSearchName['nameaddress_vector'], 1, -1);
|
|
if (!empty($sWordIds)) {
|
|
$sSQL = 'SELECT * FROM word WHERE word_id in ('.$sWordIds.')';
|
|
$aPlaceSearchAddressKeywords = $oDB->getAll($sSQL);
|
|
}
|
|
}
|
|
}
|
|
|
|
logEnd($oDB, $hLog, 1);
|
|
|
|
include(CONST_LibDir.'/template/details-'.$sOutputFormat.'.php');
|