unify address details lookup

Introduces new AddressDetails class which is responsible
for address lookups. Saves always the complete result
and then allows filtering throught the different access
function. Remove special handling in Geocode() and use
there the lookup throught PlaceLookup() as well.
This commit is contained in:
Sarah Hoffmann 2018-07-10 23:38:27 +02:00
parent 320d488627
commit 25baaf530d
18 changed files with 195 additions and 213 deletions

117
lib/AddressDetails.php Normal file
View File

@ -0,0 +1,117 @@
<?php
namespace Nominatim;
require_once(CONST_BasePath.'/lib/ClassTypes.php');
/**
* Detailed list of address parts for a single result
*/
class AddressDetails
{
private $aAddressLines;
public function __construct(&$oDB, $iPlaceID, $sHousenumber, $mLangPref)
{
if (is_array($mLangPref)) {
$mLangPref = 'ARRAY['.join(',', array_map('getDBQuoted', $mLangPref)).']';
}
if (!$sHousenumber) {
$sHousenumber = -1;
}
$sSQL = 'SELECT *,';
$sSQL .= ' get_name_by_language(name,'.$mLangPref.') as localname';
$sSQL .= ' FROM get_addressdata('.$iPlaceID.','.$sHousenumber.')';
$sSQL .= ' ORDER BY rank_address desc,isaddress DESC';
$this->aAddressLines = chksql($oDB->getAll($sSQL));
}
private static function isAddress($aLine)
{
return $aLine['isaddress'] == 't' || $aLine['type'] == 'country_code';
}
public function getAddressDetails($bAll = false)
{
if ($bAll) {
return $this->aAddressLines;
}
return array_filter($this->aAddressLines, 'AddressDetails::isAddress');
}
public function getLocaleAddress()
{
$aParts = array();
$sPrevResult = '';
foreach ($this->aAddressLines as $aLine) {
if ($aLine['isaddress'] == 't' && $sPrevResult != $aLine['localname']) {
$sPrevResult = $aLine['localname'];
$aParts[] = $sPrevResult;
}
}
return join(', ', $aParts);
}
public function getAddressNames()
{
$aAddress = array();
$aFallback = array();
foreach ($this->aAddressLines as $aLine) {
if (!self::isAddress($aLine)) {
continue;
}
$bFallback = false;
$aTypeLabel = ClassTypes\getInfo($aLine);
if ($aTypeLabel === false) {
$aTypeLabel = ClassTypes\getFallbackInfo($aLine);
$bFallback = true;
}
$sName = false;
if (isset($aLine['localname']) && $aLine['localname']) {
$sName = $aLine['localname'];
} elseif (isset($aLine['housenumber']) && $aLine['housenumber']) {
$sName = $aLine['housenumber'];
}
if ($sName) {
$sTypeLabel = strtolower(isset($aTypeLabel['simplelabel']) ? $aTypeLabel['simplelabel'] : $aTypeLabel['label']);
$sTypeLabel = str_replace(' ', '_', $sTypeLabel);
if (!isset($aAddress[$sTypeLabel])
|| isset($aFallback[$sTypeLabel])
|| $aLine['class'] == 'place'
) {
$aAddress[$sTypeLabel] = $sName;
if ($bFallback) {
$aFallback[$sTypeLabel] = $bFallback;
}
}
}
}
return $aAddress;
}
public function getAdminLevels()
{
$aAddress = array();
foreach ($this->aAddressLines as $aLine) {
if (self::isAddress($aLine)
&& isset($aLine['admin_level'])
&& $aLine['admin_level'] < 15
&& !isset($aAddress['level'.$aLine['admin_level']])
) {
$aAddress['level'.$aLine['admin_level']] = $aLine['localname'];
}
}
return $aAddress;
}
}

View File

@ -28,7 +28,7 @@ function getFallbackInfo($aPlace)
$sFallback = 'boundary:administrative:'.((int)($aPlace['rank_address']/2));
if (isset($aClassType[$sFallback])) {
return $aClassType[$sFallback];
}
}
return array('simplelabel' => 'address'.$aPlace['rank_address']);
}

View File

@ -17,8 +17,6 @@ class Geocode
protected $aLangPrefOrder = array();
protected $bIncludeAddressDetails = false;
protected $aExcludePlaceIDs = array();
protected $bReverseInPlan = false;
@ -87,7 +85,6 @@ class Geocode
$aParams['exclude_place_ids'] = implode(',', $this->aExcludePlaceIDs);
}
if ($this->bIncludeAddressDetails) $aParams['addressdetails'] = '1';
if ($this->bBoundedSearch) $aParams['bounded'] = '1';
if ($this->aCountryCodes) {
@ -183,9 +180,6 @@ class Geocode
public function loadParamArray($oParams, $sForceGeometryType = null)
{
$this->bIncludeAddressDetails
= $oParams->getBool('addressdetails', $this->bIncludeAddressDetails);
$this->bBoundedSearch = $oParams->getBool('bounded', $this->bBoundedSearch);
$this->setLimit($oParams->getInt('limit', $this->iFinalLimit));
@ -247,14 +241,8 @@ class Geocode
}
$this->oPlaceLookup->loadParamArray($oParams, $sForceGeometryType);
$this->oPlaceLookup->setIncludeAddressDetails(false);
$this->oPlaceLookup->setIncludePolygonAsPoints($oParams->getBool('polygon'));
if ($this->bIncludeAddressDetails
&& $oParams->getString('format', '') == 'geocodejson'
) {
$this->oPlaceLookup->setAddressAdminLevels(true);
}
$this->oPlaceLookup->setIncludeAddressDetails($oParams->getBool('addressdetails', false));
}
public function setQueryFromParams($oParams)
@ -903,14 +891,6 @@ class Geocode
$aResult['label'] = $aClassInfo['label'];
}
}
// if tag '&addressdetails=1' is set in query
if ($this->bIncludeAddressDetails) {
// getAddressDetails() is defined in lib.php and uses the SQL function get_addressdata in functions.sql
$aResult['address'] = getAddressDetails($this->oDB, $sLanguagePrefArraySQL, $aResult['place_id'], $aResult['country_code'], $aResults[$aResult['place_id']]->iHouseNumber);
if ($aResult['extra_place'] == 'city' && !isset($aResult['address']['city'])) {
$aResult['address'] = array_merge(array('city' => array_values($aResult['address'])[0]), $aResult['address']);
}
}
$aResult['name'] = $aResult['langaddress'];
@ -990,7 +970,6 @@ class Geocode
'Query' => $this->sQuery,
'Structured query' => $this->aStructuredQuery,
'Name keys' => Debug::fmtArrayVals($this->aLangPrefOrder),
'Include address' => $this->bIncludeAddressDetails,
'Excluded place IDs' => Debug::fmtArrayVals($this->aExcludePlaceIDs),
'Try reversed query'=> $this->bReverseInPlan,
'Limit (for searches)' => $this->iLimit,

View File

@ -2,6 +2,7 @@
namespace Nominatim;
require_once(CONST_BasePath.'/lib/AddressDetails.php');
require_once(CONST_BasePath.'/lib/Result.php');
class PlaceLookup
@ -11,7 +12,6 @@ class PlaceLookup
protected $aLangPrefOrderSql = "''";
protected $bAddressDetails = false;
protected $bAddressAdminLevels = false;
protected $bExtraTags = false;
protected $bNameDetails = false;
@ -43,9 +43,9 @@ class PlaceLookup
$this->bIncludePolygonAsPoints = $b;
}
public function setAddressAdminLevels($b = true)
public function setIncludeAddressDetails($b)
{
$this->bAddressAdminLevels = $b;
$this->bAddressDetails = $b;
}
public function loadParamArray($oParams, $sGeomType = null)
@ -54,7 +54,6 @@ class PlaceLookup
$this->aLangPrefOrderSql =
'ARRAY['.join(',', array_map('getDBQuoted', $aLangs)).']';
$this->bAddressDetails = $oParams->getBool('addressdetails', true);
$this->bExtraTags = $oParams->getBool('extratags', false);
$this->bNameDetails = $oParams->getBool('namedetails', false);
@ -137,11 +136,6 @@ class PlaceLookup
'ARRAY['.join(',', array_map('getDBQuoted', $aLangPrefOrder)).']';
}
public function setIncludeAddressDetails($bAddressDetails = true)
{
$this->bAddressDetails = $bAddressDetails;
}
private function addressImportanceSql($sGeometry, $sPlaceId)
{
if ($this->sAnchorSql) {
@ -160,6 +154,9 @@ class PlaceLookup
private function langAddressSql($sHousenumber)
{
if ($this->bAddressDetails)
return ''; // langaddress will be computed from address details
return 'get_address_by_language(place_id,'.$sHousenumber.','.$this->aLangPrefOrderSql.') AS langaddress,';
}
@ -245,7 +242,7 @@ class PlaceLookup
$sSQL .= ' country_code, ';
$sSQL .= ' importance, ';
if (!$this->bDeDupe) $sSQL .= 'place_id,';
$sSQL .= ' langaddress, ';
if (!$this->bAddressDetails) $sSQL .= 'langaddress, ';
$sSQL .= ' placename, ';
$sSQL .= ' ref, ';
if ($this->bExtraTags) $sSQL .= 'extratags, ';
@ -432,17 +429,13 @@ class PlaceLookup
foreach ($aPlaces as &$aPlace) {
if ($this->bAddressDetails) {
// to get addressdetails for tiger data, the housenumber is needed
$aPlace['aAddress'] = $this->getAddressNames(
$aPlace['address'] = new AddressDetails(
$this->oDB,
$aPlace['place_id'],
$aPlace['housenumber']
);
}
if ($this->bAddressAdminLevels) {
$aPlace['aAddressAdminLevels'] = $this->getAddressAdminLevels(
$aPlace['place_id'],
$aPlace['housenumber']
$aPlace['housenumber'],
$this->aLangPrefOrderSql
);
$aPlace['langaddress'] = $aPlace['address']->getLocaleAddress();
}
if ($this->bExtraTags) {
@ -473,81 +466,6 @@ class PlaceLookup
return $aPlaces;
}
public function getAddressDetails($iPlaceID, $bAll = false, $sHousenumber = -1)
{
$sSQL = 'SELECT *,';
$sSQL .= ' get_name_by_language(name,'.$this->aLangPrefOrderSql.') as localname';
$sSQL .= ' FROM get_addressdata('.$iPlaceID.','.$sHousenumber.')';
if (!$bAll) {
$sSQL .= " WHERE isaddress OR type = 'country_code'";
}
$sSQL .= ' ORDER BY rank_address desc,isaddress DESC';
return chksql($this->oDB->getAll($sSQL));
}
public function getAddressNames($iPlaceID, $sHousenumber = null)
{
$aAddressLines = $this->getAddressDetails(
$iPlaceID,
false,
$sHousenumber === null ? -1 : $sHousenumber
);
$aAddress = array();
$aFallback = array();
foreach ($aAddressLines as $aLine) {
$bFallback = false;
$aTypeLabel = ClassTypes\getInfo($aLine);
if ($aTypeLabel === false) {
$aTypeLabel = ClassTypes\getFallbackInfo($aLine);
$bFallback = true;
}
if ((isset($aLine['localname']) && $aLine['localname']) || (isset($aLine['housenumber']) && $aLine['housenumber'])) {
$sTypeLabel = strtolower(isset($aTypeLabel['simplelabel'])?$aTypeLabel['simplelabel']:$aTypeLabel['label']);
$sTypeLabel = str_replace(' ', '_', $sTypeLabel);
if (!isset($aAddress[$sTypeLabel]) || (isset($aFallback[$sTypeLabel]) && $aFallback[$sTypeLabel]) || $aLine['class'] == 'place') {
$aAddress[$sTypeLabel] = $aLine['localname']?$aLine['localname']:$aLine['housenumber'];
}
$aFallback[$sTypeLabel] = $bFallback;
}
}
return $aAddress;
}
/* "Downing Street, London"
* [
* "level15" => "Covent Garden",
* "level8" => "Westminster",
* "level6" => "London",
* "level5" => "Greater London",
* "level4" => "England",
* "level2" => "United Kingdom"
* ]
*/
public function getAddressAdminLevels($iPlaceID, $sHousenumber = null)
{
$aAddressLines = $this->getAddressDetails(
$iPlaceID,
true,
$sHousenumber === null ? -1 : $sHousenumber
);
$aAddress = array();
foreach ($aAddressLines as $aLine) {
if (isset($aLine['admin_level'])
&& $aLine['admin_level'] < 15
&& !isset($aAddress['level'.$aLine['admin_level']])) {
$aAddress['level'.$aLine['admin_level']] = $aLine['localname'];
}
}
return $aAddress;
}
/* returns an array which will contain the keys
* aBoundingBox
* and may also contain one or more of the keys

View File

@ -83,41 +83,6 @@ function javascript_renderData($xVal, $iOptions = 0)
}
}
function getAddressDetails(&$oDB, $sLanguagePrefArraySQL, $iPlaceID, $sCountryCode = false, $housenumber = -1, $bRaw = false)
{
$sSQL = "select *,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata($iPlaceID, $housenumber)";
if (!$bRaw) $sSQL .= " WHERE isaddress OR type = 'country_code'";
$sSQL .= ' order by rank_address desc,isaddress desc';
$aAddressLines = chksql($oDB->getAll($sSQL));
if ($bRaw) return $aAddressLines;
//echo "<pre>";
//var_dump($aAddressLines);
$aAddress = array();
$aFallback = array();
foreach ($aAddressLines as $aLine) {
$bFallback = false;
$aTypeLabel = Nominatim\ClassTypes\getInfo($aLine);
if ($aTypeLabel === false) {
$aTypeLabel = Nominatim\ClassTypes\getFallbackInfo($aLine);
$bFallback = true;
}
if ((isset($aLine['localname']) && $aLine['localname']) || (isset($aLine['housenumber']) && $aLine['housenumber'])) {
$sTypeLabel = strtolower(isset($aTypeLabel['simplelabel'])?$aTypeLabel['simplelabel']:$aTypeLabel['label']);
$sTypeLabel = str_replace(' ', '_', $sTypeLabel);
if (!isset($aAddress[$sTypeLabel]) || (isset($aFallback[$sTypeLabel]) && $aFallback[$sTypeLabel]) || $aLine['class'] == 'place') {
$aAddress[$sTypeLabel] = $aLine['localname']?$aLine['localname']:$aLine['housenumber'];
}
$aFallback[$sTypeLabel] = $bFallback;
}
}
return $aAddress;
}
function addQuotes($s)
{
return "'".$s."'";

View File

@ -32,25 +32,29 @@ if (empty($aPlace)) {
$aFilteredPlaces['properties']['geocoding']['name'] = $aPlace['placename'];
$aFieldMappings = array(
'house_number' => 'housenumber',
'road' => 'street',
'locality' => 'locality',
'postcode' => 'postcode',
'city' => 'city',
'district' => 'district',
'county' => 'county',
'state' => 'state',
'country' => 'country'
);
if (isset($aPlace['address'])) {
$aFieldMappings = array(
'house_number' => 'housenumber',
'road' => 'street',
'locality' => 'locality',
'postcode' => 'postcode',
'city' => 'city',
'district' => 'district',
'county' => 'county',
'state' => 'state',
'country' => 'country'
);
foreach ($aFieldMappings as $sFrom => $sTo) {
if (isset($aPlace['aAddress'][$sFrom])) {
$aFilteredPlaces['properties']['geocoding'][$sTo] = $aPlace['aAddress'][$sFrom];
$aAddressNames = $aPlace['address']->getAddressNames();
foreach ($aFieldMappings as $sFrom => $sTo) {
if (isset($aAddressNames[$sFrom])) {
$aFilteredPlaces['properties']['geocoding'][$sTo] = $aAddressNames[$sFrom];
}
}
}
$aFilteredPlaces['properties']['geocoding']['admin'] = $aPlace['aAddressAdminLevels'];
$aFilteredPlaces['properties']['geocoding']['admin']
= $aPlace['address']->getAdminLevels();
}
if (isset($aPlace['asgeojson'])) {
$aFilteredPlaces['geometry'] = json_decode($aPlace['asgeojson']);

View File

@ -33,7 +33,9 @@ if (empty($aPlace)) {
$aFilteredPlaces['properties']['display_name'] = $aPlace['langaddress'];
if (isset($aPlace['aAddress'])) $aFilteredPlaces['properties']['address'] = $aPlace['aAddress'];
if (isset($aPlace['address'])) {
$aFilteredPlaces['properties']['address'] = $aPlace['address']->getAddressNames();
}
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['properties']['extratags'] = $aPlace['sExtraTags'];
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['properties']['namedetails'] = $aPlace['sNameDetails'];

View File

@ -32,7 +32,9 @@ if (empty($aPlace)) {
$aFilteredPlaces['display_name'] = $aPlace['langaddress'];
if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
if (isset($aPlace['address'])) {
$aFilteredPlaces['address'] = $aPlace['address']->getAddressNames();
}
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];

View File

@ -48,9 +48,9 @@ if (empty($aPlace)) {
}
echo '>'.htmlspecialchars($aPlace['langaddress']).'</result>';
if (isset($aPlace['aAddress'])) {
if (isset($aPlace['address'])) {
echo '<addressparts>';
foreach ($aPlace['aAddress'] as $sKey => $sValue) {
foreach ($aPlace['address']->getAddressNames() as $sKey => $sValue) {
$sKey = str_replace(' ', '_', $sKey);
echo "<$sKey>";
echo htmlspecialchars($sValue);

View File

@ -49,8 +49,8 @@ foreach ($aBatchResults as $aSearchResults) {
$aPlace['icon'] = $aPointDetails['icon'];
}
if (isset($aPointDetails['address']) && !empty($aPointDetails['address'])) {
$aPlace['address'] = $aPointDetails['address'];
if (isset($aPointDetails['address'])) {
$aPlace['address'] = $aPointDetails['address']->getAddressNames();
}
if (isset($aPointDetails['asgeojson'])) {

View File

@ -22,25 +22,29 @@ foreach ($aSearchResults as $iResNum => $aPointDetails) {
$aPlace['properties']['geocoding']['name'] = $aPointDetails['placename'];
$aFieldMappings = array(
'house_number' => 'housenumber',
'road' => 'street',
'locality' => 'locality',
'postcode' => 'postcode',
'city' => 'city',
'district' => 'district',
'county' => 'county',
'state' => 'state',
'country' => 'country'
);
if (isset($aPointDetails['address'])) {
$aFieldMappings = array(
'house_number' => 'housenumber',
'road' => 'street',
'locality' => 'locality',
'postcode' => 'postcode',
'city' => 'city',
'district' => 'district',
'county' => 'county',
'state' => 'state',
'country' => 'country'
);
foreach ($aFieldMappings as $sFrom => $sTo) {
if (isset($aPointDetails['address'][$sFrom])) {
$aPlace['properties']['geocoding'][$sTo] = $aPointDetails['address'][$sFrom];
$aAddrNames = $aPointDetails['address']->getAddressNames();
foreach ($aFieldMappings as $sFrom => $sTo) {
if (isset($aAddrNames[$sFrom])) {
$aPlace['properties']['geocoding'][$sTo] = $aAddrNames[$sFrom];
}
}
}
$aPlace['properties']['geocoding']['admin'] = $aPointDetails['aAddressAdminLevels'];
$aPlace['properties']['geocoding']['admin']
= $aPointDetails['address']->getAdminLevels();
}
if (isset($aPointDetails['asgeojson'])) {
$aPlace['geometry'] = json_decode($aPointDetails['asgeojson']);

View File

@ -41,8 +41,8 @@ foreach ($aSearchResults as $iResNum => $aPointDetails) {
$aPlace['properties']['icon'] = $aPointDetails['icon'];
}
if (isset($aPointDetails['address']) && !empty($aPointDetails['address'])) {
$aPlace['properties']['address'] = $aPointDetails['address'];
if (isset($aPointDetails['address'])) {
$aPlace['properties']['address'] = $aPointDetails['address']->getAddressNames();
}
if (isset($aPointDetails['asgeojson'])) {

View File

@ -44,8 +44,8 @@ foreach ($aSearchResults as $iResNum => $aPointDetails) {
$aPlace['icon'] = $aPointDetails['icon'];
}
if (isset($aPointDetails['address']) && !empty($aPointDetails['address'])) {
$aPlace['address'] = $aPointDetails['address'];
if (isset($aPointDetails['address'])) {
$aPlace['address'] = $aPointDetails['address']->getAddressNames();
}
if (isset($aPointDetails['asgeojson'])) {

View File

@ -116,7 +116,7 @@ foreach ($aSearchResults as $iResNum => $aResult) {
echo '>';
}
echo "\n";
foreach ($aResult['address'] as $sKey => $sValue) {
foreach ($aResult['address']->getAddressNames() as $sKey => $sValue) {
$sKey = str_replace(' ', '_', $sKey);
echo "<$sKey>";
echo htmlspecialchars($sValue);

View File

@ -5,6 +5,7 @@ require_once(dirname(dirname(__FILE__)).'/settings/settings.php');
require_once(CONST_BasePath.'/lib/init-website.php');
require_once(CONST_BasePath.'/lib/log.php');
require_once(CONST_BasePath.'/lib/output.php');
require_once(CONST_BasePath.'/lib/AddressDetails.php');
ini_set('memory_limit', '200M');
$oParams = new Nominatim\ParameterParser();
@ -164,14 +165,8 @@ if (PEAR::isError($aPointDetails['aExtraTags'])) { // possible timeout
// Address
$aAddressLines = false;
if ($bIncludeAddressDetails) {
$aAddressLines = getAddressDetails(
$oDB,
$sLanguagePrefArraySQL,
$iPlaceID,
$aPointDetails['country_code'],
-1,
true
);
$oDetails = new Nominatim\AddressDetails($oDB, $iPlaceID, -1, $sLanguagePrefArraySQL);
$aAddressLines = $oDetails->getAddressDetails(true);
}
// Linked places

View File

@ -4,7 +4,7 @@
require_once(dirname(dirname(__FILE__)).'/settings/settings.php');
require_once(CONST_BasePath.'/lib/init-website.php');
require_once(CONST_BasePath.'/lib/log.php');
require_once(CONST_BasePath.'/lib/PlaceLookup.php');
require_once(CONST_BasePath.'/lib/AddressDetails.php');
require_once(CONST_BasePath.'/lib/output.php');
ini_set('memory_limit', '200M');
@ -56,11 +56,9 @@ if (CONST_Use_Aux_Location_data) {
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID;
}
$oPlaceLookup = new Nominatim\PlaceLookup($oDB);
$oPlaceLookup->setLanguagePreference($aLangPrefOrder);
$oPlaceLookup->setIncludeAddressDetails(true);
$aPlaceAddress = array_reverse($oPlaceLookup->getAddressDetails($iPlaceID));
$oAddressLookup = new AddressDetails($oDB, $iPlaceID, -1, $aLangPrefOrder);
$aPlaceAddress = array_reverse($oAddressLookup->getAddressDetails());
if (empty($aPlaceAddress)) userError('Unknown place id.');
@ -106,7 +104,7 @@ if (!empty($aParentOfLines)) {
foreach ($aParentOfLines as $aAddressLine) {
$aAddressLine['label'] = Nominatim\ClassTypes\getProperty($aAddressLine, 'label');
if (!$aAddressLine['label']) {
$aAddressLine['label'] = ucwords($aAddressLine['type']);
$aAddressLine['label'] = ucwords($aAddressLine['type']);
}
if (!isset($aGroupedAddressLines[$aAddressLine['label']])) $aGroupedAddressLines[$aAddressLine['label']] = array();

View File

@ -25,6 +25,7 @@ $aCleanedQueryParts = array();
$oPlaceLookup = new Nominatim\PlaceLookup($oDB);
$oPlaceLookup->loadParamArray($oParams);
$oPlaceLookup->setIncludeAddressDetails($oParams->getBool('addressdetails', true));
$aOsmIds = explode(',', $oParams->getString('osm_ids', ''));

View File

@ -23,10 +23,7 @@ $hLog = logStart($oDB, 'reverse', $_SERVER['QUERY_STRING'], $aLangPrefOrder);
$oPlaceLookup = new Nominatim\PlaceLookup($oDB);
$oPlaceLookup->loadParamArray($oParams);
if ($sOutputFormat == 'geocodejson') {
$oPlaceLookup->setIncludeAddressDetails(true);
$oPlaceLookup->setAddressAdminLevels(true);
}
$oPlaceLookup->setIncludeAddressDetails($oParams->getBool('addressdetails', true));
$sOsmType = $oParams->getSet('osm_type', array('N', 'W', 'R'));
$iOsmId = $oParams->getInt('osm_id', -1);