Merge pull request #2391 from lonvia/fix-sonar-issues

Fix bugs and code smells found by Sonarqube
This commit is contained in:
Sarah Hoffmann
2021-07-12 17:14:59 +02:00
committed by GitHub
43 changed files with 564 additions and 341 deletions

View File

@@ -61,7 +61,7 @@ class AddressDetails
return join(', ', $aParts); return join(', ', $aParts);
} }
public function getAddressNames($sCountry = null) public function getAddressNames()
{ {
$aAddress = array(); $aAddress = array();
@@ -79,12 +79,11 @@ class AddressDetails
$sName = $aLine['housenumber']; $sName = $aLine['housenumber'];
} }
if (isset($sName)) { if (isset($sName)
if (!isset($aAddress[$sTypeLabel]) && (!isset($aAddress[$sTypeLabel])
|| $aLine['class'] == 'place' || $aLine['class'] == 'place')
) { ) {
$aAddress[$sTypeLabel] = $sName; $aAddress[$sTypeLabel] = $sName;
}
} }
} }

View File

@@ -39,7 +39,9 @@ class DB
$conn->exec("SET DateStyle TO 'sql,european'"); $conn->exec("SET DateStyle TO 'sql,european'");
$conn->exec("SET client_encoding TO 'utf-8'"); $conn->exec("SET client_encoding TO 'utf-8'");
$iMaxExecution = ini_get('max_execution_time'); $iMaxExecution = ini_get('max_execution_time');
if ($iMaxExecution > 0) $conn->setAttribute(\PDO::ATTR_TIMEOUT, $iMaxExecution); // seconds if ($iMaxExecution > 0) {
$conn->setAttribute(\PDO::ATTR_TIMEOUT, $iMaxExecution); // seconds
}
$this->connection = $conn; $this->connection = $conn;
return true; return true;
@@ -95,7 +97,9 @@ class DB
try { try {
$stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage); $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
$row = $stmt->fetch(\PDO::FETCH_NUM); $row = $stmt->fetch(\PDO::FETCH_NUM);
if ($row === false) return false; if ($row === false) {
return false;
}
} catch (\PDOException $e) { } catch (\PDOException $e) {
throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL); throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
} }
@@ -306,9 +310,13 @@ class DB
if (preg_match('/^pgsql:(.+)$/', $sDSN, $aMatches)) { if (preg_match('/^pgsql:(.+)$/', $sDSN, $aMatches)) {
foreach (explode(';', $aMatches[1]) as $sKeyVal) { foreach (explode(';', $aMatches[1]) as $sKeyVal) {
list($sKey, $sVal) = explode('=', $sKeyVal, 2); list($sKey, $sVal) = explode('=', $sKeyVal, 2);
if ($sKey == 'host') $sKey = 'hostspec'; if ($sKey == 'host') {
if ($sKey == 'dbname') $sKey = 'database'; $sKey = 'hostspec';
if ($sKey == 'user') $sKey = 'username'; } elseif ($sKey == 'dbname') {
$sKey = 'database';
} elseif ($sKey == 'user') {
$sKey = 'username';
}
$aInfo[$sKey] = $sVal; $aInfo[$sKey] = $sVal;
} }
} }

View File

@@ -5,7 +5,7 @@ namespace Nominatim;
class DatabaseError extends \Exception class DatabaseError extends \Exception
{ {
public function __construct($message, $code = 500, Exception $previous = null, $oPDOErr, $sSql = null) public function __construct($message, $code, $previous, $oPDOErr, $sSql = null)
{ {
parent::__construct($message, $code, $previous); parent::__construct($message, $code, $previous);
// https://secure.php.net/manual/en/class.pdoexception.php // https://secure.php.net/manual/en/class.pdoexception.php

View File

@@ -78,7 +78,7 @@ class Debug
echo '<th>Address Tokens</th><th>Address Not</th>'; echo '<th>Address Tokens</th><th>Address Not</th>';
echo '<th>country</th><th>operator</th>'; echo '<th>country</th><th>operator</th>';
echo '<th>class</th><th>type</th><th>postcode</th><th>housenumber</th></tr>'; echo '<th>class</th><th>type</th><th>postcode</th><th>housenumber</th></tr>';
foreach ($aSearches as $iRank => $aRankedSet) { foreach ($aSearches as $aRankedSet) {
foreach ($aRankedSet as $aRow) { foreach ($aRankedSet as $aRow) {
$aRow->dumpAsHtmlTableRow($aWordsIDs); $aRow->dumpAsHtmlTableRow($aWordsIDs);
} }

View File

@@ -70,7 +70,9 @@ class Geocode
$aParams['exclude_place_ids'] = implode(',', $this->aExcludePlaceIDs); $aParams['exclude_place_ids'] = implode(',', $this->aExcludePlaceIDs);
} }
if ($this->bBoundedSearch) $aParams['bounded'] = '1'; if ($this->bBoundedSearch) {
$aParams['bounded'] = '1';
}
if ($this->aCountryCodes) { if ($this->aCountryCodes) {
$aParams['countrycodes'] = implode(',', $this->aCountryCodes); $aParams['countrycodes'] = implode(',', $this->aCountryCodes);
@@ -85,8 +87,11 @@ class Geocode
public function setLimit($iLimit = 10) public function setLimit($iLimit = 10)
{ {
if ($iLimit > 50) $iLimit = 50; if ($iLimit > 50) {
if ($iLimit < 1) $iLimit = 1; $iLimit = 50;
} elseif ($iLimit < 1) {
$iLimit = 1;
}
$this->iFinalLimit = $iLimit; $this->iFinalLimit = $iLimit;
$this->iLimit = $iLimit + min($iLimit, 10); $this->iLimit = $iLimit + min($iLimit, 10);
@@ -181,18 +186,24 @@ class Geocode
if ($sExcluded) { if ($sExcluded) {
foreach ($sExcluded as $iExcludedPlaceID) { foreach ($sExcluded as $iExcludedPlaceID) {
$iExcludedPlaceID = (int)$iExcludedPlaceID; $iExcludedPlaceID = (int)$iExcludedPlaceID;
if ($iExcludedPlaceID) if ($iExcludedPlaceID) {
$aExcludePlaceIDs[$iExcludedPlaceID] = $iExcludedPlaceID; $aExcludePlaceIDs[$iExcludedPlaceID] = $iExcludedPlaceID;
}
} }
if (isset($aExcludePlaceIDs)) if (isset($aExcludePlaceIDs)) {
$this->aExcludePlaceIDs = $aExcludePlaceIDs; $this->aExcludePlaceIDs = $aExcludePlaceIDs;
}
} }
// Only certain ranks of feature // Only certain ranks of feature
$sFeatureType = $oParams->getString('featureType'); $sFeatureType = $oParams->getString('featureType');
if (!$sFeatureType) $sFeatureType = $oParams->getString('featuretype'); if (!$sFeatureType) {
if ($sFeatureType) $this->setFeatureType($sFeatureType); $sFeatureType = $oParams->getString('featuretype');
}
if ($sFeatureType) {
$this->setFeatureType($sFeatureType);
}
// Country code list // Country code list
$sCountries = $oParams->getStringList('countrycodes'); $sCountries = $oParams->getStringList('countrycodes');
@@ -202,8 +213,9 @@ class Geocode
$aCountries[] = strtolower($sCountryCode); $aCountries[] = strtolower($sCountryCode);
} }
} }
if (isset($aCountries)) if (isset($aCountries)) {
$this->aCountryCodes = $aCountries; $this->aCountryCodes = $aCountries;
}
} }
$aViewbox = $oParams->getStringList('viewboxlbrt'); $aViewbox = $oParams->getStringList('viewboxlbrt');
@@ -255,13 +267,17 @@ class Geocode
public function loadStructuredAddressElement($sValue, $sKey, $iNewMinAddressRank, $iNewMaxAddressRank, $aItemListValues) public function loadStructuredAddressElement($sValue, $sKey, $iNewMinAddressRank, $iNewMaxAddressRank, $aItemListValues)
{ {
$sValue = trim($sValue); $sValue = trim($sValue);
if (!$sValue) return false; if (!$sValue) {
return false;
}
$this->aStructuredQuery[$sKey] = $sValue; $this->aStructuredQuery[$sKey] = $sValue;
if ($this->iMinAddressRank == 0 && $this->iMaxAddressRank == 30) { if ($this->iMinAddressRank == 0 && $this->iMaxAddressRank == 30) {
$this->iMinAddressRank = $iNewMinAddressRank; $this->iMinAddressRank = $iNewMinAddressRank;
$this->iMaxAddressRank = $iNewMaxAddressRank; $this->iMaxAddressRank = $iNewMaxAddressRank;
} }
if ($aItemListValues) $this->aAddressRankList = array_merge($this->aAddressRankList, $aItemListValues); if ($aItemListValues) {
$this->aAddressRankList = array_merge($this->aAddressRankList, $aItemListValues);
}
return true; return true;
} }
@@ -295,11 +311,11 @@ class Geocode
public function fallbackStructuredQuery() public function fallbackStructuredQuery()
{ {
if (!$this->aStructuredQuery) return false;
$aParams = $this->aStructuredQuery; $aParams = $this->aStructuredQuery;
if (count($aParams) == 1) return false; if (!$aParams || count($aParams) == 1) {
return false;
}
$aOrderToFallback = array('postalcode', 'street', 'city', 'county', 'state'); $aOrderToFallback = array('postalcode', 'street', 'city', 'county', 'state');
@@ -336,14 +352,9 @@ class Geocode
// Add all words from this wordset // Add all words from this wordset
foreach ($aWordset as $iToken => $sToken) { foreach ($aWordset as $iToken => $sToken) {
//echo "<br><b>$sToken</b>";
$aNewWordsetSearches = array(); $aNewWordsetSearches = array();
foreach ($aWordsetSearches as $oCurrentSearch) { foreach ($aWordsetSearches as $oCurrentSearch) {
//echo "<i>";
//var_dump($oCurrentSearch);
//echo "</i>";
// Tokens with full name matches. // Tokens with full name matches.
foreach ($oValidTokens->get(' '.$sToken) as $oSearchTerm) { foreach ($oValidTokens->get(' '.$sToken) as $oSearchTerm) {
$aNewSearches = $oCurrentSearch->extendWithFullTerm( $aNewSearches = $oCurrentSearch->extendWithFullTerm(
@@ -387,7 +398,6 @@ class Geocode
usort($aNewWordsetSearches, array('Nominatim\SearchDescription', 'bySearchRank')); usort($aNewWordsetSearches, array('Nominatim\SearchDescription', 'bySearchRank'));
$aWordsetSearches = array_slice($aNewWordsetSearches, 0, 50); $aWordsetSearches = array_slice($aNewWordsetSearches, 0, 50);
} }
//var_Dump('<hr>',count($aWordsetSearches)); exit;
$aNewPhraseSearches = array_merge($aNewPhraseSearches, $aNewWordsetSearches); $aNewPhraseSearches = array_merge($aNewPhraseSearches, $aNewWordsetSearches);
usort($aNewPhraseSearches, array('Nominatim\SearchDescription', 'bySearchRank')); usort($aNewPhraseSearches, array('Nominatim\SearchDescription', 'bySearchRank'));
@@ -395,8 +405,11 @@ class Geocode
$aSearchHash = array(); $aSearchHash = array();
foreach ($aNewPhraseSearches as $iSearch => $aSearch) { foreach ($aNewPhraseSearches as $iSearch => $aSearch) {
$sHash = serialize($aSearch); $sHash = serialize($aSearch);
if (isset($aSearchHash[$sHash])) unset($aNewPhraseSearches[$iSearch]); if (isset($aSearchHash[$sHash])) {
else $aSearchHash[$sHash] = 1; unset($aNewPhraseSearches[$iSearch]);
} else {
$aSearchHash[$sHash] = 1;
}
} }
$aNewPhraseSearches = array_slice($aNewPhraseSearches, 0, 50); $aNewPhraseSearches = array_slice($aNewPhraseSearches, 0, 50);
@@ -417,10 +430,12 @@ class Geocode
$iSearchCount = 0; $iSearchCount = 0;
$aSearches = array(); $aSearches = array();
foreach ($aGroupedSearches as $iScore => $aNewSearches) { foreach ($aGroupedSearches as $aNewSearches) {
$iSearchCount += count($aNewSearches); $iSearchCount += count($aNewSearches);
$aSearches = array_merge($aSearches, $aNewSearches); $aSearches = array_merge($aSearches, $aNewSearches);
if ($iSearchCount > 50) break; if ($iSearchCount > 50) {
break;
}
} }
} }
@@ -477,7 +492,9 @@ class Geocode
public function lookup() public function lookup()
{ {
Debug::newFunction('Geocode::lookup'); Debug::newFunction('Geocode::lookup');
if (!$this->sQuery && !$this->aStructuredQuery) return array(); if (!$this->sQuery && !$this->aStructuredQuery) {
return array();
}
Debug::printDebugArray('Geocode', $this); Debug::printDebugArray('Geocode', $this);
@@ -503,10 +520,6 @@ class Geocode
Debug::newSection('Query Preprocessing'); Debug::newSection('Query Preprocessing');
$sLanguagePrefArraySQL = $this->oDB->getArraySQL(
$this->oDB->getDBQuotedList($this->aLangPrefOrder)
);
$sQuery = $this->sQuery; $sQuery = $this->sQuery;
if (!preg_match('//u', $sQuery)) { if (!preg_match('//u', $sQuery)) {
userError('Query string is not UTF-8 encoded.'); userError('Query string is not UTF-8 encoded.');
@@ -639,7 +652,9 @@ class Geocode
$aGroupedSearches = array(); $aGroupedSearches = array();
foreach ($aSearches as $aSearch) { foreach ($aSearches as $aSearch) {
if ($aSearch->getRank() < $this->iMaxRank) { if ($aSearch->getRank() < $this->iMaxRank) {
if (!isset($aGroupedSearches[$aSearch->getRank()])) $aGroupedSearches[$aSearch->getRank()] = array(); if (!isset($aGroupedSearches[$aSearch->getRank()])) {
$aGroupedSearches[$aSearch->getRank()] = array();
}
$aGroupedSearches[$aSearch->getRank()][] = $aSearch; $aGroupedSearches[$aSearch->getRank()][] = $aSearch;
} }
} }
@@ -653,7 +668,9 @@ class Geocode
$sHash = serialize($aSearch); $sHash = serialize($aSearch);
if (isset($aSearchHash[$sHash])) { if (isset($aSearchHash[$sHash])) {
unset($aGroupedSearches[$iGroup][$iSearch]); unset($aGroupedSearches[$iGroup][$iSearch]);
if (empty($aGroupedSearches[$iGroup])) unset($aGroupedSearches[$iGroup]); if (empty($aGroupedSearches[$iGroup])) {
unset($aGroupedSearches[$iGroup]);
}
} else { } else {
$aSearchHash[$sHash] = 1; $aSearchHash[$sHash] = 1;
} }
@@ -697,7 +714,9 @@ class Geocode
} }
} }
if ($iQueryLoop > 20) break; if ($iQueryLoop > 20) {
break;
}
} }
if (!empty($aResults)) { if (!empty($aResults)) {
@@ -772,9 +791,9 @@ class Geocode
$aResults = $tempIDs; $aResults = $tempIDs;
} }
if (!empty($aResults)) break; if (!empty($aResults) || $iGroupLoop > 4 || $iQueryLoop > 30) {
if ($iGroupLoop > 4) break; break;
if ($iQueryLoop > 30) break; }
} }
} else { } else {
// Just interpret as a reverse geocode // Just interpret as a reverse geocode
@@ -792,10 +811,8 @@ class Geocode
// No results? Done // No results? Done
if (empty($aResults)) { if (empty($aResults)) {
if ($this->bFallback) { if ($this->bFallback && $this->fallbackStructuredQuery()) {
if ($this->fallbackStructuredQuery()) { return $this->lookup();
return $this->lookup();
}
} }
return array(); return array();
@@ -814,7 +831,9 @@ class Geocode
$aRecheckWords = preg_split('/\b[\s,\\-]*/u', $sQuery); $aRecheckWords = preg_split('/\b[\s,\\-]*/u', $sQuery);
foreach ($aRecheckWords as $i => $sWord) { foreach ($aRecheckWords as $i => $sWord) {
if (!preg_match('/[\pL\pN]/', $sWord)) unset($aRecheckWords[$i]); if (!preg_match('/[\pL\pN]/', $sWord)) {
unset($aRecheckWords[$i]);
}
} }
Debug::printVar('Recheck words', $aRecheckWords); Debug::printVar('Recheck words', $aRecheckWords);
@@ -874,7 +893,9 @@ class Geocode
foreach ($aRecheckWords as $i => $sWord) { foreach ($aRecheckWords as $i => $sWord) {
if (stripos($sAddress, $sWord)!==false) { if (stripos($sAddress, $sWord)!==false) {
$iCountWords++; $iCountWords++;
if (preg_match('/(^|,)\s*'.preg_quote($sWord, '/').'\s*(,|$)/', $sAddress)) $iCountWords += 0.1; if (preg_match('/(^|,)\s*'.preg_quote($sWord, '/').'\s*(,|$)/', $sAddress)) {
$iCountWords += 0.1;
}
} }
} }
@@ -891,15 +912,8 @@ class Geocode
$aToFilter = $aSearchResults; $aToFilter = $aSearchResults;
$aSearchResults = array(); $aSearchResults = array();
$bFirst = true;
foreach ($aToFilter as $aResult) { foreach ($aToFilter as $aResult) {
$this->aExcludePlaceIDs[$aResult['place_id']] = $aResult['place_id']; $this->aExcludePlaceIDs[$aResult['place_id']] = $aResult['place_id'];
if ($bFirst) {
$fLat = $aResult['lat'];
$fLon = $aResult['lon'];
if (isset($aResult['zoom'])) $iZoom = $aResult['zoom'];
$bFirst = false;
}
if (!$this->oPlaceLookup->doDeDupe() || (!isset($aOSMIDDone[$aResult['osm_type'].$aResult['osm_id']]) if (!$this->oPlaceLookup->doDeDupe() || (!isset($aOSMIDDone[$aResult['osm_type'].$aResult['osm_id']])
&& !isset($aClassTypeNameDone[$aResult['osm_type'].$aResult['class'].$aResult['type'].$aResult['name'].$aResult['admin_level']])) && !isset($aClassTypeNameDone[$aResult['osm_type'].$aResult['class'].$aResult['type'].$aResult['name'].$aResult['admin_level']]))
) { ) {
@@ -909,7 +923,9 @@ class Geocode
} }
// Absolute limit on number of results // Absolute limit on number of results
if (count($aSearchResults) >= $this->iFinalLimit) break; if (count($aSearchResults) >= $this->iFinalLimit) {
break;
}
} }
Debug::printVar('Post-filter results', $aSearchResults); Debug::printVar('Post-filter results', $aSearchResults);

View File

@@ -90,14 +90,16 @@ class ParameterParser
$aLanguages = array(); $aLanguages = array();
$sLangString = $this->getString('accept-language', $sFallback); $sLangString = $this->getString('accept-language', $sFallback);
if ($sLangString) { if ($sLangString
if (preg_match_all('/(([a-z]{1,8})([-_][a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $sLangString, $aLanguagesParse, PREG_SET_ORDER)) { && preg_match_all('/(([a-z]{1,8})([-_][a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $sLangString, $aLanguagesParse, PREG_SET_ORDER)
foreach ($aLanguagesParse as $iLang => $aLanguage) { ) {
$aLanguages[$aLanguage[1]] = isset($aLanguage[5])?(float)$aLanguage[5]:1 - ($iLang/100); foreach ($aLanguagesParse as $iLang => $aLanguage) {
if (!isset($aLanguages[$aLanguage[2]])) $aLanguages[$aLanguage[2]] = $aLanguages[$aLanguage[1]]/10; $aLanguages[$aLanguage[1]] = isset($aLanguage[5])?(float)$aLanguage[5]:1 - ($iLang/100);
if (!isset($aLanguages[$aLanguage[2]])) {
$aLanguages[$aLanguage[2]] = $aLanguages[$aLanguage[1]]/10;
} }
arsort($aLanguages);
} }
arsort($aLanguages);
} }
if (empty($aLanguages) && CONST_Default_Language) { if (empty($aLanguages) && CONST_Default_Language) {
$aLanguages[CONST_Default_Language] = 1; $aLanguages[CONST_Default_Language] = 1;

View File

@@ -89,20 +89,36 @@ class PlaceLookup
{ {
$aParams = array(); $aParams = array();
if ($this->bAddressDetails) $aParams['addressdetails'] = '1'; if ($this->bAddressDetails) {
if ($this->bExtraTags) $aParams['extratags'] = '1'; $aParams['addressdetails'] = '1';
if ($this->bNameDetails) $aParams['namedetails'] = '1'; }
if ($this->bExtraTags) {
$aParams['extratags'] = '1';
}
if ($this->bNameDetails) {
$aParams['namedetails'] = '1';
}
if ($this->bIncludePolygonAsText) $aParams['polygon_text'] = '1'; if ($this->bIncludePolygonAsText) {
if ($this->bIncludePolygonAsGeoJSON) $aParams['polygon_geojson'] = '1'; $aParams['polygon_text'] = '1';
if ($this->bIncludePolygonAsKML) $aParams['polygon_kml'] = '1'; }
if ($this->bIncludePolygonAsSVG) $aParams['polygon_svg'] = '1'; if ($this->bIncludePolygonAsGeoJSON) {
$aParams['polygon_geojson'] = '1';
}
if ($this->bIncludePolygonAsKML) {
$aParams['polygon_kml'] = '1';
}
if ($this->bIncludePolygonAsSVG) {
$aParams['polygon_svg'] = '1';
}
if ($this->fPolygonSimplificationThreshold > 0.0) { if ($this->fPolygonSimplificationThreshold > 0.0) {
$aParams['polygon_threshold'] = $this->fPolygonSimplificationThreshold; $aParams['polygon_threshold'] = $this->fPolygonSimplificationThreshold;
} }
if (!$this->bDeDupe) $aParams['dedupe'] = '0'; if (!$this->bDeDupe) {
$aParams['dedupe'] = '0';
}
return $aParams; return $aParams;
} }
@@ -147,8 +163,9 @@ class PlaceLookup
private function langAddressSql($sHousenumber) private function langAddressSql($sHousenumber)
{ {
if ($this->bAddressDetails) if ($this->bAddressDetails) {
return ''; // langaddress will be computed from address details return ''; // langaddress will be computed from address details
}
return 'get_address_by_language(place_id,'.$sHousenumber.','.$this->aLangPrefOrderSql.') AS langaddress,'; return 'get_address_by_language(place_id,'.$sHousenumber.','.$this->aLangPrefOrderSql.') AS langaddress,';
} }
@@ -234,12 +251,20 @@ class PlaceLookup
$sSQL .= ' housenumber,'; $sSQL .= ' housenumber,';
$sSQL .= ' country_code, '; $sSQL .= ' country_code, ';
$sSQL .= ' importance, '; $sSQL .= ' importance, ';
if (!$this->bDeDupe) $sSQL .= 'place_id,'; if (!$this->bDeDupe) {
if (!$this->bAddressDetails) $sSQL .= 'langaddress, '; $sSQL .= 'place_id,';
}
if (!$this->bAddressDetails) {
$sSQL .= 'langaddress, ';
}
$sSQL .= ' placename, '; $sSQL .= ' placename, ';
$sSQL .= ' ref, '; $sSQL .= ' ref, ';
if ($this->bExtraTags) $sSQL .= 'extratags, '; if ($this->bExtraTags) {
if ($this->bNameDetails) $sSQL .= 'name, '; $sSQL .= 'extratags, ';
}
if ($this->bNameDetails) {
$sSQL .= 'name, ';
}
$sSQL .= ' extra_place '; $sSQL .= ' extra_place ';
$aSubSelects[] = $sSQL; $aSubSelects[] = $sSQL;
@@ -260,8 +285,12 @@ class PlaceLookup
$sSQL .= $this->langAddressSql('-1'); $sSQL .= $this->langAddressSql('-1');
$sSQL .= ' postcode as placename,'; $sSQL .= ' postcode as placename,';
$sSQL .= ' postcode as ref,'; $sSQL .= ' postcode as ref,';
if ($this->bExtraTags) $sSQL .= 'null::text AS extra,'; if ($this->bExtraTags) {
if ($this->bNameDetails) $sSQL .= 'null::text AS names,'; $sSQL .= 'null::text AS extra,';
}
if ($this->bNameDetails) {
$sSQL .= 'null::text AS names,';
}
$sSQL .= ' ST_x(geometry) AS lon, ST_y(geometry) AS lat,'; $sSQL .= ' ST_x(geometry) AS lon, ST_y(geometry) AS lat,';
$sSQL .= ' (0.75-(rank_search::float/40)) AS importance, '; $sSQL .= ' (0.75-(rank_search::float/40)) AS importance, ';
$sSQL .= $this->addressImportanceSql('geometry', 'lp.parent_place_id'); $sSQL .= $this->addressImportanceSql('geometry', 'lp.parent_place_id');
@@ -298,8 +327,12 @@ class PlaceLookup
$sSQL .= $this->langAddressSql('housenumber_for_place'); $sSQL .= $this->langAddressSql('housenumber_for_place');
$sSQL .= ' null::text AS placename, '; $sSQL .= ' null::text AS placename, ';
$sSQL .= ' null::text AS ref, '; $sSQL .= ' null::text AS ref, ';
if ($this->bExtraTags) $sSQL .= 'null::text AS extra,'; if ($this->bExtraTags) {
if ($this->bNameDetails) $sSQL .= 'null::text AS names,'; $sSQL .= 'null::text AS extra,';
}
if ($this->bNameDetails) {
$sSQL .= 'null::text AS names,';
}
$sSQL .= ' st_x(centroid) AS lon, '; $sSQL .= ' st_x(centroid) AS lon, ';
$sSQL .= ' st_y(centroid) AS lat,'; $sSQL .= ' st_y(centroid) AS lat,';
$sSQL .= ' -1.15 AS importance, '; $sSQL .= ' -1.15 AS importance, ';
@@ -344,8 +377,12 @@ class PlaceLookup
$sSQL .= $this->langAddressSql('housenumber_for_place'); $sSQL .= $this->langAddressSql('housenumber_for_place');
$sSQL .= ' null::text AS placename, '; $sSQL .= ' null::text AS placename, ';
$sSQL .= ' null::text AS ref, '; $sSQL .= ' null::text AS ref, ';
if ($this->bExtraTags) $sSQL .= 'null::text AS extra, '; if ($this->bExtraTags) {
if ($this->bNameDetails) $sSQL .= 'null::text AS names, '; $sSQL .= 'null::text AS extra, ';
}
if ($this->bNameDetails) {
$sSQL .= 'null::text AS names, ';
}
$sSQL .= ' st_x(centroid) AS lon, '; $sSQL .= ' st_x(centroid) AS lon, ';
$sSQL .= ' st_y(centroid) AS lat, '; $sSQL .= ' st_y(centroid) AS lat, ';
// slightly smaller than the importance for normal houses // slightly smaller than the importance for normal houses
@@ -448,7 +485,9 @@ class PlaceLookup
{ {
$aOutlineResult = array(); $aOutlineResult = array();
if (!$iPlaceID) return $aOutlineResult; if (!$iPlaceID) {
return $aOutlineResult;
}
// Get the bounding box and outline polygon // Get the bounding box and outline polygon
$sSQL = 'select place_id,0 as numfeatures,st_area(geometry) as area,'; $sSQL = 'select place_id,0 as numfeatures,st_area(geometry) as area,';
@@ -460,10 +499,18 @@ class PlaceLookup
} }
$sSQL .= ' ST_YMin(geometry) as minlat,ST_YMax(geometry) as maxlat,'; $sSQL .= ' ST_YMin(geometry) as minlat,ST_YMax(geometry) as maxlat,';
$sSQL .= ' ST_XMin(geometry) as minlon,ST_XMax(geometry) as maxlon'; $sSQL .= ' ST_XMin(geometry) as minlon,ST_XMax(geometry) as maxlon';
if ($this->bIncludePolygonAsGeoJSON) $sSQL .= ',ST_AsGeoJSON(geometry) as asgeojson'; if ($this->bIncludePolygonAsGeoJSON) {
if ($this->bIncludePolygonAsKML) $sSQL .= ',ST_AsKML(geometry) as askml'; $sSQL .= ',ST_AsGeoJSON(geometry) as asgeojson';
if ($this->bIncludePolygonAsSVG) $sSQL .= ',ST_AsSVG(geometry) as assvg'; }
if ($this->bIncludePolygonAsText) $sSQL .= ',ST_AsText(geometry) as astext'; if ($this->bIncludePolygonAsKML) {
$sSQL .= ',ST_AsKML(geometry) as askml';
}
if ($this->bIncludePolygonAsSVG) {
$sSQL .= ',ST_AsSVG(geometry) as assvg';
}
if ($this->bIncludePolygonAsText) {
$sSQL .= ',ST_AsText(geometry) as astext';
}
if ($fLonReverse != null && $fLatReverse != null) { if ($fLonReverse != null && $fLatReverse != null) {
$sFrom = ' from (SELECT * , CASE WHEN (class = \'highway\') AND (ST_GeometryType(geometry) = \'ST_LineString\') THEN '; $sFrom = ' from (SELECT * , CASE WHEN (class = \'highway\') AND (ST_GeometryType(geometry) = \'ST_LineString\') THEN ';
$sFrom .=' ST_ClosestPoint(geometry, ST_SetSRID(ST_Point('.$fLatReverse.','.$fLonReverse.'),4326))'; $sFrom .=' ST_ClosestPoint(geometry, ST_SetSRID(ST_Point('.$fLatReverse.','.$fLonReverse.'),4326))';
@@ -486,10 +533,18 @@ class PlaceLookup
$aOutlineResult['lon'] = $aPointPolygon['centrelon']; $aOutlineResult['lon'] = $aPointPolygon['centrelon'];
} }
if ($this->bIncludePolygonAsGeoJSON) $aOutlineResult['asgeojson'] = $aPointPolygon['asgeojson']; if ($this->bIncludePolygonAsGeoJSON) {
if ($this->bIncludePolygonAsKML) $aOutlineResult['askml'] = $aPointPolygon['askml']; $aOutlineResult['asgeojson'] = $aPointPolygon['asgeojson'];
if ($this->bIncludePolygonAsSVG) $aOutlineResult['assvg'] = $aPointPolygon['assvg']; }
if ($this->bIncludePolygonAsText) $aOutlineResult['astext'] = $aPointPolygon['astext']; if ($this->bIncludePolygonAsKML) {
$aOutlineResult['askml'] = $aPointPolygon['askml'];
}
if ($this->bIncludePolygonAsSVG) {
$aOutlineResult['assvg'] = $aPointPolygon['assvg'];
}
if ($this->bIncludePolygonAsText) {
$aOutlineResult['astext'] = $aPointPolygon['astext'];
}
if (abs($aPointPolygon['minlat'] - $aPointPolygon['maxlat']) < 0.0000001) { if (abs($aPointPolygon['minlat'] - $aPointPolygon['maxlat']) < 0.0000001) {
$aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius; $aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius;

View File

@@ -74,8 +74,6 @@ class ReverseGeocode
protected function lookupLargeArea($sPointSQL, $iMaxRank) protected function lookupLargeArea($sPointSQL, $iMaxRank)
{ {
$oResult = null;
if ($iMaxRank > 4) { if ($iMaxRank > 4) {
$aPlace = $this->lookupPolygon($sPointSQL, $iMaxRank); $aPlace = $this->lookupPolygon($sPointSQL, $iMaxRank);
if ($aPlace) { if ($aPlace) {
@@ -167,9 +165,13 @@ class ReverseGeocode
{ {
Debug::newFunction('lookupPolygon'); Debug::newFunction('lookupPolygon');
// polygon search begins at suburb-level // polygon search begins at suburb-level
if ($iMaxRank > 25) $iMaxRank = 25; if ($iMaxRank > 25) {
$iMaxRank = 25;
}
// no polygon search over country-level // no polygon search over country-level
if ($iMaxRank < 5) $iMaxRank = 5; if ($iMaxRank < 5) {
$iMaxRank = 5;
}
// search for polygon // search for polygon
$sSQL = 'SELECT place_id, parent_place_id, rank_address, rank_search FROM'; $sSQL = 'SELECT place_id, parent_place_id, rank_address, rank_search FROM';
$sSQL .= '(select place_id, parent_place_id, rank_address, rank_search, country_code, geometry'; $sSQL .= '(select place_id, parent_place_id, rank_address, rank_search, country_code, geometry';
@@ -190,7 +192,6 @@ class ReverseGeocode
if ($aPoly) { if ($aPoly) {
// if a polygon is found, search for placenodes begins ... // if a polygon is found, search for placenodes begins ...
$iParentPlaceID = $aPoly['parent_place_id'];
$iRankAddress = $aPoly['rank_address']; $iRankAddress = $aPoly['rank_address'];
$iRankSearch = $aPoly['rank_search']; $iRankSearch = $aPoly['rank_search'];
$iPlaceID = $aPoly['place_id']; $iPlaceID = $aPoly['place_id'];
@@ -242,26 +243,24 @@ class ReverseGeocode
public function lookupPoint($sPointSQL, $bDoInterpolation = true) public function lookupPoint($sPointSQL, $bDoInterpolation = true)
{ {
Debug::newFunction('lookupPoint'); Debug::newFunction('lookupPoint');
// starts if the search is on POI or street level,
// searches for the nearest POI or street,
// if a street is found and a POI is searched for,
// the nearest POI which the found street is a parent of is choosen.
$iMaxRank = $this->iMaxRank;
// Find the nearest point // Find the nearest point
$fSearchDiam = 0.006; $fSearchDiam = 0.006;
$oResult = null; $oResult = null;
$aPlace = null; $aPlace = null;
// for POI or street level // for POI or street level
if ($iMaxRank >= 26) { if ($this->iMaxRank >= 26) {
// starts if the search is on POI or street level,
// searches for the nearest POI or street,
// if a street is found and a POI is searched for,
// the nearest POI which the found street is a parent of is choosen.
$sSQL = 'select place_id,parent_place_id,rank_address,country_code,'; $sSQL = 'select place_id,parent_place_id,rank_address,country_code,';
$sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance'; $sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance';
$sSQL .= ' FROM '; $sSQL .= ' FROM ';
$sSQL .= ' placex'; $sSQL .= ' placex';
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', geometry, '.$fSearchDiam.')'; $sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', geometry, '.$fSearchDiam.')';
$sSQL .= ' AND'; $sSQL .= ' AND';
$sSQL .= ' rank_address between 26 and '.$iMaxRank; $sSQL .= ' rank_address between 26 and '.$this->iMaxRank;
$sSQL .= ' and (name is not null or housenumber is not null'; $sSQL .= ' and (name is not null or housenumber is not null';
$sSQL .= ' or rank_address between 26 and 27)'; $sSQL .= ' or rank_address between 26 and 27)';
$sSQL .= ' and (rank_address between 26 and 27'; $sSQL .= ' and (rank_address between 26 and 27';
@@ -284,7 +283,7 @@ class ReverseGeocode
if ($aPlace) { if ($aPlace) {
// if street and maxrank > streetlevel // if street and maxrank > streetlevel
if ($iRankAddress <= 27 && $iMaxRank > 27) { if ($iRankAddress <= 27 && $this->iMaxRank > 27) {
// find the closest object (up to a certain radius) of which the street is a parent of // find the closest object (up to a certain radius) of which the street is a parent of
$sSQL = ' select place_id,'; $sSQL = ' select place_id,';
$sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance'; $sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance';
@@ -338,7 +337,7 @@ class ReverseGeocode
} }
} }
if ($bDoInterpolation && $iMaxRank >= 30) { if ($bDoInterpolation && $this->iMaxRank >= 30) {
$fDistance = $fSearchDiam; $fDistance = $fSearchDiam;
if ($aPlace) { if ($aPlace) {
// We can't reliably go from the closest street to an // We can't reliably go from the closest street to an
@@ -356,7 +355,6 @@ class ReverseGeocode
$oResult = new Result($aHouse['place_id'], Result::TABLE_OSMLINE); $oResult = new Result($aHouse['place_id'], Result::TABLE_OSMLINE);
$oResult->iHouseNumber = closestHouseNumber($aHouse); $oResult->iHouseNumber = closestHouseNumber($aHouse);
$aPlace = $aHouse; $aPlace = $aHouse;
$iRankAddress = 30;
} }
} }
@@ -366,7 +364,7 @@ class ReverseGeocode
} }
} else { } else {
// lower than street level ($iMaxRank < 26 ) // lower than street level ($iMaxRank < 26 )
$oResult = $this->lookupLargeArea($sPointSQL, $iMaxRank); $oResult = $this->lookupLargeArea($sPointSQL, $this->iMaxRank);
} }
Debug::printVar('Final result', $oResult); Debug::printVar('Final result', $oResult);

View File

@@ -415,7 +415,6 @@ class SearchDescription
public function query(&$oDB, $iMinRank, $iMaxRank, $iLimit) public function query(&$oDB, $iMinRank, $iMaxRank, $iLimit)
{ {
$aResults = array(); $aResults = array();
$iHousenumber = -1;
if ($this->sCountryCode if ($this->sCountryCode
&& empty($this->aName) && empty($this->aName)

View File

@@ -33,7 +33,9 @@ class Shell
public function addEnvPair($sKey, $sVal) public function addEnvPair($sKey, $sVal)
{ {
if (isset($sKey) && $sKey && isset($sVal)) { if (isset($sKey) && $sKey && isset($sVal)) {
if (!isset($this->aEnv)) $this->aEnv = $_ENV; if (!isset($this->aEnv)) {
$this->aEnv = $_ENV;
}
$this->aEnv = array_merge($this->aEnv, array($sKey => $sVal), $_ENV); $this->aEnv = array_merge($this->aEnv, array($sKey => $sVal), $_ENV);
} }
return $this; return $this;
@@ -75,11 +77,8 @@ class Shell
return $iStat; return $iStat;
} }
private function escapeParam($sParam) private function escapeParam($sParam)
{ {
if (preg_match('/^-*\w+$/', $sParam)) return $sParam; return (preg_match('/^-*\w+$/', $sParam)) ? $sParam : escapeshellarg($sParam);
return escapeshellarg($sParam);
} }
} }

View File

@@ -49,7 +49,9 @@
$oDB->connect(); $oDB->connect();
if (isset($aCMDResult['output-type'])) { if (isset($aCMDResult['output-type'])) {
if (!isset($aRankmap[$aCMDResult['output-type']])) fail('unknown output-type: '.$aCMDResult['output-type']); if (!isset($aRankmap[$aCMDResult['output-type']])) {
fail('unknown output-type: '.$aCMDResult['output-type']);
}
$iOutputRank = $aRankmap[$aCMDResult['output-type']]; $iOutputRank = $aRankmap[$aCMDResult['output-type']];
} else { } else {
$iOutputRank = $aRankmap['street']; $iOutputRank = $aRankmap['street'];
@@ -58,14 +60,18 @@
// Preferred language // Preferred language
$oParams = new Nominatim\ParameterParser(); $oParams = new Nominatim\ParameterParser();
if (!isset($aCMDResult['language'])) $aCMDResult['language'] = 'xx'; if (!isset($aCMDResult['language'])) {
$aCMDResult['language'] = 'xx';
}
$aLangPrefOrder = $oParams->getPreferredLanguages($aCMDResult['language']); $aLangPrefOrder = $oParams->getPreferredLanguages($aCMDResult['language']);
$sLanguagePrefArraySQL = $oDB->getArraySQL($oDB->getDBQuotedList($aLangPrefOrder)); $sLanguagePrefArraySQL = $oDB->getArraySQL($oDB->getDBQuotedList($aLangPrefOrder));
// output formatting: build up a lookup table that maps address ranks to columns // output formatting: build up a lookup table that maps address ranks to columns
$aColumnMapping = array(); $aColumnMapping = array();
$iNumCol = 0; $iNumCol = 0;
if (!isset($aCMDResult['output-format'])) $aCMDResult['output-format'] = 'street;suburb;city;county;state;country'; if (!isset($aCMDResult['output-format'])) {
$aCMDResult['output-format'] = 'street;suburb;city;county;state;country';
}
foreach (preg_split('/\s*;\s*/', $aCMDResult['output-format']) as $sColumn) { foreach (preg_split('/\s*;\s*/', $aCMDResult['output-format']) as $sColumn) {
$bHasData = false; $bHasData = false;
foreach (preg_split('/\s*,\s*/', $sColumn) as $sRank) { foreach (preg_split('/\s*,\s*/', $sColumn) as $sRank) {
@@ -80,7 +86,9 @@
} }
} }
} }
if ($bHasData) $iNumCol++; if ($bHasData) {
$iNumCol++;
}
} }
// build the query for objects // build the query for objects
@@ -122,7 +130,9 @@
if ($sOsmType) { if ($sOsmType) {
$sSQL = 'select place_id from placex where osm_type = :osm_type and osm_id = :osm_id'; $sSQL = 'select place_id from placex where osm_type = :osm_type and osm_id = :osm_id';
$sParentId = $oDB->getOne($sSQL, array('osm_type' => $sOsmType, 'osm_id' => $sOsmId)); $sParentId = $oDB->getOne($sSQL, array('osm_type' => $sOsmType, 'osm_id' => $sOsmId));
if (!$sParentId) fail('Could not find place '.$sOsmType.' '.$sOsmId); if (!$sParentId) {
fail('Could not find place '.$sOsmType.' '.$sOsmId);
}
} }
if ($sParentId) { if ($sParentId) {
$sPlacexSQL .= ' and place_id in (select place_id from place_addressline where address_place_id = '.$sParentId.' and isaddress)'; $sPlacexSQL .= ' and place_id in (select place_id from place_addressline where address_place_id = '.$sParentId.' and isaddress)';
@@ -136,7 +146,6 @@
$oResults = $oDB->getQueryStatement($sPlacexSQL); $oResults = $oDB->getQueryStatement($sPlacexSQL);
$fOutstream = fopen('php://output', 'w'); $fOutstream = fopen('php://output', 'w');
while ($aRow = $oResults->fetch()) { while ($aRow = $oResults->fetch()) {
//var_dump($aRow);
$iPlaceID = $aRow['place_id']; $iPlaceID = $aRow['place_id'];
$sSQL = "select rank_address,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata(:place_id, -1)"; $sSQL = "select rank_address,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata(:place_id, -1)";
$sSQL .= ' WHERE isaddress'; $sSQL .= ' WHERE isaddress';

View File

@@ -40,7 +40,9 @@ $oDB->connect();
$fPostgresVersion = $oDB->getPostgresVersion(); $fPostgresVersion = $oDB->getPostgresVersion();
$aDSNInfo = Nominatim\DB::parseDSN(getSetting('DATABASE_DSN')); $aDSNInfo = Nominatim\DB::parseDSN(getSetting('DATABASE_DSN'));
if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432; if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) {
$aDSNInfo['port'] = 5432;
}
// cache memory to be used by osm2pgsql, should not be more than the available memory // cache memory to be used by osm2pgsql, should not be more than the available memory
$iCacheMemory = (isset($aResult['osm2pgsql-cache'])?$aResult['osm2pgsql-cache']:2000); $iCacheMemory = (isset($aResult['osm2pgsql-cache'])?$aResult['osm2pgsql-cache']:2000);

View File

@@ -62,11 +62,15 @@ if (!$aResult['search-only']) {
$oPlaceLookup->setLanguagePreference(array('en')); $oPlaceLookup->setLanguagePreference(array('en'));
echo 'Warm reverse: '; echo 'Warm reverse: ';
if ($bVerbose) echo "\n"; if ($bVerbose) {
echo "\n";
}
for ($i = 0; $i < 1000; $i++) { for ($i = 0; $i < 1000; $i++) {
$fLat = rand(-9000, 9000) / 100; $fLat = rand(-9000, 9000) / 100;
$fLon = rand(-18000, 18000) / 100; $fLon = rand(-18000, 18000) / 100;
if ($bVerbose) echo "$fLat, $fLon = "; if ($bVerbose) {
echo "$fLat, $fLon = ";
}
$oLookup = $oReverseGeocode->lookup($fLat, $fLon); $oLookup = $oReverseGeocode->lookup($fLat, $fLon);
$aSearchResults = $oLookup ? $oPlaceLookup->lookup(array($oLookup->iId => $oLookup)) : null; $aSearchResults = $oLookup ? $oPlaceLookup->lookup(array($oLookup->iId => $oLookup)) : null;
@@ -79,10 +83,14 @@ if (!$aResult['reverse-only']) {
$oGeocode = new Nominatim\Geocode($oDB); $oGeocode = new Nominatim\Geocode($oDB);
echo 'Warm search: '; echo 'Warm search: ';
if ($bVerbose) echo "\n"; if ($bVerbose) {
echo "\n";
}
$sSQL = 'SELECT word FROM word WHERE word is not null ORDER BY search_name_count DESC LIMIT 1000'; $sSQL = 'SELECT word FROM word WHERE word is not null ORDER BY search_name_count DESC LIMIT 1000';
foreach ($oDB->getCol($sSQL) as $sWord) { foreach ($oDB->getCol($sSQL) as $sWord) {
if ($bVerbose) echo "$sWord = "; if ($bVerbose) {
echo "$sWord = ";
}
$oGeocode->setLanguagePreference(array('en')); $oGeocode->setLanguagePreference(array('en'));
$oGeocode->setQuery($sWord); $oGeocode->setQuery($sWord);

View File

@@ -9,8 +9,12 @@ function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnkn
foreach ($aSpec as $aLine) { foreach ($aSpec as $aLine) {
if (is_array($aLine)) { if (is_array($aLine)) {
if ($aLine[0]) $aQuick['--'.$aLine[0]] = $aLine; if ($aLine[0]) {
if ($aLine[1]) $aQuick['-'.$aLine[1]] = $aLine; $aQuick['--'.$aLine[0]] = $aLine;
}
if ($aLine[1]) {
$aQuick['-'.$aLine[1]] = $aLine;
}
$aCounts[$aLine[0]] = 0; $aCounts[$aLine[0]] = 0;
} }
} }
@@ -28,7 +32,9 @@ function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnkn
$xVal = array(); $xVal = array();
for ($n = $aLine[4]; $i < $iSize && $n; $n--) { for ($n = $aLine[4]; $i < $iSize && $n; $n--) {
$i++; $i++;
if ($i >= $iSize || $aArg[$i][0] == '-') showUsage($aSpec, $bExitOnError, 'Parameter of \''.$aLine[0].'\' is missing'); if ($i >= $iSize || $aArg[$i][0] == '-') {
showUsage($aSpec, $bExitOnError, 'Parameter of \''.$aLine[0].'\' is missing');
}
switch ($aLine[6]) { switch ($aLine[6]) {
case 'realpath': case 'realpath':
@@ -56,7 +62,9 @@ function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnkn
break; break;
} }
} }
if ($aLine[4] == 1) $xVal = $xVal[0]; if ($aLine[4] == 1) {
$xVal = $xVal[0];
}
} else { } else {
$xVal = true; $xVal = true;
} }
@@ -65,7 +73,9 @@ function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnkn
} }
if ($aLine[3] > 1) { if ($aLine[3] > 1) {
if (!array_key_exists($aLine[0], $aResult)) $aResult[$aLine[0]] = array(); if (!array_key_exists($aLine[0], $aResult)) {
$aResult[$aLine[0]] = array();
}
$aResult[$aLine[0]][] = $xVal; $aResult[$aLine[0]][] = $xVal;
} else { } else {
$aResult[$aLine[0]] = $xVal; $aResult[$aLine[0]] = $xVal;
@@ -75,18 +85,23 @@ function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnkn
} }
} }
if (array_key_exists('help', $aResult)) showUsage($aSpec); if (array_key_exists('help', $aResult)) {
if ($bUnknown && $bExitOnUnknown) showUsage($aSpec, $bExitOnError, 'Unknown option \''.$bUnknown.'\''); showUsage($aSpec);
}
if ($bUnknown && $bExitOnUnknown) {
showUsage($aSpec, $bExitOnError, 'Unknown option \''.$bUnknown.'\'');
}
foreach ($aSpec as $aLine) { foreach ($aSpec as $aLine) {
if (is_array($aLine)) { if (is_array($aLine)) {
if ($aCounts[$aLine[0]] < $aLine[2]) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is missing'); if ($aCounts[$aLine[0]] < $aLine[2]) {
if ($aCounts[$aLine[0]] > $aLine[3]) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is pressent too many times'); showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is missing');
switch ($aLine[6]) { }
case 'bool': if ($aCounts[$aLine[0]] > $aLine[3]) {
if (!array_key_exists($aLine[0], $aResult)) showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is pressent too many times');
$aResult[$aLine[0]] = false; }
break; if ($aLine[6] == 'bool' && !array_key_exists($aLine[0], $aResult)) {
$aResult[$aLine[0]] = false;
} }
} }
} }
@@ -109,8 +124,12 @@ function showUsage($aSpec, $bExit = false, $sError = false)
echo "\n"; echo "\n";
} }
$aNames = array(); $aNames = array();
if ($aLine[1]) $aNames[] = '-'.$aLine[1]; if ($aLine[1]) {
if ($aLine[0]) $aNames[] = '--'.$aLine[0]; $aNames[] = '-'.$aLine[1];
}
if ($aLine[0]) {
$aNames[] = '--'.$aLine[0];
}
$sName = join(', ', $aNames); $sName = join(', ', $aNames);
echo ' '.$sName.str_repeat(' ', 30-strlen($sName)).$aLine[7]."\n"; echo ' '.$sName.str_repeat(' ', 30-strlen($sName)).$aLine[7]."\n";
} else { } else {

View File

@@ -81,6 +81,10 @@ if (CONST_NoAccessControl) {
header('Access-Control-Allow-Headers: '.$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']); header('Access-Control-Allow-Headers: '.$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
} }
} }
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS') exit; if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
exit;
}
if (CONST_Debug) header('Content-type: text/html; charset=utf-8'); if (CONST_Debug) {
header('Content-type: text/html; charset=utf-8');
}

View File

@@ -6,10 +6,7 @@ function loadSettings($sProjectDir)
// Temporary hack to set the direcory via environment instead of // Temporary hack to set the direcory via environment instead of
// the installed scripts. Neither setting is part of the official // the installed scripts. Neither setting is part of the official
// set of settings. // set of settings.
defined('CONST_DataDir') or define('CONST_DataDir', $_SERVER['NOMINATIM_DATADIR']);
defined('CONST_SqlDir') or define('CONST_SqlDir', $_SERVER['NOMINATIM_SQLDIR']);
defined('CONST_ConfigDir') or define('CONST_ConfigDir', $_SERVER['NOMINATIM_CONFIGDIR']); defined('CONST_ConfigDir') or define('CONST_ConfigDir', $_SERVER['NOMINATIM_CONFIGDIR']);
defined('CONST_Default_ModulePath') or define('CONST_Default_ModulePath', $_SERVER['NOMINATIM_DATABASE_MODULE_SRC_PATH']);
} }
function getSetting($sConfName, $sDefault = null) function getSetting($sConfName, $sDefault = null)
@@ -32,22 +29,14 @@ function getSettingBool($sConfName)
|| strcmp($sVal, '1') == 0; || strcmp($sVal, '1') == 0;
} }
function getSettingConfig($sConfName, $sSystemConfig)
{
$sValue = $_SERVER['NOMINATIM_'.$sConfName];
if (!$sValue) {
return CONST_ConfigDir.'/'.$sSystemConfig;
}
return $sValue;
}
function fail($sError, $sUserError = false) function fail($sError, $sUserError = false)
{ {
if (!$sUserError) $sUserError = $sError; if (!$sUserError) {
$sUserError = $sError;
}
error_log('ERROR: '.$sError); error_log('ERROR: '.$sError);
var_dump($sUserError)."\n"; var_dump($sUserError);
echo "\n";
exit(-1); exit(-1);
} }
@@ -95,8 +84,9 @@ function getDatabaseDate(&$oDB)
function byImportance($a, $b) function byImportance($a, $b)
{ {
if ($a['importance'] != $b['importance']) if ($a['importance'] != $b['importance']) {
return ($a['importance'] > $b['importance']?-1:1); return ($a['importance'] > $b['importance']?-1:1);
}
return $a['foundorder'] <=> $b['foundorder']; return $a['foundorder'] <=> $b['foundorder'];
} }
@@ -231,6 +221,8 @@ function closestHouseNumber($aRow)
if (!function_exists('array_key_last')) { if (!function_exists('array_key_last')) {
function array_key_last(array $array) function array_key_last(array $array)
{ {
if (!empty($array)) return key(array_slice($array, -1, 1, true)); if (!empty($array)) {
return key(array_slice($array, -1, 1, true));
}
} }
} }

View File

@@ -5,15 +5,23 @@ function logStart(&$oDB, $sType = '', $sQuery = '', $aLanguageList = array())
{ {
$fStartTime = microtime(true); $fStartTime = microtime(true);
$aStartTime = explode('.', $fStartTime); $aStartTime = explode('.', $fStartTime);
if (!isset($aStartTime[1])) $aStartTime[1] = '0'; if (!isset($aStartTime[1])) {
$aStartTime[1] = '0';
}
$sOutputFormat = ''; $sOutputFormat = '';
if (isset($_GET['format'])) $sOutputFormat = $_GET['format']; if (isset($_GET['format'])) {
$sOutputFormat = $_GET['format'];
}
if ($sType == 'reverse') { if ($sType == 'reverse') {
$sOutQuery = (isset($_GET['lat'])?$_GET['lat']:'').'/'; $sOutQuery = (isset($_GET['lat'])?$_GET['lat']:'').'/';
if (isset($_GET['lon'])) $sOutQuery .= $_GET['lon']; if (isset($_GET['lon'])) {
if (isset($_GET['zoom'])) $sOutQuery .= '/'.$_GET['zoom']; $sOutQuery .= $_GET['lon'];
}
if (isset($_GET['zoom'])) {
$sOutQuery .= '/'.$_GET['zoom'];
}
} else { } else {
$sOutQuery = $sQuery; $sOutQuery = $sQuery;
} }
@@ -28,13 +36,15 @@ function logStart(&$oDB, $sType = '', $sQuery = '', $aLanguageList = array())
); );
if (CONST_Log_DB) { if (CONST_Log_DB) {
if (isset($_GET['email'])) if (isset($_GET['email'])) {
$sUserAgent = $_GET['email']; $sUserAgent = $_GET['email'];
elseif (isset($_SERVER['HTTP_REFERER'])) } elseif (isset($_SERVER['HTTP_REFERER'])) {
$sUserAgent = $_SERVER['HTTP_REFERER']; $sUserAgent = $_SERVER['HTTP_REFERER'];
elseif (isset($_SERVER['HTTP_USER_AGENT'])) } elseif (isset($_SERVER['HTTP_USER_AGENT'])) {
$sUserAgent = $_SERVER['HTTP_USER_AGENT']; $sUserAgent = $_SERVER['HTTP_USER_AGENT'];
else $sUserAgent = ''; } else {
$sUserAgent = '';
}
$sSQL = 'insert into new_query_log (type,starttime,query,ipaddress,useragent,language,format,searchterm)'; $sSQL = 'insert into new_query_log (type,starttime,query,ipaddress,useragent,language,format,searchterm)';
$sSQL .= ' values ('; $sSQL .= ' values (';
$sSQL .= join(',', $oDB->getDBQuotedList(array( $sSQL .= join(',', $oDB->getDBQuotedList(array(
@@ -60,7 +70,9 @@ function logEnd(&$oDB, $hLog, $iNumResults)
if (CONST_Log_DB) { if (CONST_Log_DB) {
$aEndTime = explode('.', $fEndTime); $aEndTime = explode('.', $fEndTime);
if (!$aEndTime[1]) $aEndTime[1] = '0'; if (!$aEndTime[1]) {
$aEndTime[1] = '0';
}
$sEndTime = date('Y-m-d H:i:s', $aEndTime[0]).'.'.$aEndTime[1]; $sEndTime = date('Y-m-d H:i:s', $aEndTime[0]).'.'.$aEndTime[1];
$sSQL = 'update new_query_log set endtime = '.$oDB->getDBQuoted($sEndTime).', results = '.$iNumResults; $sSQL = 'update new_query_log set endtime = '.$oDB->getDBQuoted($sEndTime).', results = '.$iNumResults;

View File

@@ -8,10 +8,12 @@ if (file_exists($phpPhraseSettingsFile) && !file_exists($jsonPhraseSettingsFile)
$data = array(); $data = array();
if (isset($aTagsBlacklist)) if (isset($aTagsBlacklist)) {
$data['blackList'] = $aTagsBlacklist; $data['blackList'] = $aTagsBlacklist;
if (isset($aTagsWhitelist)) }
if (isset($aTagsWhitelist)) {
$data['whiteList'] = $aTagsWhitelist; $data['whiteList'] = $aTagsWhitelist;
}
$jsonFile = fopen($jsonPhraseSettingsFile, 'w'); $jsonFile = fopen($jsonPhraseSettingsFile, 'w');
fwrite($jsonFile, json_encode($data)); fwrite($jsonFile, json_encode($data));

View File

@@ -3,14 +3,26 @@
function formatOSMType($sType, $bIncludeExternal = true) function formatOSMType($sType, $bIncludeExternal = true)
{ {
if ($sType == 'N') return 'node'; if ($sType == 'N') {
if ($sType == 'W') return 'way'; return 'node';
if ($sType == 'R') return 'relation'; }
if ($sType == 'W') {
return 'way';
}
if ($sType == 'R') {
return 'relation';
}
if (!$bIncludeExternal) return ''; if (!$bIncludeExternal) {
return '';
}
if ($sType == 'T') return 'way'; if ($sType == 'T') {
if ($sType == 'I') return 'way'; return 'way';
}
if ($sType == 'I') {
return 'way';
}
// not handled: P, L // not handled: P, L

View File

@@ -5,9 +5,11 @@
$aFilteredPlaces = array(); $aFilteredPlaces = array();
if (empty($aPlace)) { if (empty($aPlace)) {
if (isset($sError)) if (isset($sError)) {
$aFilteredPlaces['error'] = $sError; $aFilteredPlaces['error'] = $sError;
else $aFilteredPlaces['error'] = 'Unable to geocode'; } else {
$aFilteredPlaces['error'] = 'Unable to geocode';
}
javascript_renderData($aFilteredPlaces); javascript_renderData($aFilteredPlaces);
} else { } else {
$aFilteredPlaces = array( $aFilteredPlaces = array(
@@ -17,7 +19,9 @@ if (empty($aPlace)) {
) )
); );
if (isset($aPlace['place_id'])) $aFilteredPlaces['properties']['geocoding']['place_id'] = $aPlace['place_id']; if (isset($aPlace['place_id'])) {
$aFilteredPlaces['properties']['geocoding']['place_id'] = $aPlace['place_id'];
}
$sOSMType = formatOSMType($aPlace['osm_type']); $sOSMType = formatOSMType($aPlace['osm_type']);
if ($sOSMType) { if ($sOSMType) {
$aFilteredPlaces['properties']['geocoding']['osm_type'] = $sOSMType; $aFilteredPlaces['properties']['geocoding']['osm_type'] = $sOSMType;

View File

@@ -3,9 +3,11 @@
$aFilteredPlaces = array(); $aFilteredPlaces = array();
if (empty($aPlace)) { if (empty($aPlace)) {
if (isset($sError)) if (isset($sError)) {
$aFilteredPlaces['error'] = $sError; $aFilteredPlaces['error'] = $sError;
else $aFilteredPlaces['error'] = 'Unable to geocode'; } else {
$aFilteredPlaces['error'] = 'Unable to geocode';
}
javascript_renderData($aFilteredPlaces); javascript_renderData($aFilteredPlaces);
} else { } else {
$aFilteredPlaces = array( $aFilteredPlaces = array(
@@ -13,7 +15,9 @@ if (empty($aPlace)) {
'properties' => array() 'properties' => array()
); );
if (isset($aPlace['place_id'])) $aFilteredPlaces['properties']['place_id'] = $aPlace['place_id']; if (isset($aPlace['place_id'])) {
$aFilteredPlaces['properties']['place_id'] = $aPlace['place_id'];
}
$sOSMType = formatOSMType($aPlace['osm_type']); $sOSMType = formatOSMType($aPlace['osm_type']);
if ($sOSMType) { if ($sOSMType) {
$aFilteredPlaces['properties']['osm_type'] = $sOSMType; $aFilteredPlaces['properties']['osm_type'] = $sOSMType;
@@ -36,8 +40,12 @@ if (empty($aPlace)) {
if (isset($aPlace['address'])) { if (isset($aPlace['address'])) {
$aFilteredPlaces['properties']['address'] = $aPlace['address']->getAddressNames(); $aFilteredPlaces['properties']['address'] = $aPlace['address']->getAddressNames();
} }
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['properties']['extratags'] = $aPlace['sExtraTags']; if (isset($aPlace['sExtraTags'])) {
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['properties']['namedetails'] = $aPlace['sNameDetails']; $aFilteredPlaces['properties']['extratags'] = $aPlace['sExtraTags'];
}
if (isset($aPlace['sNameDetails'])) {
$aFilteredPlaces['properties']['namedetails'] = $aPlace['sNameDetails'];
}
if (isset($aPlace['aBoundingBox'])) { if (isset($aPlace['aBoundingBox'])) {
$aFilteredPlaces['bbox'] = array( $aFilteredPlaces['bbox'] = array(

View File

@@ -3,19 +3,27 @@
$aFilteredPlaces = array(); $aFilteredPlaces = array();
if (empty($aPlace)) { if (empty($aPlace)) {
if (isset($sError)) if (isset($sError)) {
$aFilteredPlaces['error'] = $sError; $aFilteredPlaces['error'] = $sError;
else $aFilteredPlaces['error'] = 'Unable to geocode'; } else {
$aFilteredPlaces['error'] = 'Unable to geocode';
}
} else { } else {
if (isset($aPlace['place_id'])) $aFilteredPlaces['place_id'] = $aPlace['place_id']; if (isset($aPlace['place_id'])) {
$aFilteredPlaces['place_id'] = $aPlace['place_id'];
}
$aFilteredPlaces['licence'] = 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright'; $aFilteredPlaces['licence'] = 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright';
$sOSMType = formatOSMType($aPlace['osm_type']); $sOSMType = formatOSMType($aPlace['osm_type']);
if ($sOSMType) { if ($sOSMType) {
$aFilteredPlaces['osm_type'] = $sOSMType; $aFilteredPlaces['osm_type'] = $sOSMType;
$aFilteredPlaces['osm_id'] = $aPlace['osm_id']; $aFilteredPlaces['osm_id'] = $aPlace['osm_id'];
} }
if (isset($aPlace['lat'])) $aFilteredPlaces['lat'] = $aPlace['lat']; if (isset($aPlace['lat'])) {
if (isset($aPlace['lon'])) $aFilteredPlaces['lon'] = $aPlace['lon']; $aFilteredPlaces['lat'] = $aPlace['lat'];
}
if (isset($aPlace['lon'])) {
$aFilteredPlaces['lon'] = $aPlace['lon'];
}
if ($sOutputFormat == 'jsonv2' || $sOutputFormat == 'geojson') { if ($sOutputFormat == 'jsonv2' || $sOutputFormat == 'geojson') {
$aFilteredPlaces['place_rank'] = $aPlace['rank_search']; $aFilteredPlaces['place_rank'] = $aPlace['rank_search'];
@@ -35,8 +43,12 @@ if (empty($aPlace)) {
if (isset($aPlace['address'])) { if (isset($aPlace['address'])) {
$aFilteredPlaces['address'] = $aPlace['address']->getAddressNames(); $aFilteredPlaces['address'] = $aPlace['address']->getAddressNames();
} }
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags']; if (isset($aPlace['sExtraTags'])) {
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails']; $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
}
if (isset($aPlace['sNameDetails'])) {
$aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
}
if (isset($aPlace['aBoundingBox'])) { if (isset($aPlace['aBoundingBox'])) {
$aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox']; $aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox'];

View File

@@ -12,17 +12,29 @@ echo " querystring='".htmlspecialchars($_SERVER['QUERY_STRING'], ENT_QUOTES)."'"
echo ">\n"; echo ">\n";
if (empty($aPlace)) { if (empty($aPlace)) {
if (isset($sError)) if (isset($sError)) {
echo "<error>$sError</error>"; echo "<error>$sError</error>";
else echo '<error>Unable to geocode</error>'; } else {
echo '<error>Unable to geocode</error>';
}
} else { } else {
echo '<result'; echo '<result';
if ($aPlace['place_id']) echo ' place_id="'.$aPlace['place_id'].'"'; if ($aPlace['place_id']) {
echo ' place_id="'.$aPlace['place_id'].'"';
}
$sOSMType = formatOSMType($aPlace['osm_type']); $sOSMType = formatOSMType($aPlace['osm_type']);
if ($sOSMType) echo ' osm_type="'.$sOSMType.'"'.' osm_id="'.$aPlace['osm_id'].'"'; if ($sOSMType) {
if ($aPlace['ref']) echo ' ref="'.htmlspecialchars($aPlace['ref']).'"'; echo ' osm_type="'.$sOSMType.'"'.' osm_id="'.$aPlace['osm_id'].'"';
if (isset($aPlace['lat'])) echo ' lat="'.htmlspecialchars($aPlace['lat']).'"'; }
if (isset($aPlace['lon'])) echo ' lon="'.htmlspecialchars($aPlace['lon']).'"'; if ($aPlace['ref']) {
echo ' ref="'.htmlspecialchars($aPlace['ref']).'"';
}
if (isset($aPlace['lat'])) {
echo ' lat="'.htmlspecialchars($aPlace['lat']).'"';
}
if (isset($aPlace['lon'])) {
echo ' lon="'.htmlspecialchars($aPlace['lon']).'"';
}
if (isset($aPlace['aBoundingBox'])) { if (isset($aPlace['aBoundingBox'])) {
echo ' boundingbox="'; echo ' boundingbox="';
echo join(',', $aPlace['aBoundingBox']); echo join(',', $aPlace['aBoundingBox']);

View File

@@ -43,29 +43,26 @@ $aPlaceDetails['centroid'] = array(
$aPlaceDetails['geometry'] = json_decode($aPointDetails['asgeojson']); $aPlaceDetails['geometry'] = json_decode($aPointDetails['asgeojson']);
$funcMapAddressLine = function ($aFull) { $funcMapAddressLine = function ($aFull) {
$aMapped = array( return array(
'localname' => $aFull['localname'], 'localname' => $aFull['localname'],
'place_id' => isset($aFull['place_id']) ? (int) $aFull['place_id'] : null, 'place_id' => isset($aFull['place_id']) ? (int) $aFull['place_id'] : null,
'osm_id' => isset($aFull['osm_id']) ? (int) $aFull['osm_id'] : null, 'osm_id' => isset($aFull['osm_id']) ? (int) $aFull['osm_id'] : null,
'osm_type' => isset($aFull['osm_type']) ? $aFull['osm_type'] : null, 'osm_type' => isset($aFull['osm_type']) ? $aFull['osm_type'] : null,
'place_type' => isset($aFull['place_type']) ? $aFull['place_type'] : null, 'place_type' => isset($aFull['place_type']) ? $aFull['place_type'] : null,
'class' => $aFull['class'], 'class' => $aFull['class'],
'type' => $aFull['type'], 'type' => $aFull['type'],
'admin_level' => isset($aFull['admin_level']) ? (int) $aFull['admin_level'] : null, 'admin_level' => isset($aFull['admin_level']) ? (int) $aFull['admin_level'] : null,
'rank_address' => $aFull['rank_address'] ? (int) $aFull['rank_address'] : null, 'rank_address' => $aFull['rank_address'] ? (int) $aFull['rank_address'] : null,
'distance' => (float) $aFull['distance'], 'distance' => (float) $aFull['distance'],
'isaddress' => isset($aFull['isaddress']) ? (bool) $aFull['isaddress'] : null 'isaddress' => isset($aFull['isaddress']) ? (bool) $aFull['isaddress'] : null
); );
return $aMapped;
}; };
$funcMapKeyword = function ($aFull) { $funcMapKeyword = function ($aFull) {
$aMapped = array( return array(
'id' => (int) $aFull['word_id'], 'id' => (int) $aFull['word_id'],
'token' => $aFull['word_token'] 'token' => $aFull['word_token']
); );
return $aMapped;
}; };
if ($aAddressLines) { if ($aAddressLines) {
@@ -96,11 +93,15 @@ if ($bIncludeHierarchy) {
if ($bGroupHierarchy) { if ($bGroupHierarchy) {
$aPlaceDetails['hierarchy'] = array(); $aPlaceDetails['hierarchy'] = array();
foreach ($aHierarchyLines as $aAddressLine) { foreach ($aHierarchyLines as $aAddressLine) {
if ($aAddressLine['type'] == 'yes') $sType = $aAddressLine['class']; if ($aAddressLine['type'] == 'yes') {
else $sType = $aAddressLine['type']; $sType = $aAddressLine['class'];
} else {
$sType = $aAddressLine['type'];
}
if (!isset($aPlaceDetails['hierarchy'][$sType])) if (!isset($aPlaceDetails['hierarchy'][$sType])) {
$aPlaceDetails['hierarchy'][$sType] = array(); $aPlaceDetails['hierarchy'][$sType] = array();
}
$aPlaceDetails['hierarchy'][$sType][] = $funcMapAddressLine($aAddressLine); $aPlaceDetails['hierarchy'][$sType][] = $funcMapAddressLine($aAddressLine);
} }
} else { } else {

View File

@@ -8,4 +8,4 @@
$error['details'] = $exception->getFile() . '('. $exception->getLine() . ')'; $error['details'] = $exception->getFile() . '('. $exception->getLine() . ')';
} }
echo javascript_renderData(array('error' => $error)); javascript_renderData(array('error' => $error));

View File

@@ -5,7 +5,9 @@ $aOutput['licence'] = 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm
$aOutput['batch'] = array(); $aOutput['batch'] = array();
foreach ($aBatchResults as $aSearchResults) { foreach ($aBatchResults as $aSearchResults) {
if (!$aSearchResults) $aSearchResults = array(); if (!$aSearchResults) {
$aSearchResults = array();
}
$aFilteredPlaces = array(); $aFilteredPlaces = array();
foreach ($aSearchResults as $iResNum => $aPointDetails) { foreach ($aSearchResults as $iResNum => $aPointDetails) {
$aPlace = array( $aPlace = array(

View File

@@ -9,7 +9,9 @@ foreach ($aSearchResults as $iResNum => $aPointDetails) {
) )
); );
if (isset($aPointDetails['place_id'])) $aPlace['properties']['geocoding']['place_id'] = $aPointDetails['place_id']; if (isset($aPointDetails['place_id'])) {
$aPlace['properties']['geocoding']['place_id'] = $aPointDetails['place_id'];
}
$sOSMType = formatOSMType($aPointDetails['osm_type']); $sOSMType = formatOSMType($aPointDetails['osm_type']);
if ($sOSMType) { if ($sOSMType) {
$aPlace['properties']['geocoding']['osm_type'] = $sOSMType; $aPlace['properties']['geocoding']['osm_type'] = $sOSMType;

View File

@@ -58,8 +58,12 @@ foreach ($aSearchResults as $iResNum => $aPointDetails) {
} }
if (isset($aPointDetails['sExtraTags'])) $aPlace['properties']['extratags'] = $aPointDetails['sExtraTags']; if (isset($aPointDetails['sExtraTags'])) {
if (isset($aPointDetails['sNameDetails'])) $aPlace['properties']['namedetails'] = $aPointDetails['sNameDetails']; $aPlace['properties']['extratags'] = $aPointDetails['sExtraTags'];
}
if (isset($aPointDetails['sNameDetails'])) {
$aPlace['properties']['namedetails'] = $aPointDetails['sNameDetails'];
}
$aFilteredPlaces[] = $aPlace; $aFilteredPlaces[] = $aPlace;
} }

View File

@@ -60,8 +60,12 @@ foreach ($aSearchResults as $iResNum => $aPointDetails) {
$aPlace['geokml'] = $aPointDetails['askml']; $aPlace['geokml'] = $aPointDetails['askml'];
} }
if (isset($aPointDetails['sExtraTags'])) $aPlace['extratags'] = $aPointDetails['sExtraTags']; if (isset($aPointDetails['sExtraTags'])) {
if (isset($aPointDetails['sNameDetails'])) $aPlace['namedetails'] = $aPointDetails['sNameDetails']; $aPlace['extratags'] = $aPointDetails['sExtraTags'];
}
if (isset($aPointDetails['sNameDetails'])) {
$aPlace['namedetails'] = $aPointDetails['sNameDetails'];
}
$aFilteredPlaces[] = $aPlace; $aFilteredPlaces[] = $aPlace;
} }

View File

@@ -10,7 +10,9 @@ echo (isset($sXmlRootTag)?$sXmlRootTag:'searchresults');
echo " timestamp='".date(DATE_RFC822)."'"; echo " timestamp='".date(DATE_RFC822)."'";
echo " attribution='Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright'"; echo " attribution='Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright'";
echo " querystring='".htmlspecialchars($sQuery, ENT_QUOTES)."'"; echo " querystring='".htmlspecialchars($sQuery, ENT_QUOTES)."'";
if (isset($aMoreParams['viewbox'])) echo " viewbox='".htmlspecialchars($aMoreParams['viewbox'], ENT_QUOTES)."'"; if (isset($aMoreParams['viewbox'])) {
echo " viewbox='".htmlspecialchars($aMoreParams['viewbox'], ENT_QUOTES)."'";
}
if (isset($aMoreParams['exclude_place_ids'])) { if (isset($aMoreParams['exclude_place_ids'])) {
echo " exclude_place_ids='".htmlspecialchars($aMoreParams['exclude_place_ids'])."'"; echo " exclude_place_ids='".htmlspecialchars($aMoreParams['exclude_place_ids'])."'";
} }

View File

@@ -105,7 +105,7 @@ class Tokenizer
// now compute all possible tokens // now compute all possible tokens
$aWordLists = array(); $aWordLists = array();
$aTokens = array(); $aTokens = array();
foreach ($aNormPhrases as $sTitle => $sPhrase) { foreach ($aNormPhrases as $sPhrase) {
if (strlen($sPhrase) > 0) { if (strlen($sPhrase) > 0) {
$aWords = explode(' ', $sPhrase); $aWords = explode(' ', $sPhrase);
Tokenizer::addTokens($aTokens, $aWords); Tokenizer::addTokens($aTokens, $aWords);

View File

@@ -95,16 +95,22 @@ $iPlaceID = (int)$sPlaceId;
if (CONST_Use_US_Tiger_Data) { if (CONST_Use_US_Tiger_Data) {
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_tiger WHERE place_id = '.$iPlaceID); $iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_tiger WHERE place_id = '.$iPlaceID);
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID; if ($iParentPlaceID) {
$iPlaceID = $iParentPlaceID;
}
} }
// interpolated house numbers // interpolated house numbers
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_osmline WHERE place_id = '.$iPlaceID); $iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_osmline WHERE place_id = '.$iPlaceID);
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID; if ($iParentPlaceID) {
$iPlaceID = $iParentPlaceID;
}
// artificial postcodes // artificial postcodes
$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_postcode WHERE place_id = '.$iPlaceID); $iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_postcode WHERE place_id = '.$iPlaceID);
if ($iParentPlaceID) $iPlaceID = $iParentPlaceID; if ($iParentPlaceID) {
$iPlaceID = $iParentPlaceID;
}
$hLog = logStart($oDB, 'details', $_SERVER['QUERY_STRING'], $aLangPrefOrder); $hLog = logStart($oDB, 'details', $_SERVER['QUERY_STRING'], $aLangPrefOrder);

View File

@@ -35,7 +35,9 @@ if (count($aOsmIds) > CONST_Places_Max_ID_count) {
foreach ($aOsmIds as $sItem) { foreach ($aOsmIds as $sItem) {
// Skip empty sItem // Skip empty sItem
if (empty($sItem)) continue; if (empty($sItem)) {
continue;
}
$sType = $sItem[0]; $sType = $sItem[0];
$iId = (int) substr($sItem, 1); $iId = (int) substr($sItem, 1);
@@ -48,7 +50,9 @@ foreach ($aOsmIds as $sItem) {
// key names // key names
$oResult = $oPlace; $oResult = $oPlace;
unset($oResult['aAddress']); unset($oResult['aAddress']);
if (isset($oPlace['aAddress'])) $oResult['address'] = $oPlace['aAddress']; if (isset($oPlace['aAddress'])) {
$oResult['address'] = $oPlace['aAddress'];
}
if ($sOutputFormat != 'geocodejson') { if ($sOutputFormat != 'geocodejson') {
unset($oResult['langaddress']); unset($oResult['langaddress']);
$oResult['name'] = $oPlace['langaddress']; $oResult['name'] = $oPlace['langaddress'];
@@ -71,7 +75,9 @@ foreach ($aOsmIds as $sItem) {
} }
if (CONST_Debug) exit; if (CONST_Debug) {
exit;
}
$sXmlRootTag = 'lookupresults'; $sXmlRootTag = 'lookupresults';
$sQuery = join(',', $aCleanedQueryParts); $sQuery = join(',', $aCleanedQueryParts);

View File

@@ -30,8 +30,12 @@ while ($iTotalBroken && empty($aPolygons)) {
$iDays++; $iDays++;
} }
if ($bReduced) $aWhere[] = "errormessage like 'Area reduced%'"; if ($bReduced) {
if ($sClass) $sWhere[] = "class = '".pg_escape_string($sClass)."'"; $aWhere[] = "errormessage like 'Area reduced%'";
}
if ($sClass) {
$sWhere[] = "class = '".pg_escape_string($sClass)."'";
}
if (!empty($aWhere)) { if (!empty($aWhere)) {
$sSQL .= ' WHERE '.join(' and ', $aWhere); $sSQL .= ' WHERE '.join(' and ', $aWhere);

View File

@@ -77,7 +77,9 @@ if (isset($_SERVER['REQUEST_SCHEME'])
$sMoreURL = '/search.php?'.http_build_query($aMoreParams); $sMoreURL = '/search.php?'.http_build_query($aMoreParams);
} }
if (CONST_Debug) exit; if (CONST_Debug) {
exit;
}
$sOutputTemplate = ($sOutputFormat == 'jsonv2') ? 'json' : $sOutputFormat; $sOutputTemplate = ($sOutputFormat == 'jsonv2') ? 'json' : $sOutputFormat;
include(CONST_LibDir.'/template/search-'.$sOutputTemplate.'.php'); include(CONST_LibDir.'/template/search-'.$sOutputTemplate.'.php');

View File

@@ -33,18 +33,17 @@ class DeadlockHandler:
self.ignore_sql_errors = ignore_sql_errors self.ignore_sql_errors = ignore_sql_errors
def __enter__(self): def __enter__(self):
pass return self
def __exit__(self, exc_type, exc_value, traceback): def __exit__(self, exc_type, exc_value, traceback):
if __has_psycopg2_errors__: if __has_psycopg2_errors__:
if exc_type == psycopg2.errors.DeadlockDetected: # pylint: disable=E1101 if exc_type == psycopg2.errors.DeadlockDetected: # pylint: disable=E1101
self.handler() self.handler()
return True return True
else: elif exc_type == psycopg2.extensions.TransactionRollbackError \
if exc_type == psycopg2.extensions.TransactionRollbackError: and exc_value.pgcode == '40P01':
if exc_value.pgcode == '40P01': self.handler()
self.handler() return True
return True
if self.ignore_sql_errors and isinstance(exc_value, psycopg2.Error): if self.ignore_sql_errors and isinstance(exc_value, psycopg2.Error):
LOG.info("SQL error ignored: %s", exc_value) LOG.info("SQL error ignored: %s", exc_value)
@@ -191,10 +190,7 @@ class WorkerPool:
yield thread yield thread
if command_stat > self.REOPEN_CONNECTIONS_AFTER: if command_stat > self.REOPEN_CONNECTIONS_AFTER:
for thread in self.threads: self._reconnect_threads()
while not thread.is_done():
thread.wait()
thread.connect()
ready = self.threads ready = self.threads
command_stat = 0 command_stat = 0
else: else:
@@ -203,6 +199,13 @@ class WorkerPool:
self.wait_time += time.time() - tstart self.wait_time += time.time() - tstart
def _reconnect_threads(self):
for thread in self.threads:
while not thread.is_done():
thread.wait()
thread.connect()
def __enter__(self): def __enter__(self):
return self return self

View File

@@ -92,7 +92,7 @@ class Indexer:
def index_full(self, analyse=True): def index_full(self, analyse=True):
""" Index the complete database. This will first index boudnaries """ Index the complete database. This will first index boundaries
followed by all other objects. When `analyse` is True, then the followed by all other objects. When `analyse` is True, then the
database will be analysed at the appropriate places to database will be analysed at the appropriate places to
ensure that database statistics are updated. ensure that database statistics are updated.
@@ -100,13 +100,10 @@ class Indexer:
with connect(self.dsn) as conn: with connect(self.dsn) as conn:
conn.autocommit = True conn.autocommit = True
if analyse: def _analyze():
def _analyze(): if analyse:
with conn.cursor() as cur: with conn.cursor() as cur:
cur.execute('ANALYZE') cur.execute('ANALYZE')
else:
def _analyze():
pass
self.index_by_rank(0, 4) self.index_by_rank(0, 4)
_analyze() _analyze()

View File

@@ -119,18 +119,22 @@ class ICUNameProcessor:
pos += 1 pos += 1
force_space = False force_space = False
results = set() # No variants detected? Fast return.
if startpos == 0: if startpos == 0:
trans_name = self.to_ascii.transliterate(norm_name).strip() trans_name = self.to_ascii.transliterate(norm_name).strip()
return [trans_name] if trans_name else []
return self._compute_result_set(partials, baseform[startpos:])
def _compute_result_set(self, partials, prefix):
results = set()
for variant in partials:
vname = variant + prefix
trans_name = self.to_ascii.transliterate(vname[1:-1]).strip()
if trans_name: if trans_name:
results.add(trans_name) results.add(trans_name)
else:
for variant in partials:
name = variant + baseform[startpos:]
trans_name = self.to_ascii.transliterate(name[1:-1]).strip()
if trans_name:
results.add(trans_name)
return list(results) return list(results)

View File

@@ -411,33 +411,36 @@ class LegacyICUNameAnalyzer:
self.add_country_names(country_feature.lower(), names) self.add_country_names(country_feature.lower(), names)
address = place.get('address') address = place.get('address')
if address: if address:
hnrs = [] self._process_place_address(token_info, address)
addr_terms = []
for key, value in address.items():
if key == 'postcode':
self._add_postcode(value)
elif key in ('housenumber', 'streetnumber', 'conscriptionnumber'):
hnrs.append(value)
elif key == 'street':
token_info.add_street(*self._compute_name_tokens({'name': value}))
elif key == 'place':
token_info.add_place(*self._compute_name_tokens({'name': value}))
elif not key.startswith('_') and \
key not in ('country', 'full'):
addr_terms.append((key, *self._compute_name_tokens({'name': value})))
if hnrs:
hnrs = self._split_housenumbers(hnrs)
token_info.add_housenumbers(self.conn, [self._make_standard_hnr(n) for n in hnrs])
if addr_terms:
token_info.add_address_terms(addr_terms)
return token_info.data return token_info.data
def _process_place_address(self, token_info, address):
hnrs = []
addr_terms = []
for key, value in address.items():
if key == 'postcode':
self._add_postcode(value)
elif key in ('housenumber', 'streetnumber', 'conscriptionnumber'):
hnrs.append(value)
elif key == 'street':
token_info.add_street(*self._compute_name_tokens({'name': value}))
elif key == 'place':
token_info.add_place(*self._compute_name_tokens({'name': value}))
elif not key.startswith('_') and \
key not in ('country', 'full'):
addr_terms.append((key, *self._compute_name_tokens({'name': value})))
if hnrs:
hnrs = self._split_housenumbers(hnrs)
token_info.add_housenumbers(self.conn, [self._make_standard_hnr(n) for n in hnrs])
if addr_terms:
token_info.add_address_terms(addr_terms)
def _compute_name_tokens(self, names): def _compute_name_tokens(self, names):
""" Computes the full name and partial name tokens for the given """ Computes the full name and partial name tokens for the given
dictionary of names. dictionary of names.

View File

@@ -424,37 +424,37 @@ class LegacyNameAnalyzer:
self.add_country_names(country_feature.lower(), names) self.add_country_names(country_feature.lower(), names)
address = place.get('address') address = place.get('address')
if address: if address:
hnrs = [] self._process_place_address(token_info, address)
addr_terms = []
for key, value in address.items():
if key == 'postcode':
self._add_postcode(value)
elif key in ('housenumber', 'streetnumber', 'conscriptionnumber'):
hnrs.append(value)
elif key == 'street':
token_info.add_street(self.conn, value)
elif key == 'place':
token_info.add_place(self.conn, value)
elif not key.startswith('_') and \
key not in ('country', 'full'):
addr_terms.append((key, value))
if hnrs:
token_info.add_housenumbers(self.conn, hnrs)
if addr_terms:
token_info.add_address_terms(self.conn, addr_terms)
return token_info.data return token_info.data
def _add_postcode(self, postcode): def _process_place_address(self, token_info, address):
""" Make sure the normalized postcode is present in the word table. hnrs = []
""" addr_terms = []
if re.search(r'[:,;]', postcode) is None:
self._cache.add_postcode(self.conn, self.normalize_postcode(postcode)) for key, value in address.items():
if key == 'postcode':
# Make sure the normalized postcode is present in the word table.
if re.search(r'[:,;]', value) is None:
self._cache.add_postcode(self.conn,
self.normalize_postcode(value))
elif key in ('housenumber', 'streetnumber', 'conscriptionnumber'):
hnrs.append(value)
elif key == 'street':
token_info.add_street(self.conn, value)
elif key == 'place':
token_info.add_place(self.conn, value)
elif not key.startswith('_') and key not in ('country', 'full'):
addr_terms.append((key, value))
if hnrs:
token_info.add_housenumbers(self.conn, hnrs)
if addr_terms:
token_info.add_address_terms(self.conn, addr_terms)
class _TokenInfo: class _TokenInfo:

View File

@@ -130,9 +130,8 @@ def import_osm_data(osm_file, options, drop=False, ignore_errors=False):
if drop: if drop:
conn.drop_table('planet_osm_nodes') conn.drop_table('planet_osm_nodes')
if drop: if drop and options['flatnode_file']:
if options['flatnode_file']: Path(options['flatnode_file']).unlink()
Path(options['flatnode_file']).unlink()
def create_tables(conn, config, reverse_only=False): def create_tables(conn, config, reverse_only=False):

View File

@@ -155,6 +155,20 @@ def recompute_importance(conn):
conn.commit() conn.commit()
def _quote_php_variable(var_type, config, conf_name):
if var_type == bool:
return 'true' if config.get_bool(conf_name) else 'false'
if var_type == int:
return getattr(config, conf_name)
if not getattr(config, conf_name):
return 'false'
quoted = getattr(config, conf_name).replace("'", "\\'")
return f"'{quoted}'"
def setup_website(basedir, config, conn): def setup_website(basedir, config, conn):
""" Create the website script stubs. """ Create the website script stubs.
""" """
@@ -174,18 +188,11 @@ def setup_website(basedir, config, conn):
config.project_dir / 'tokenizer')) config.project_dir / 'tokenizer'))
for php_name, conf_name, var_type in PHP_CONST_DEFS: for php_name, conf_name, var_type in PHP_CONST_DEFS:
if var_type == bool: varout = _quote_php_variable(var_type, config, conf_name)
varout = 'true' if config.get_bool(conf_name) else 'false'
elif var_type == int:
varout = getattr(config, conf_name)
elif not getattr(config, conf_name):
varout = 'false'
else:
varout = "'{}'".format(getattr(config, conf_name).replace("'", "\\'"))
template += "@define('CONST_{}', {});\n".format(php_name, varout) template += f"@define('CONST_{php_name}', {varout});\n"
template += "\nrequire_once('{}/website/{{}}');\n".format(config.lib_dir.php) template += f"\nrequire_once('{config.lib_dir.php}/website/{{}}');\n"
search_name_table_exists = bool(conn and conn.table_exists('search_name')) search_name_table_exists = bool(conn and conn.table_exists('search_name'))

View File

@@ -20,6 +20,12 @@ from nominatim.errors import UsageError
from nominatim.tools.special_phrases.importer_statistics import SpecialPhrasesImporterStatistics from nominatim.tools.special_phrases.importer_statistics import SpecialPhrasesImporterStatistics
LOG = logging.getLogger() LOG = logging.getLogger()
def _classtype_table(phrase_class, phrase_type):
""" Return the name of the table for the given class and type.
"""
return f'place_classtype_{phrase_class}_{phrase_type}'
class SPImporter(): class SPImporter():
# pylint: disable-msg=too-many-instance-attributes # pylint: disable-msg=too-many-instance-attributes
""" """
@@ -164,7 +170,7 @@ class SPImporter():
phrase_class = pair[0] phrase_class = pair[0]
phrase_type = pair[1] phrase_type = pair[1]
table_name = 'place_classtype_{}_{}'.format(phrase_class, phrase_type) table_name = _classtype_table(phrase_class, phrase_type)
if table_name in self.table_phrases_to_delete: if table_name in self.table_phrases_to_delete:
self.statistics_handler.notify_one_table_ignored() self.statistics_handler.notify_one_table_ignored()
@@ -193,7 +199,7 @@ class SPImporter():
""" """
Create table place_classtype of the given phrase_class/phrase_type if doesn't exit. Create table place_classtype of the given phrase_class/phrase_type if doesn't exit.
""" """
table_name = 'place_classtype_{}_{}'.format(phrase_class, phrase_type) table_name = _classtype_table(phrase_class, phrase_type)
with self.db_connection.cursor() as db_cursor: with self.db_connection.cursor() as db_cursor:
db_cursor.execute(SQL(""" db_cursor.execute(SQL("""
CREATE TABLE IF NOT EXISTS {{}} {} CREATE TABLE IF NOT EXISTS {{}} {}
@@ -208,7 +214,7 @@ class SPImporter():
Create indexes on centroid and place_id for the place_classtype table. Create indexes on centroid and place_id for the place_classtype table.
""" """
index_prefix = 'idx_place_classtype_{}_{}_'.format(phrase_class, phrase_type) index_prefix = 'idx_place_classtype_{}_{}_'.format(phrase_class, phrase_type)
base_table = 'place_classtype_{}_{}'.format(phrase_class, phrase_type) base_table = _classtype_table(phrase_class, phrase_type)
#Index on centroid #Index on centroid
if not self.db_connection.index_exists(index_prefix + 'centroid'): if not self.db_connection.index_exists(index_prefix + 'centroid'):
with self.db_connection.cursor() as db_cursor: with self.db_connection.cursor() as db_cursor:
@@ -230,7 +236,7 @@ class SPImporter():
""" """
Grant access on read to the table place_classtype for the webuser. Grant access on read to the table place_classtype for the webuser.
""" """
table_name = 'place_classtype_{}_{}'.format(phrase_class, phrase_type) table_name = _classtype_table(phrase_class, phrase_type)
with self.db_connection.cursor() as db_cursor: with self.db_connection.cursor() as db_cursor:
db_cursor.execute(SQL("""GRANT SELECT ON {} TO {}""") db_cursor.execute(SQL("""GRANT SELECT ON {} TO {}""")
.format(Identifier(table_name), .format(Identifier(table_name),
@@ -274,9 +280,8 @@ class SPImporter():
(self.phplib_dir / 'migration/PhraseSettingsToJson.php').resolve(), (self.phplib_dir / 'migration/PhraseSettingsToJson.php').resolve(),
file_path], check=True) file_path], check=True)
LOG.warning('special_phrase configuration file has been converted to json.') LOG.warning('special_phrase configuration file has been converted to json.')
return json_file_path
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
LOG.error('Error while converting %s to json.', file_path) LOG.error('Error while converting %s to json.', file_path)
raise raise
else:
return json_file_path return json_file_path