--- /dev/null
+# Place details
+
+Lookup details about a single place by id. The default output is HTML for debugging search logic and results.
+
+**The details page (including JSON output) exists for debugging only and must not be downloaded automatically**, see [Nominatim Usage Policy](https://operations.osmfoundation.org/policies/nominatim/).
+
+
+## Parameters
+
+The details API supports the following two request formats:
+
+```
+ https://nominatim.openstreetmap.org/details?osmtype=[N|W|R]&osmid=<value>
+```
+
+Both parameters are required, the type is one of node(N), way(W) or relation(R).
+
+Or
+
+```
+ https://nominatim.openstreetmap.org/details?placeid=<value>
+```
+
+Placeids are assigned sequentially during Nominatim data import. The id for a place is different between Nominatim installation (servers) and changes when data gets reimported. Therefore it can't be used as permanent id and shouldn't be used in bug reports.
+
+
+Additional optional parameters are explained below.
+
+### Output format
+
+* `format=[html|json]`
+
+See [Place Output Formats](Output.md) for details on each format. (Default: html)
+
+* `json_callback=<string>`
+
+Wrap json output in a callback function (JSONP) i.e. `<string>(<json>)`.
+Only has an effect for JSON output formats.
+
+* `pretty=[0|1]`
+
+For JSON output will add indentation to make it more human-readable. (Default: 0)
+
+
+### Output details
+
+* `addressdetails=[0|1]`
+
+Include a breakdown of the address into elements. (Default for JSON: 0, for HTML: 1)
+
+* `keywords=[0|1]`
+
+Include a list of name keywords and address keywords (word ids). (Default: 0)
+
+* `linkedplaces=[0|1]`
+
+Include details of places higher in the address hierarchy. E.g. for a street this is usually the city, state, postal code, country. (Default: 1)
+
+* `hierarchy=[0|1]`
+
+Include details of places lower in the address hierarchy. E.g. for a city this usually a list of streets, suburbs, rivers. (Default for JSON: 0, for HTML: 1)
+
+* `group_hierarchy=[0|1]`
+
+For JSON output will group the places by type. (Default: 0)
+
+* `polygon_geojson=[0|1]`
+
+Include geometry of result. (Default for JSON: 0, for HTML: 1)
+
+### Language of results
+
+* `accept-language=<browser language string>`
+
+Preferred language order for showing result, overrides the value
+specified in the "Accept-Language" HTTP header.
+Either use a standard RFC2616 accept-language string or a simple
+comma-separated list of language codes.
+
+
+## Examples
+
+##### HTML
+
+[https://nominatim.openstreetmap.org/details.php?osmtype=W&osmid=38210407](https://nominatim.openstreetmap.org/details.php?osmtype=W&osmid=38210407)
+
+##### JSON
+
+[https://nominatim.openstreetmap.org/details.php?osmtype=W&osmid=38210407&format=json](https://nominatim.openstreetmap.org/details.php?osmtype=W&osmid=38210407&format=json)
+
+
+```json
+{
+ "place_id": 85993608,
+ "parent_place_id": 72765313,
+ "osm_type": "W",
+ "osm_id": 38210407,
+ "category": "place",
+ "type": "square",
+ "admin_level": "15",
+ "localname": "Pariser Platz",
+ "names": {
+ "name": "Pariser Platz",
+ "name:be": "Парыжская плошча",
+ "name:de": "Pariser Platz",
+ "name:es": "Plaza de París",
+ "name:he": "פאריזר פלאץ",
+ "name:ko": "파리저 광장",
+ "name:la": "Forum Parisinum",
+ "name:ru": "Парижская площадь",
+ "name:uk": "Паризька площа",
+ "name:zh": "巴黎廣場"
+ },
+ "addresstags": {
+ "postcode": "10117"
+ },
+ "housenumber": null,
+ "calculated_postcode": "10117",
+ "country_code": "de",
+ "indexed_date": "2018-08-18T17:02:45+00:00",
+ "importance": 0.339401620591472,
+ "calculated_importance": 0.339401620591472,
+ "extratags": {
+ "wikidata": "Q156716",
+ "wikipedia": "de:Pariser Platz"
+ },
+ "calculated_wikipedia": "de:Pariser_Platz",
+ "rank_address": 30,
+ "rank_search": 30,
+ "isarea": true,
+ "centroid": {
+ "type": "Point",
+ "coordinates": [
+ 13.3786822618517,
+ 52.5163654
+ ]
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 13.3786822618517,
+ 52.5163654
+ ]
+ }
+}
+```
### Nominatim API
-Nominatim indexes named (or numbered) features with the OSM data set and a subset of other unnamed features (pubs, hotels, churches, etc).
+Nominatim indexes named (or numbered) features within the OpenStreetMap (OSM) dataset and a subset of other unnamed features (pubs, hotels, churches, etc).
Its API has the following endpoints for querying the data:
* __[/search](Search.md)__ - search OSM objects by name or type
* __[/reverse](Reverse.md)__ - search OSM object by their location
- * __[/lookup](Lookup.md)__ - look up address details for OSM objects by thier ID
+ * __[/lookup](Lookup.md)__ - look up address details for OSM objects by their ID
* __/status__ - query the status of the server
* __/deletable__ - list objects that have been deleted in OSM but are held
back in Nominatim in case the deletion was accidental
* __/polygons__ - list of broken polygons detected by Nominatim
- * __/details__ - show internal details for an object (for debugging only)
+ * __[/details](Details.md)__ - show internal details for an object (for debugging only)
* `json_callback=<string>`
-Wrap json output in a callback function (JSONP) i.e. `<string>(<json>)`.
+Wrap json output in a callback function ([JSONP](https://en.wikipedia.org/wiki/JSONP)) i.e. `<string>(<json>)`.
Only has an effect for JSON output formats.
### Output details
* `zoom=[0-18]`
-Level of detail required for the address. This is a number that corresponds
+Level of detail required for the address. Default: 18. This is a number that corresponds
roughly to the zoom level used in map frameworks like Leaflet.js, Openlayers etc.
In terms of address details the zoom levels are as follows:
The search query may also contain
[special phrases](https://wiki.openstreetmap.org/wiki/Nominatim/Special_Phrases)
-which are tranlated into specific OpenStreetMap(OSM) tags (e.g. Pub => amenity=pub).
-Note that this only limits the items to be found. It is not suited to return complete
-lists of OSM objects of a specific type.
-Use [Overpass API](https://overpass-api.de/) for that.
+which are translated into specific OpenStreetMap (OSM) tags (e.g. Pub => `amenity=pub`).
+Note that this only limits the items to be found, it's not suited to return complete
+lists of OSM objects of a specific type. For those use [Overpass API](https://overpass-api.de/).
## Parameters
* `q=<query>`
Free-form query string to search for.
- Free-form queries are processed first left to right and then right to
- left if that fails. So you may search for
+ Free-form queries are processed first left-to-right and then right-to-left if that fails. So you may search for
[pilkington avenue, birmingham](//nominatim.openstreetmap.org/search?q=pilkington+avenue,birmingham) as well as for
[birmingham, pilkington avenue](//nominatim.openstreetmap.org/search?q=birmingham,+pilkington+avenue).
- Commas are optional, but improve performance by reducing the complexity
- of the search.
+ Commas are optional, but improve performance by reducing the complexity of the search.
* `street=<housenumber> <streetname>`
- `city=<city>`
- `county=<county>`
- `state=<state>`
- `country=<country>`
- `postalcode=<postalcode>`
+* `city=<city>`
+* `county=<county>`
+* `state=<state>`
+* `country=<country>`
+* `postalcode=<postalcode>`
- Alternative query string format for structured requests.
+ Alternative query string format split into several parameters for structured requests.
Structured requests are faster but are less robust against alternative
OSM tagging schemas. **Do not combine with** `q=<query>` **parameter**.
* `json_callback=<string>`
-Wrap json output in a callback function (JSONP) i.e. `<string>(<json>)`.
+Wrap json output in a callback function ([JSONP](https://en.wikipedia.org/wiki/JSONP)) i.e. `<string>(<json>)`.
Only has an effect for JSON output formats.
### Output details
* `accept-language=<browser language string>`
Preferred language order for showing search results, overrides the value
-specified in the "Accept-Language" HTTP header.
+specified in the ["Accept-Language" HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language).
Either use a standard RFC2616 accept-language string or a simple
comma-separated list of language codes.
* `limit=<integer>`
-Limit the number of returned results. (Default: 10)
+Limit the number of returned results. (Default: 10, Maximum: 50)
* `viewbox=<x1>,<y1>,<x2>,<y2>`
* `bounded=[0|1]`
When a viewbox is given, restrict the result to items contained with that
-viewbox (see above). When `viewbox` and `bounded` are given, an amenity
+viewbox (see above). When `viewbox` and `bounded=1` are given, an amenity
only search is allowed. In this case, give the special keyword for the
-amenity in squaer brackets, e.g. `[pub]`. (Default: 0)
+amenity in square brackets, e.g. `[pub]`. (Default: 0)
### Polygon output
- 'Search': 'api/Search.md'
- 'Reverse': 'api/Reverse.md'
- 'Address Lookup': 'api/Lookup.md'
+ - 'Details' : 'api/Details.md'
- 'Place Output Formats': 'api/Output.md'
- 'FAQ': 'api/Faq.md'
- 'Administration Guide':
}
} elseif (is_object($mVar) && method_exists($mVar, 'debugInfo')) {
Debug::outputVar($mVar->debugInfo(), $sPreNL);
+ } elseif (is_a($mVar, 'stdClass')) {
+ Debug::outputVar(json_decode(json_encode($mVar), true), $sPreNL);
} else {
Debug::outputSimpleVar($mVar);
}
/**
* Find the closest interpolation with the given search diameter.
*
- * @param string $sPointSQL Reverse geocoding point as SQL
- * @param float $fSearchDiam Search diameter
- * @param integer $iParentPlaceID Id of parent object
+ * @param string $sPointSQL Reverse geocoding point as SQL
+ * @param float $fSearchDiam Search diameter
*
* @return Record of the interpolation or null.
*/
- protected function lookupInterpolation($sPointSQL, $fSearchDiam, $iParentPlaceID = null)
+ protected function lookupInterpolation($sPointSQL, $fSearchDiam)
{
$sSQL = 'SELECT place_id, parent_place_id, 30 as rank_search,';
$sSQL .= ' ST_LineLocatePoint(linegeo,'.$sPointSQL.') as fraction,';
$sSQL .= ' FROM location_property_osmline';
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')';
$sSQL .= ' and indexed_status = 0 and startnumber is not NULL ';
- if (isset($iParentPlaceID)) {
- $sSQL .= ' and parent_place_id = '.$iParentPlaceID;
- }
$sSQL .= ' ORDER BY distance ASC limit 1';
return chksql(
);
}
- protected function polygonFunctions($sPointSQL, $iMaxRank)
+ protected function lookupLargeArea($sPointSQL, $iMaxRank)
{
- // starts the nopolygonFound function if no polygon is found with the lookupPolygon function
$oResult = null;
- $aPlace = $this->lookupPolygon($sPointSQL, $iMaxRank);
- if ($aPlace) {
- $oResult = new Result($aPlace['place_id']);
- // if no polygon which contains the searchpoint is found,
- // the noPolygonFound function searches in the country_osm_grid table for a polygon
- } elseif (!$aPlace && $iMaxRank > 4) {
- $aPlace = $this->noPolygonFound($sPointSQL, $iMaxRank);
+ if ($iMaxRank > 4) {
+ $aPlace = $this->lookupPolygon($sPointSQL, $iMaxRank);
if ($aPlace) {
- $oResult = new Result($aPlace['place_id']);
+ return new Result($aPlace['place_id']);
}
}
- return $oResult;
+
+ // If no polygon which contains the searchpoint is found,
+ // searches in the country_osm_grid table for a polygon.
+ return $this->lookupInCountry($sPointSQL, $iMaxRank);
}
- protected function noPolygonFound($sPointSQL, $iMaxRank)
+ protected function lookupInCountry($sPointSQL, $iMaxRank)
{
// searches for polygon in table country_osm_grid which contains the searchpoint
// and searches for the nearest place node to the searchpoint in this polygon
$sSQL = 'SELECT country_code FROM country_osm_grid';
- $sSQL .= ' WHERE ST_CONTAINS (geometry, '.$sPointSQL.') limit 1';
+ $sSQL .= ' WHERE ST_CONTAINS(geometry, '.$sPointSQL.') LIMIT 1';
- $aPoly = chksql(
- $this->oDB->getRow($sSQL),
- 'Could not determine polygon containing the point.'
+ $sCountryCode = chksql(
+ $this->oDB->getOne($sSQL),
+ 'Could not determine country polygon containing the point.'
);
- if ($aPoly) {
- $sCountryCode = $aPoly['country_code'];
-
- // look for place nodes with the given country code
- $sSQL = 'SELECT place_id FROM';
- $sSQL .= ' (SELECT place_id, rank_search,';
- $sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance';
- $sSQL .= ' FROM placex';
- $sSQL .= ' WHERE osm_type = \'N\'';
- $sSQL .= ' AND country_code = \''.$sCountryCode.'\'';
- $sSQL .= ' AND rank_search between 5 and ' .min(25, $iMaxRank);
- $sSQL .= ' AND class = \'place\' AND type != \'postcode\'';
- $sSQL .= ' AND name IS NOT NULL ';
- $sSQL .= ' and indexed_status = 0 and linked_place_id is null';
- $sSQL .= ' AND ST_DWithin('.$sPointSQL.', geometry, 1.8)) p ';
- $sSQL .= 'WHERE distance <= reverse_place_diameter(rank_search)';
- $sSQL .= ' ORDER BY rank_search DESC, distance ASC';
- $sSQL .= ' LIMIT 1';
+ if ($sCountryCode) {
+ if ($iMaxRank > 4) {
+ // look for place nodes with the given country code
+ $sSQL = 'SELECT place_id FROM';
+ $sSQL .= ' (SELECT place_id, rank_search,';
+ $sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance';
+ $sSQL .= ' FROM placex';
+ $sSQL .= ' WHERE osm_type = \'N\'';
+ $sSQL .= ' AND country_code = \''.$sCountryCode.'\'';
+ $sSQL .= ' AND rank_search between 5 and ' .min(25, $iMaxRank);
+ $sSQL .= ' AND class = \'place\' AND type != \'postcode\'';
+ $sSQL .= ' AND name IS NOT NULL ';
+ $sSQL .= ' and indexed_status = 0 and linked_place_id is null';
+ $sSQL .= ' AND ST_DWithin('.$sPointSQL.', geometry, 1.8)) p ';
+ $sSQL .= 'WHERE distance <= reverse_place_diameter(rank_search)';
+ $sSQL .= ' ORDER BY rank_search DESC, distance ASC';
+ $sSQL .= ' LIMIT 1';
- if (CONST_Debug) var_dump($sSQL);
- $aPlacNode = chksql(
- $this->oDB->getRow($sSQL),
- 'Could not determine place node.'
- );
- if ($aPlacNode) {
- return $aPlacNode;
+ if (CONST_Debug) var_dump($sSQL);
+ $aPlace = chksql(
+ $this->oDB->getRow($sSQL),
+ 'Could not determine place node.'
+ );
+ if ($aPlace) {
+ return new Result($aPlace['place_id']);
+ }
}
// still nothing, then return the country object
$sSQL .= ' WHERE country_code = \''.$sCountryCode.'\'';
$sSQL .= ' AND rank_search = 4 AND rank_address = 4';
$sSQL .= ' AND class in (\'boundary\', \'place\')';
+ $sSQL .= ' AND linked_place_id is null';
$sSQL .= ' ORDER BY distance ASC';
if (CONST_Debug) var_dump($sSQL);
- $aPlacNode = chksql(
+ $aPlace = chksql(
$this->oDB->getRow($sSQL),
'Could not determine place node.'
);
- if ($aPlacNode) {
- return $aPlacNode;
+ if ($aPlace) {
+ return new Result($aPlace['place_id']);
}
}
+
+ return null;
}
+ /**
+ * Search for areas or nodes for areas or nodes between state and suburb level.
+ *
+ * @param string $sPointSQL Search point as SQL string.
+ * @param int $iMaxRank Maximum address rank of the feature.
+ *
+ * @return Record of the found feature or null.
+ *
+ * Searches first for polygon that contains the search point.
+ * If such a polygon is found, place nodes with a higher rank are
+ * searched inside the polygon.
+ */
protected function lookupPolygon($sPointSQL, $iMaxRank)
{
- // searches for polygon where the searchpoint is within
- // if a polygon is found, placenodes with a higher rank are searched inside the polygon
-
// polygon search begins at suburb-level
if ($iMaxRank > 25) $iMaxRank = 25;
// no polygon search over country-level
$fSearchDiam = 0.006;
$oResult = null;
$aPlace = null;
- $fMaxAreaDistance = 1;
- $bIsTigerStreet = false;
// for POI or street level
if ($iMaxRank >= 26) {
'Could not determine closest place.'
);
+ if (CONST_Debug) var_dump($aPlace);
if ($aPlace) {
- $iDistance = $aPlace['distance'];
$iPlaceID = $aPlace['place_id'];
$oResult = new Result($iPlaceID);
+ $iRankAddress = $aPlace['rank_address'];
$iParentPlaceID = $aPlace['parent_place_id'];
+ }
- if ($bDoInterpolation && $iMaxRank >= 30) {
- if ($aPlace['rank_address'] <=27) {
- $iDistance = 0.001;
- }
- $aHouse = $this->lookupInterpolation($sPointSQL, $iDistance);
+ if ($bDoInterpolation && $iMaxRank >= 30) {
+ $fDistance = $fSearchDiam;
+ if ($aPlace) {
+ // We can't reliably go from the closest street to an
+ // interpolation line because the closest interpolation
+ // may have a different street segments as a parent.
+ // Therefore allow an interpolation line to take precendence
+ // even when the street is closer.
+ $fDistance = $iRankAddress < 28 ? 0.001 : $aPlace['distance'];
+ }
- if ($aHouse) {
- $oResult = new Result($aHouse['place_id'], Result::TABLE_OSMLINE);
- $oResult->iHouseNumber = closestHouseNumber($aHouse);
- }
+ $aHouse = $this->lookupInterpolation($sPointSQL, $fDistance);
+
+ if ($aHouse) {
+ $oResult = new Result($aHouse['place_id'], Result::TABLE_OSMLINE);
+ $oResult->iHouseNumber = closestHouseNumber($aHouse);
+ $aPlace = $aHouse;
+ $iRankAddress = 30;
}
+ }
+ if ($aPlace) {
// if street and maxrank > streetlevel
- if (($aPlace['rank_address'] <=27)&& $iMaxRank > 27) {
+ if ($iRankAddress <= 27 && $iMaxRank > 27) {
// find the closest object (up to a certain radius) of which the street is a parent of
- $sSQL = ' select place_id,parent_place_id,rank_address,country_code,';
+ $sSQL = ' select place_id,';
$sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance';
$sSQL .= ' FROM ';
$sSQL .= ' placex';
'Could not determine closest place.'
);
if ($aStreet) {
- $iDistance = $aStreet['distance'];
- $iPlaceID = $aStreet['place_id'];
- $oResult = new Result($iPlaceID);
- $iParentPlaceID = $aStreet['parent_place_id'];
-
- if ($bDoInterpolation && $iMaxRank >= 30) {
- $aHouse = $this->lookupInterpolation($sPointSQL, $iDistance, $iParentPlaceID);
-
- if ($aHouse) {
- $oResult = new Result($aHouse['place_id'], Result::TABLE_OSMLINE);
- $oResult->iHouseNumber = closestHouseNumber($aHouse);
- }
- }
+ if (CONST_Debug) var_dump($aStreet);
+ $oResult = new Result($aStreet['place_id']);
}
}
// In the US we can check TIGER data for nearest housenumber
- if (CONST_Use_US_Tiger_Data && $aPlace['country_code'] == 'us' && $this->iMaxRank >= 28) {
- $fSearchDiam = $aPlace['rank_address'] > 28 ? $aPlace['distance'] : 0.001;
+ if (CONST_Use_US_Tiger_Data
+ && $iRankAddress <= 27
+ && $aPlace['country_code'] == 'us'
+ && $this->iMaxRank >= 28
+ ) {
$sSQL = 'SELECT place_id,parent_place_id,30 as rank_search,';
$sSQL .= 'ST_LineLocatePoint(linegeo,'.$sPointSQL.') as fraction,';
$sSQL .= 'ST_distance('.$sPointSQL.', linegeo) as distance,';
$sSQL .= 'startnumber,endnumber,interpolationtype';
$sSQL .= ' FROM location_property_tiger WHERE parent_place_id = '.$oResult->iId;
- $sSQL .= ' AND ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')';
+ $sSQL .= ' AND ST_DWithin('.$sPointSQL.', linegeo, 0.001)';
$sSQL .= ' ORDER BY distance ASC limit 1';
if (CONST_Debug) var_dump($sSQL);
$aPlaceTiger = chksql(
);
if ($aPlaceTiger) {
if (CONST_Debug) var_dump('found Tiger housenumber', $aPlaceTiger);
- $aPlace = $aPlaceTiger;
- $oResult = new Result($aPlace['place_id'], Result::TABLE_TIGER);
+ $oResult = new Result($aPlaceTiger['place_id'], Result::TABLE_TIGER);
$oResult->iHouseNumber = closestHouseNumber($aPlaceTiger);
}
}
- // if no POI or street is found ...
} else {
- $oResult = $this->PolygonFunctions($sPointSQL, $iMaxRank);
+ // if no POI or street is found ...
+ $oResult = $this->lookupLargeArea($sPointSQL, 25);
}
- // lower than street level ($iMaxRank < 26 )
} else {
- $oResult = $this->PolygonFunctions($sPointSQL, $iMaxRank);
+ // lower than street level ($iMaxRank < 26 )
+ $oResult = $this->lookupLargeArea($sPointSQL, $iMaxRank);
}
return $oResult;
}
$aFDs = array(
0 => array('pipe', 'r'),
1 => STDOUT,
- 2 => STDERR);
+ 2 => STDERR
+ );
$aPipes = null;
$hProc = @proc_open($sCmd, $aFDs, $aPipes, null, $aEnv);
if (!is_resource($hProc)) {
function hash_to_subtable($aAssociatedList)
{
$sHTML = '';
- foreach($aAssociatedList as $sKey => $sValue)
- {
+ foreach ($aAssociatedList as $sKey => $sValue) {
$sHTML = $sHTML.' <div class="line"><span class="name">'.$sValue.'</span> ('.$sKey.')</div>'."\n";
}
return $sHTML;
<tbody>
<?php
-
- foreach($aAddressLines as $aAddressLine)
- {
+ foreach ($aAddressLines as $aAddressLine) {
_one_row($aAddressLine);
}
?>
-
<?php
if ($aLinkedLines)
{
headline('Linked Places');
- foreach($aLinkedLines as $aAddressLine)
- {
+ foreach ($aLinkedLines as $aAddressLine) {
_one_row($aAddressLine);
}
}
-
-
if ($bIncludeKeywords)
{
headline('Name Keywords');
- foreach($aPlaceSearchNameKeywords as $aRow)
- {
- _one_keyword_row($aRow['word_token'], $aRow['word_id']);
+ if ($aPlaceSearchNameKeywords) {
+ foreach ($aPlaceSearchNameKeywords as $aRow) {
+ _one_keyword_row($aRow['word_token'], $aRow['word_id']);
+ }
}
headline('Address Keywords');
- foreach($aPlaceSearchAddressKeywords as $aRow)
- {
- _one_keyword_row($aRow['word_token'], $aRow['word_id']);
+ if ($aPlaceSearchAddressKeywords) {
+ foreach ($aPlaceSearchAddressKeywords as $aRow) {
+ _one_keyword_row($aRow['word_token'], $aRow['word_id']);
+ }
}
}
-
+
if (!empty($aHierarchyLines))
{
headline('Parent Of');
$aGroupedAddressLines = array();
- foreach($aHierarchyLines as $aAddressLine)
- {
+ foreach ($aHierarchyLines as $aAddressLine) {
if ($aAddressLine['type'] == 'yes') $sType = $aAddressLine['class'];
else $sType = $aAddressLine['type'];
$aGroupedAddressLines[$sType] = array();
$aGroupedAddressLines[$sType][] = $aAddressLine;
}
- foreach($aGroupedAddressLines as $sGroupHeading => $aHierarchyLines)
- {
+ foreach ($aGroupedAddressLines as $sGroupHeading => $aHierarchyLines) {
$sGroupHeading = ucwords($sGroupHeading);
headline3($sGroupHeading);
- foreach($aHierarchyLines as $aAddressLine)
- {
+ foreach ($aHierarchyLines as $aAddressLine) {
_one_row($aAddressLine);
}
}
'lon' => $aPointDetails['lon'],
'lat' => $aPointDetails['lat'],
);
- echo 'var nominatim_result = ' . json_encode($aPlace, JSON_PRETTY_PRINT) . ';';
+ echo 'var nominatim_result = ' . json_encode($aPlace, JSON_PRETTY_PRINT) . ';';
?>
$aPlaceDetails['extratags'] = $aPointDetails['aExtraTags'];
$aPlaceDetails['calculated_wikipedia'] = $aPointDetails['wikipedia'];
-$aPlaceDetails['icon'] = CONST_Website_BaseURL.'images/mapicons/'.$aPointDetails['icon'].'.n.32.png';
+if ($aPointDetails['icon']) {
+ $aPlaceDetails['icon'] = CONST_Website_BaseURL.'images/mapicons/'.$aPointDetails['icon'].'.n.32.png';
+}
$aPlaceDetails['rank_address'] = (int) $aPointDetails['rank_address'];
$aPlaceDetails['rank_search'] = (int) $aPointDetails['rank_search'];
| linkedplaces |
| 1 |
Then the result is valid json
+
+ Scenario Outline: HTML Details with keywords
+ When sending html details query for <osmid>
+ | keywords |
+ | 1 |
+ Then the result is valid html
+
+ Examples:
+ | osmid |
+ | W78099902 |
+ | N3121929846 |
+
+
Then results contain
| display_name |
| Tacuarembó, Uruguay |
+
+ Scenario Outline: Zoom levels below 5 result in country
+ When sending jsonv2 reverse coordinates -33.28,-56.29
+ | zoom |
+ | <zoom> |
+ Then results contain
+ | display_name |
+ | Uruguay |
+
+ Examples:
+ | zoom |
+ | 0 |
+ | 1 |
+ | 2 |
+ | 3 |
+ | 4 |
+
+ Scenario: When on a street, the closest interpolation is shown
+ When sending jsonv2 reverse coordinates -33.2309430210215,-54.38126470020989
+ | zoom |
+ | 18 |
+ Then results contain
+ | display_name |
+ | 1429, Andrés Areguati, Treinta y Tres, 33000, Uruguay |
+
+ Scenario: When on a street with zoom 18, the closest housenumber is returned
+ When sending jsonv2 reverse coordinates 53.551826690895226,9.885258475318201
+ | zoom |
+ | 18 |
+ Then result addresses contain
+ | house_number |
+ | 33 |
When sending xml search query "Vaduz"
| countrycodes |
| pl,1,,invalid,undefined,%3Cb%3E,bo,, |
- Then result header contains
+ Then result header contains
| attr | value |
| more_url | .*&countrycodes=pl%2Cbo&.* |
+
+ Scenario Outline: Search with debug prints valid HTML
+ When sending html search query "<query>"
+ | extratags | addressdetails | namedetails | debug |
+ | 1 | 1 | 1 | 1 |
+ Then the result is valid html
+
+ Examples:
+ | query |
+ | 10, Alvierweg, 9490, Vaduz |
+ | Hamburg |
options={'char-encoding' : 'utf8'})
#eq_(len(errors), 0 , "Errors found in HTML document:\n%s" % errors)
+ self.result = []
b = content.find('nominatim_results =')
e = content.find('</script>')
- content = content[b:e]
- b = content.find('[')
- e = content.rfind(']')
-
- self.result = json.JSONDecoder(object_pairs_hook=OrderedDict).decode(content[b:e+1])
+ if b >= 0 and e >= 0:
+ content = content[b:e]
+
+ b = content.find('[')
+ e = content.rfind(']')
+ if b >= 0 and e >= 0:
+ self.result = json.JSONDecoder(object_pairs_hook=OrderedDict)\
+ .decode(content[b:e+1])
def parse_xml(self):
et = ET.fromstring(self.page)