From: Sarah Hoffmann Date: Tue, 10 Jul 2018 21:38:27 +0000 (+0200) Subject: unify address details lookup X-Git-Tag: v3.2.0~49^2~2 X-Git-Url: https://git.openstreetmap.org./nominatim.git/commitdiff_plain/25baaf530dea28b7cf3c72ba4e83f3ebed05629f 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. --- diff --git a/lib/AddressDetails.php b/lib/AddressDetails.php new file mode 100644 index 00000000..8a4005d9 --- /dev/null +++ b/lib/AddressDetails.php @@ -0,0 +1,117 @@ +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; + } +} diff --git a/lib/ClassTypes.php b/lib/ClassTypes.php index be5577d7..c56e514e 100644 --- a/lib/ClassTypes.php +++ b/lib/ClassTypes.php @@ -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']); } diff --git a/lib/Geocode.php b/lib/Geocode.php index 684e7adb..b9e26f03 100644 --- a/lib/Geocode.php +++ b/lib/Geocode.php @@ -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, diff --git a/lib/PlaceLookup.php b/lib/PlaceLookup.php index 6753a0fa..9e19db90 100644 --- a/lib/PlaceLookup.php +++ b/lib/PlaceLookup.php @@ -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['place_id'], - $aPlace['housenumber'] - ); - } - - if ($this->bAddressAdminLevels) { - $aPlace['aAddressAdminLevels'] = $this->getAddressAdminLevels( + $aPlace['address'] = new AddressDetails( + $this->oDB, $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 diff --git a/lib/lib.php b/lib/lib.php index 39bc90d7..8255aa46 100644 --- a/lib/lib.php +++ b/lib/lib.php @@ -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 "
";
-    //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."'";
diff --git a/lib/template/address-geocodejson.php b/lib/template/address-geocodejson.php
index 92efc8fe..480a4f9e 100644
--- a/lib/template/address-geocodejson.php
+++ b/lib/template/address-geocodejson.php
@@ -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']);
diff --git a/lib/template/address-geojson.php b/lib/template/address-geojson.php
index 8ef5713b..089a86b6 100644
--- a/lib/template/address-geojson.php
+++ b/lib/template/address-geojson.php
@@ -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'];
 
diff --git a/lib/template/address-json.php b/lib/template/address-json.php
index b620c63e..691d6a74 100644
--- a/lib/template/address-json.php
+++ b/lib/template/address-json.php
@@ -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'];
 
diff --git a/lib/template/address-xml.php b/lib/template/address-xml.php
index 5eddfa3e..a17da738 100644
--- a/lib/template/address-xml.php
+++ b/lib/template/address-xml.php
@@ -48,9 +48,9 @@ if (empty($aPlace)) {
     }
     echo '>'.htmlspecialchars($aPlace['langaddress']).'';
 
-    if (isset($aPlace['aAddress'])) {
+    if (isset($aPlace['address'])) {
         echo '';
-        foreach ($aPlace['aAddress'] as $sKey => $sValue) {
+        foreach ($aPlace['address']->getAddressNames() as $sKey => $sValue) {
             $sKey = str_replace(' ', '_', $sKey);
             echo "<$sKey>";
             echo htmlspecialchars($sValue);
diff --git a/lib/template/search-batch-json.php b/lib/template/search-batch-json.php
index 513f3c2b..40b27a72 100644
--- a/lib/template/search-batch-json.php
+++ b/lib/template/search-batch-json.php
@@ -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'])) {
diff --git a/lib/template/search-geocodejson.php b/lib/template/search-geocodejson.php
index 6f822799..f3c577d9 100644
--- a/lib/template/search-geocodejson.php
+++ b/lib/template/search-geocodejson.php
@@ -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']);
diff --git a/lib/template/search-geojson.php b/lib/template/search-geojson.php
index 0d04ddc7..0847fba4 100644
--- a/lib/template/search-geojson.php
+++ b/lib/template/search-geojson.php
@@ -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'])) {
diff --git a/lib/template/search-json.php b/lib/template/search-json.php
index 30817c04..6108aca4 100644
--- a/lib/template/search-json.php
+++ b/lib/template/search-json.php
@@ -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'])) {
diff --git a/lib/template/search-xml.php b/lib/template/search-xml.php
index 94bb7ec9..f67ba33b 100644
--- a/lib/template/search-xml.php
+++ b/lib/template/search-xml.php
@@ -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);
diff --git a/website/details.php b/website/details.php
index 2427c9dd..c9e86312 100755
--- a/website/details.php
+++ b/website/details.php
@@ -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
diff --git a/website/hierarchy.php b/website/hierarchy.php
index bfc0eebb..3ac4f323 100755
--- a/website/hierarchy.php
+++ b/website/hierarchy.php
@@ -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();
diff --git a/website/lookup.php b/website/lookup.php
index 695a083a..f09506a4 100755
--- a/website/lookup.php
+++ b/website/lookup.php
@@ -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', ''));
 
diff --git a/website/reverse.php b/website/reverse.php
index 2e03acae..a7261802 100755
--- a/website/reverse.php
+++ b/website/reverse.php
@@ -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);