--- /dev/null
+<?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;
+ }
+}
$sFallback = 'boundary:administrative:'.((int)($aPlace['rank_address']/2));
if (isset($aClassType[$sFallback])) {
return $aClassType[$sFallback];
-}
+ }
return array('simplelabel' => 'address'.$aPlace['rank_address']);
}
protected $aLangPrefOrder = array();
- protected $bIncludeAddressDetails = false;
-
protected $aExcludePlaceIDs = array();
protected $bReverseInPlan = false;
$aParams['exclude_place_ids'] = implode(',', $this->aExcludePlaceIDs);
}
- if ($this->bIncludeAddressDetails) $aParams['addressdetails'] = '1';
if ($this->bBoundedSearch) $aParams['bounded'] = '1';
if ($this->aCountryCodes) {
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));
}
$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)
$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'];
'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,
namespace Nominatim;
+require_once(CONST_BasePath.'/lib/AddressDetails.php');
require_once(CONST_BasePath.'/lib/Result.php');
class PlaceLookup
protected $aLangPrefOrderSql = "''";
protected $bAddressDetails = false;
- protected $bAddressAdminLevels = false;
protected $bExtraTags = false;
protected $bNameDetails = false;
$this->bIncludePolygonAsPoints = $b;
}
- public function setAddressAdminLevels($b = true)
+ public function setIncludeAddressDetails($b)
{
- $this->bAddressAdminLevels = $b;
+ $this->bAddressDetails = $b;
}
public function loadParamArray($oParams, $sGeomType = null)
$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);
'ARRAY['.join(',', array_map('getDBQuoted', $aLangPrefOrder)).']';
}
- public function setIncludeAddressDetails($bAddressDetails = true)
- {
- $this->bAddressDetails = $bAddressDetails;
- }
-
private function addressImportanceSql($sGeometry, $sPlaceId)
{
if ($this->sAnchorSql) {
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,';
}
$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, ';
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) {
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
}
}
-
-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."'";
$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']);
$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'];
$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'];
}
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);
$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'])) {
$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']);
$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'])) {
$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'])) {
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);
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();
// 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
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');
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.');
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();
$oPlaceLookup = new Nominatim\PlaceLookup($oDB);
$oPlaceLookup->loadParamArray($oParams);
+$oPlaceLookup->setIncludeAddressDetails($oParams->getBool('addressdetails', true));
$aOsmIds = explode(',', $oParams->getString('osm_ids', ''));
$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);