- if [[ $TEST_SUITE == "monaco" ]]; then ./utils/specialphrases.php --wiki-import | psql -d test_api_nominatim >/dev/null; fi
- cd $TRAVIS_BUILD_DIR/test/php
- if [[ $TEST_SUITE == "tests" ]]; then phpunit ./ ; fi
- - if [[ $TEST_SUITE == "tests" ]]; then phpcs --report-width=120 */**.php ; fi
+ - if [[ $TEST_SUITE == "tests" ]]; then phpcs --report-width=120 . ; fi
- cd $TRAVIS_BUILD_DIR/test/bdd
- # behave --format=progress3 api
- if [[ $TEST_SUITE == "tests" ]]; then behave --format=progress3 db ; fi
## Workflow for Pull Requests
-We love to get pull reuqests from you. We operate the "Fork & Pull" model
+We love to get pull requests from you. We operate the "Fork & Pull" model
explained at
https://help.github.com/articles/using-pull-requests
## Coding style
Nominatim historically hasn't followed a particular coding style but we
-are in process of consolodating the style. The following rules apply:
+are in process of consolidating the style. The following rules apply:
* Python code uses the official Python style
* indention
The coding style is enforced with PHPCS and can be tested with:
```
- phpcs --report-width=120 --colors */**.php
+ phpcs --report-width=120 --colors .
```
## Testing
ADD_CUSTOM_TARGET(doc
COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/admin ${CMAKE_CURRENT_BINARY_DIR}/admin
+ COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/develop ${CMAKE_CURRENT_BINARY_DIR}/develop
COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/index.md ${CMAKE_CURRENT_BINARY_DIR}/index.md
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bash2md.sh ${PROJECT_SOURCE_DIR}/vagrant/Install-on-Centos-7.sh ${CMAKE_CURRENT_BINARY_DIR}/appendix/Install-on-Centos-7.md
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bash2md.sh ${PROJECT_SOURCE_DIR}/vagrant/Install-on-Ubuntu-16.sh ${CMAKE_CURRENT_BINARY_DIR}/appendix/Install-on-Ubuntu-16.md
These OS-specific instructions can also be found in executable form
in the `vagrant/` directory.
+Users have created instructions for other frameworks. We haven't tested those
+and can't offer support.
+
+ * [Docker](https://github.com/mediagis/nominatim-docker)
+ * [Docker on Kubernetes](https://github.com/peter-evans/nominatim-k8s)
+ * [Ansible](https://github.com/synthesio/infra-ansible-nominatim)
+
# Prerequisites
## Software
--- /dev/null
+# Basic Architecture
+
+Nominatim provides geocoding based on OpenStreetMap data. It uses a Postgresql
+database as a backend for storing the data.
+
+There are three basic parts to Nominatim's architecture: the data import,
+the address computation and the search frontend.
+
+The __data import__ stage reads the raw OSM data and extracts all information
+that is useful for geocoding. This part is done by osm2pgsql, the same tool
+that can also be used to import a rendering database. It uses the special
+gazetteer output plugin in `osm2pgsql/output-gazetter.[ch]pp`. The result of
+the import can be found in the database table `place`.
+
+The __address computation__ or __indexing__ stage takes the data from `place`
+and adds additional information needed for geocoding. It ranks the places by
+importance, links objects that belong together and computes addresses and
+the search index. Most of this work is done in Pl/pqSQL via database triggers
+and can be found in the file `sql/functions.sql`.
+
+The __search frontend__ implements the actual API. It takes queries for
+search and reverse geocoding queries from the user, looks up the data and
+returns the results in the requested format. This part is written in PHP
+and can be found in the `lib/` and `website/` directories.
- 'Importing and Updating' : 'admin/Import-and-Update.md'
- 'Migration from older Versions' : 'admin/Migration.md'
- 'Troubleshooting' : 'admin/Faq.md'
+ - 'Developers Guide':
+ - 'Overview' : 'develop/overview.md'
- 'Appendix':
- 'Installation on CentOS 7' : 'appendix/Install-on-Centos-7.md'
- 'Installation on Ubuntu 16' : 'appendix/Install-on-Ubuntu-16.md'
$aResult['importance'] = 0.001;
$aResult['foundorder'] = $aResult['addressimportance'];
} else {
- // Adjust importance for the number of exact string matches in the result
+ $aResult['importance'] = max(0.001, $aResult['importance']);
$aResult['importance'] *= $this->viewboxImportanceFactor(
$aResult['lon'],
$aResult['lat']
);
- $aResult['importance'] = max(0.001, $aResult['importance']);
+ // Adjust importance for the number of exact string matches in the result
$iCountWords = 0;
$sAddress = $aResult['langaddress'];
foreach ($aRecheckWords as $i => $sWord) {
&& $sPhraseType != 'country'
) {
$iWordID = $aSearchTerm['word_id'];
- if (sizeof($this->aName)) {
- if (($sPhraseType == '' || !$bFirstPhrase)
- && $sPhraseType != 'country'
- && !$bHasPartial
- ) {
+ // Full words can only be a name if they appear at the beginning
+ // of the phrase. In structured search the name must forcably in
+ // the first phrase. In unstructured search it may be in a later
+ // phrase when the first phrase is a house number.
+ if (sizeof($this->aName) || !($bFirstPhrase || $sPhraseType == '')) {
+ if (($sPhraseType == '' || !$bFirstPhrase) && !$bHasPartial) {
$oSearch = clone $this;
$oSearch->iSearchRank++;
$oSearch->aAddress[$iWordID] = $iWordID;
if ($this->sHouseNumber) {
$sImportanceSQL = '- abs(26 - address_rank) + 3';
} else {
- $sImportanceSQL = '(CASE WHEN importance = 0 OR importance IS NULL THEN 0.75-(search_rank::float/40) ELSE importance END)';
+ $sImportanceSQL = '(CASE WHEN importance = 0 OR importance IS NULL THEN 0.75001-(search_rank::float/40) ELSE importance END)';
}
$sImportanceSQL .= $this->oContext->viewboxImportanceSQL('centroid');
$aOrder[] = "$sImportanceSQL DESC";
$aFilteredPlaces = array();
-if (!sizeof($aPlace))
-{
+if (!sizeof($aPlace)) {
if (isset($sError))
$aFilteredPlaces['error'] = $sError;
- else
- $aFilteredPlaces['error'] = 'Unable to geocode';
-}
-else
-{
+ else $aFilteredPlaces['error'] = 'Unable to geocode';
+} else {
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']);
- if ($sOSMType)
- {
+ if ($sOSMType) {
$aFilteredPlaces['osm_type'] = $sOSMType;
$aFilteredPlaces['osm_id'] = $aPlace['osm_id'];
}
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
- if (isset($aPlace['aBoundingBox']))
- {
+ if (isset($aPlace['aBoundingBox'])) {
$aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox'];
}
- if (isset($aPlace['asgeojson']))
- {
+ if (isset($aPlace['asgeojson'])) {
$aFilteredPlaces['geojson'] = json_decode($aPlace['asgeojson']);
}
- if (isset($aPlace['assvg']))
- {
+ if (isset($aPlace['assvg'])) {
$aFilteredPlaces['svg'] = $aPlace['assvg'];
}
- if (isset($aPlace['astext']))
- {
+ if (isset($aPlace['astext'])) {
$aFilteredPlaces['geotext'] = $aPlace['astext'];
}
- if (isset($aPlace['askml']))
- {
+ if (isset($aPlace['askml'])) {
$aFilteredPlaces['geokml'] = $aPlace['askml'];
}
}
javascript_renderData($aFilteredPlaces);
-
$aFilteredPlaces = array();
-if (!sizeof($aPlace))
-{
+if (!sizeof($aPlace)) {
if (isset($sError))
$aFilteredPlaces['error'] = $sError;
- else
- $aFilteredPlaces['error'] = 'Unable to geocode';
-}
-else
-{
+ else $aFilteredPlaces['error'] = 'Unable to geocode';
+} else {
if ($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']);
- if ($sOSMType)
- {
+ if ($sOSMType) {
$aFilteredPlaces['osm_type'] = $sOSMType;
$aFilteredPlaces['osm_id'] = $aPlace['osm_id'];
}
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
- if (isset($aPlace['aBoundingBox']))
- {
+ if (isset($aPlace['aBoundingBox'])) {
$aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox'];
}
- if (isset($aPlace['asgeojson']))
- {
+ if (isset($aPlace['asgeojson'])) {
$aFilteredPlaces['geojson'] = json_decode($aPlace['asgeojson']);
}
- if (isset($aPlace['assvg']))
- {
+ if (isset($aPlace['assvg'])) {
$aFilteredPlaces['svg'] = $aPlace['assvg'];
}
- if (isset($aPlace['astext']))
- {
+ if (isset($aPlace['astext'])) {
$aFilteredPlaces['geotext'] = $aPlace['astext'];
}
- if (isset($aPlace['askml']))
- {
+ if (isset($aPlace['askml'])) {
$aFilteredPlaces['geokml'] = $aPlace['askml'];
}
-
}
javascript_renderData($aFilteredPlaces);
<?php
-header("content-type: text/xml; charset=UTF-8");
+header('content-type: text/xml; charset=UTF-8');
-echo "<";
-echo "?xml version=\"1.0\" encoding=\"UTF-8\" ?";
+echo '<';
+echo '?xml version="1.0" encoding="UTF-8" ?';
echo ">\n";
-echo "<reversegeocode";
+echo '<reversegeocode';
echo " timestamp='".date(DATE_RFC822)."'";
echo " attribution='Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright'";
echo " querystring='".htmlspecialchars($_SERVER['QUERY_STRING'], ENT_QUOTES)."'";
echo ">\n";
-if (!sizeof($aPlace))
-{
+if (!sizeof($aPlace)) {
if (isset($sError))
echo "<error>$sError</error>";
- else
- echo "<error>Unable to geocode</error>";
-}
-else
-{
- echo "<result";
+ else echo '<error>Unable to geocode</error>';
+} else {
+ echo '<result';
if ($aPlace['place_id']) echo ' place_id="'.$aPlace['place_id'].'"';
$sOSMType = formatOSMType($aPlace['osm_type']);
if ($sOSMType) echo ' osm_type="'.$sOSMType.'"'.' osm_id="'.$aPlace['osm_id'].'"';
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 join(',', $aPlace['aBoundingBox']);
echo '"';
}
- if (isset($aPlace['asgeojson']))
- {
+ if (isset($aPlace['asgeojson'])) {
echo ' geojson=\'';
echo $aPlace['asgeojson'];
echo '\'';
}
- if (isset($aPlace['assvg']))
- {
+ if (isset($aPlace['assvg'])) {
echo ' geosvg=\'';
echo $aPlace['assvg'];
echo '\'';
}
- if (isset($aPlace['astext']))
- {
+ if (isset($aPlace['astext'])) {
echo ' geotext=\'';
echo $aPlace['astext'];
echo '\'';
}
- echo ">".htmlspecialchars($aPlace['langaddress'])."</result>";
+ echo '>'.htmlspecialchars($aPlace['langaddress']).'</result>';
- if (isset($aPlace['aAddress']))
- {
- echo "<addressparts>";
- foreach($aPlace['aAddress'] as $sKey => $sValue)
- {
- $sKey = str_replace(' ','_',$sKey);
+ if (isset($aPlace['aAddress'])) {
+ echo '<addressparts>';
+ foreach ($aPlace['aAddress'] as $sKey => $sValue) {
+ $sKey = str_replace(' ', '_', $sKey);
echo "<$sKey>";
echo htmlspecialchars($sValue);
echo "</$sKey>";
}
- echo "</addressparts>";
+ echo '</addressparts>';
}
- if (isset($aPlace['sExtraTags']))
- {
- echo "<extratags>";
- foreach ($aPlace['sExtraTags'] as $sKey => $sValue)
- {
+ if (isset($aPlace['sExtraTags'])) {
+ echo '<extratags>';
+ foreach ($aPlace['sExtraTags'] as $sKey => $sValue) {
echo '<tag key="'.htmlspecialchars($sKey).'" value="'.htmlspecialchars($sValue).'"/>';
}
- echo "</extratags>";
+ echo '</extratags>';
}
- if (isset($aPlace['sNameDetails']))
- {
- echo "<namedetails>";
- foreach ($aPlace['sNameDetails'] as $sKey => $sValue)
- {
+ if (isset($aPlace['sNameDetails'])) {
+ echo '<namedetails>';
+ foreach ($aPlace['sNameDetails'] as $sKey => $sValue) {
echo '<name desc="'.htmlspecialchars($sKey).'">';
echo htmlspecialchars($sValue);
- echo "</name>";
+ echo '</name>';
}
- echo "</namedetails>";
+ echo '</namedetails>';
}
- if (isset($aPlace['askml']))
- {
+ if (isset($aPlace['askml'])) {
echo "\n<geokml>";
echo $aPlace['askml'];
- echo "</geokml>";
+ echo '</geokml>';
}
-
}
-echo "</reversegeocode>";
+echo '</reversegeocode>';
<?php
$aOutput = array();
-$aOutput['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright";
+$aOutput['licence'] = 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright';
$aOutput['batch'] = array();
-foreach($aBatchResults as $aSearchResults)
-{
+foreach ($aBatchResults as $aSearchResults) {
if (!$aSearchResults) $aSearchResults = array();
$aFilteredPlaces = array();
- foreach($aSearchResults as $iResNum => $aPointDetails)
- {
+ foreach ($aSearchResults as $iResNum => $aPointDetails) {
$aPlace = array(
- 'place_id'=>$aPointDetails['place_id'],
- );
+ 'place_id'=>$aPointDetails['place_id'],
+ );
$sOSMType = formatOSMType($aPointDetails['osm_type']);
- if ($sOSMType)
- {
+ if ($sOSMType) {
$aPlace['osm_type'] = $sOSMType;
$aPlace['osm_id'] = $aPointDetails['osm_id'];
}
- if (isset($aPointDetails['aBoundingBox']))
- {
+ if (isset($aPointDetails['aBoundingBox'])) {
$aPlace['boundingbox'] = array(
- $aPointDetails['aBoundingBox'][0],
- $aPointDetails['aBoundingBox'][1],
- $aPointDetails['aBoundingBox'][2],
- $aPointDetails['aBoundingBox'][3]);
+ $aPointDetails['aBoundingBox'][0],
+ $aPointDetails['aBoundingBox'][1],
+ $aPointDetails['aBoundingBox'][2],
+ $aPointDetails['aBoundingBox'][3]
+ );
- if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons)
- {
+ if (isset($aPointDetails['aPolyPoints']) && $bShowPolygons) {
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
}
}
- if (isset($aPointDetails['zoom']))
- {
+ if (isset($aPointDetails['zoom'])) {
$aPlace['zoom'] = $aPointDetails['zoom'];
}
$aPlace['importance'] = $aPointDetails['importance'];
- if (isset($aPointDetails['icon']))
- {
+ if (isset($aPointDetails['icon'])) {
$aPlace['icon'] = $aPointDetails['icon'];
}
- if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])>0)
- {
+ if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])>0) {
$aPlace['address'] = $aPointDetails['address'];
}
- if (isset($aPointDetails['asgeojson']))
- {
+ if (isset($aPointDetails['asgeojson'])) {
$aPlace['geojson'] = json_decode($aPointDetails['asgeojson']);
}
- if (isset($aPointDetails['assvg']))
- {
+ if (isset($aPointDetails['assvg'])) {
$aPlace['svg'] = $aPointDetails['assvg'];
}
- if (isset($aPointDetails['astext']))
- {
+ if (isset($aPointDetails['astext'])) {
$aPlace['geotext'] = $aPointDetails['astext'];
}
- if (isset($aPointDetails['askml']))
- {
+ if (isset($aPointDetails['askml'])) {
$aPlace['geokml'] = $aPointDetails['askml'];
}
<?php
-header("content-type: application/json; charset=UTF-8");
+header('content-type: application/json; charset=UTF-8');
$aFilteredPlaces = array();
-foreach($aSearchResults as $iResNum => $aPointDetails)
-{
+foreach ($aSearchResults as $iResNum => $aPointDetails) {
$aPlace = array(
- 'place_id'=>$aPointDetails['place_id'],
- 'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright",
- );
+ 'place_id'=>$aPointDetails['place_id'],
+ 'licence'=>'Data © OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright',
+ );
$sOSMType = formatOSMType($aPointDetails['osm_type']);
- if ($sOSMType)
- {
+ if ($sOSMType) {
$aPlace['osm_type'] = $sOSMType;
$aPlace['osm_id'] = $aPointDetails['osm_id'];
}
- if (isset($aPointDetails['aBoundingBox']))
- {
+ if (isset($aPointDetails['aBoundingBox'])) {
$aPlace['boundingbox'] = $aPointDetails['aBoundingBox'];
- if (isset($aPointDetails['aPolyPoints']))
- {
+ if (isset($aPointDetails['aPolyPoints'])) {
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
}
}
- if (isset($aPointDetails['zoom']))
- {
+ if (isset($aPointDetails['zoom'])) {
$aPlace['zoom'] = $aPointDetails['zoom'];
}
$aPlace['importance'] = $aPointDetails['importance'];
- if (isset($aPointDetails['icon']) && $aPointDetails['icon'])
- {
+ if (isset($aPointDetails['icon']) && $aPointDetails['icon']) {
$aPlace['icon'] = $aPointDetails['icon'];
}
- if (isset($aPointDetails['address']))
- {
+ if (isset($aPointDetails['address'])) {
$aPlace['address'] = $aPointDetails['address'];
}
- if (isset($aPointDetails['asgeojson']))
- {
+ if (isset($aPointDetails['asgeojson'])) {
$aPlace['geojson'] = json_decode($aPointDetails['asgeojson']);
}
- if (isset($aPointDetails['assvg']))
- {
+ if (isset($aPointDetails['assvg'])) {
$aPlace['svg'] = $aPointDetails['assvg'];
}
- if (isset($aPointDetails['astext']))
- {
+ if (isset($aPointDetails['astext'])) {
$aPlace['geotext'] = $aPointDetails['astext'];
}
- if (isset($aPointDetails['askml']))
- {
+ if (isset($aPointDetails['askml'])) {
$aPlace['geokml'] = $aPointDetails['askml'];
}
<?php
$aFilteredPlaces = array();
-foreach($aSearchResults as $iResNum => $aPointDetails)
-{
+foreach ($aSearchResults as $iResNum => $aPointDetails) {
$aPlace = array(
- 'place_id'=>$aPointDetails['place_id'],
- 'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
- );
+ 'place_id'=>$aPointDetails['place_id'],
+ 'licence'=>'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright',
+ );
$sOSMType = formatOSMType($aPointDetails['osm_type']);
- if ($sOSMType)
- {
+ if ($sOSMType) {
$aPlace['osm_type'] = $sOSMType;
$aPlace['osm_id'] = $aPointDetails['osm_id'];
}
- if (isset($aPointDetails['aBoundingBox']))
- {
+ if (isset($aPointDetails['aBoundingBox'])) {
$aPlace['boundingbox'] = $aPointDetails['aBoundingBox'];
- if (isset($aPointDetails['aPolyPoints']))
- {
+ if (isset($aPointDetails['aPolyPoints'])) {
$aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
}
}
- if (isset($aPointDetails['zoom']))
- {
+ if (isset($aPointDetails['zoom'])) {
$aPlace['zoom'] = $aPointDetails['zoom'];
}
$aPlace['importance'] = $aPointDetails['importance'];
- if (isset($aPointDetails['icon']))
- {
+ if (isset($aPointDetails['icon'])) {
$aPlace['icon'] = $aPointDetails['icon'];
}
- if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])>0)
- {
+ if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])>0) {
$aPlace['address'] = $aPointDetails['address'];
}
- if (isset($aPointDetails['asgeojson']))
- {
+ if (isset($aPointDetails['asgeojson'])) {
$aPlace['geojson'] = json_decode($aPointDetails['asgeojson']);
}
- if (isset($aPointDetails['assvg']))
- {
+ if (isset($aPointDetails['assvg'])) {
$aPlace['svg'] = $aPointDetails['assvg'];
}
- if (isset($aPointDetails['astext']))
- {
+ if (isset($aPointDetails['astext'])) {
$aPlace['geotext'] = $aPointDetails['astext'];
}
- if (isset($aPointDetails['askml']))
- {
+ if (isset($aPointDetails['askml'])) {
$aPlace['geokml'] = $aPointDetails['askml'];
}
<?php
-header("content-type: text/xml; charset=UTF-8");
+header('content-type: text/xml; charset=UTF-8');
-echo "<";
-echo "?xml version=\"1.0\" encoding=\"UTF-8\" ?";
+echo '<';
+echo '?xml version="1.0" encoding="UTF-8" ?';
echo ">\n";
-echo "<";
+echo '<';
echo (isset($sXmlRootTag)?$sXmlRootTag:'searchresults');
echo " timestamp='".date(DATE_RFC822)."'";
echo " attribution='Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright'";
echo " querystring='".htmlspecialchars($sQuery, ENT_QUOTES)."'";
if (isset($aMoreParams['viewbox'])) echo " viewbox='".htmlspecialchars($aMoreParams['viewbox'], ENT_QUOTES)."'";
echo " polygon='".(isset($aMoreParams['polygon'])?'true':'false')."'";
-if (isset($aMoreParams['exclude_place_ids']))
-{
+if (isset($aMoreParams['exclude_place_ids'])) {
echo " exclude_place_ids='".htmlspecialchars($aMoreParams['exclude_place_ids'])."'";
}
echo " more_url='".htmlspecialchars($sMoreURL)."'";
echo ">\n";
-foreach($aSearchResults as $iResNum => $aResult)
-{
+foreach ($aSearchResults as $iResNum => $aResult) {
echo "<place place_id='".$aResult['place_id']."'";
$sOSMType = formatOSMType($aResult['osm_type']);
- if ($sOSMType)
- {
+ if ($sOSMType) {
echo " osm_type='$sOSMType'";
echo " osm_id='".$aResult['osm_id']."'";
}
echo " place_rank='".$aResult['rank_search']."'";
- if (isset($aResult['aBoundingBox']))
- {
+ if (isset($aResult['aBoundingBox'])) {
echo ' boundingbox="';
- echo join(',',$aResult['aBoundingBox']);
+ echo join(',', $aResult['aBoundingBox']);
echo '"';
- if (isset($aResult['aPolyPoints']))
- {
+ if (isset($aResult['aPolyPoints'])) {
echo ' polygonpoints=\'';
echo json_encode($aResult['aPolyPoints']);
echo '\'';
}
}
- if (isset($aResult['asgeojson']))
- {
+ if (isset($aResult['asgeojson'])) {
echo ' geojson=\'';
echo $aResult['asgeojson'];
echo '\'';
}
- if (isset($aResult['assvg']))
- {
+ if (isset($aResult['assvg'])) {
echo ' geosvg=\'';
echo $aResult['assvg'];
echo '\'';
}
- if (isset($aResult['astext']))
- {
+ if (isset($aResult['astext'])) {
echo ' geotext=\'';
echo $aResult['astext'];
echo '\'';
}
- if (isset($aResult['zoom']))
- {
+ if (isset($aResult['zoom'])) {
echo " zoom='".$aResult['zoom']."'";
}
echo " class='".htmlspecialchars($aResult['class'])."'";
echo " type='".htmlspecialchars($aResult['type'], ENT_QUOTES)."'";
echo " importance='".htmlspecialchars($aResult['importance'])."'";
- if (isset($aResult['icon']) && $aResult['icon'])
- {
+ if (isset($aResult['icon']) && $aResult['icon']) {
echo " icon='".htmlspecialchars($aResult['icon'], ENT_QUOTES)."'";
}
$bHasDelim = false;
- if (isset($aResult['askml']))
- {
- if (!$bHasDelim)
- {
+ if (isset($aResult['askml'])) {
+ if (!$bHasDelim) {
$bHasDelim = true;
- echo ">";
+ echo '>';
}
echo "\n<geokml>";
echo $aResult['askml'];
- echo "</geokml>";
+ echo '</geokml>';
}
- if (isset($aResult['sExtraTags']))
- {
- if (!$bHasDelim)
- {
+ if (isset($aResult['sExtraTags'])) {
+ if (!$bHasDelim) {
$bHasDelim = true;
- echo ">";
+ echo '>';
}
echo "\n<extratags>";
- foreach ($aResult['sExtraTags'] as $sKey => $sValue)
- {
+ foreach ($aResult['sExtraTags'] as $sKey => $sValue) {
echo '<tag key="'.htmlspecialchars($sKey).'" value="'.htmlspecialchars($sValue).'"/>';
}
- echo "</extratags>";
+ echo '</extratags>';
}
- if (isset($aResult['sNameDetails']))
- {
- if (!$bHasDelim)
- {
+ if (isset($aResult['sNameDetails'])) {
+ if (!$bHasDelim) {
$bHasDelim = true;
- echo ">";
+ echo '>';
}
echo "\n<namedetails>";
- foreach ($aResult['sNameDetails'] as $sKey => $sValue)
- {
+ foreach ($aResult['sNameDetails'] as $sKey => $sValue) {
echo '<name desc="'.htmlspecialchars($sKey).'">';
echo htmlspecialchars($sValue);
- echo "</name>";
+ echo '</name>';
}
- echo "</namedetails>";
+ echo '</namedetails>';
}
- if (isset($aResult['address']))
- {
- if (!$bHasDelim)
- {
+ if (isset($aResult['address'])) {
+ if (!$bHasDelim) {
$bHasDelim = true;
- echo ">";
+ echo '>';
}
echo "\n";
- foreach($aResult['address'] as $sKey => $sValue)
- {
- $sKey = str_replace(' ','_',$sKey);
+ foreach ($aResult['address'] as $sKey => $sValue) {
+ $sKey = str_replace(' ', '_', $sKey);
echo "<$sKey>";
echo htmlspecialchars($sValue);
echo "</$sKey>";
}
}
- if ($bHasDelim)
- {
- echo "</place>";
- }
- else
- {
- echo "/>";
+ if ($bHasDelim) {
+ echo '</place>';
+ } else {
+ echo '/>';
}
}
-echo "</" . (isset($sXmlRootTag)?$sXmlRootTag:'searchresults') . ">";
+echo '</' . (isset($sXmlRootTag)?$sXmlRootTag:'searchresults') . '>';
PG_RETURN_TEXT_P(result);
}
+// Set isspace=1 if the replacement _only_ adds a space before the search string. I.e. to == " " + from
void str_replace(char* buffer, int* len, int* changes, char* from, int fromlen, char* to, int tolen, int isspace)
{
char *p;
- // Search string is too long to be pressent
+ // Search string is too long to be present
if (fromlen > *len) return;
p = strstr(buffer, from);
while(p)
{
- if (!isspace || *(p-1) != ' ')
+ if (!isspace || (p > buffer && *(p-1) != ' '))
{
(*changes)++;
if (tolen != fromlen) memmove(p+tolen, p+fromlen, *len-(p-buffer)+1);
sourcedata = (unsigned char *)VARDATA(source);
sourcedatalength = VARSIZE(source) - VARHDRSZ;
- // Buffer for doing the replace in - string could get slightly longer (double is mastive overkill)
+ // Buffer for doing the replace in - string could get slightly longer (double is massive overkill)
buffer = (char *)palloc((sourcedatalength*2)*sizeof(char));
memcpy(buffer+1, sourcedata, sourcedatalength);
buffer[0] = 32;
<!-- https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/PSR2/ruleset.xml -->
<rule ref="PSR2"/>
+ <exclude-pattern>./lib/template/*html*</exclude-pattern>
+ <exclude-pattern>./lib/template/includes/</exclude-pattern>
+ <exclude-pattern>./module/</exclude-pattern>
+ <exclude-pattern>./website/css</exclude-pattern>
+ <exclude-pattern>./website/js</exclude-pattern>
+
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="194"/>
INDENTATION, SPACING
************************************************************** -->
- <!-- We don't need 2 blank lines after function -->
- <rule ref="Squiz.WhiteSpace.FunctionSpacing.After">
- <severity>0</severity>
- </rule>
-
- <!-- Aligned looks nicer, but causes too many warnings currently -->
- <rule ref="Generic.Formatting.MultipleStatementAlignment.NotSame">
- <severity>0</severity>
- </rule>
- <rule ref="Generic.Formatting.MultipleStatementAlignment.NotSameWarning">
- <severity>0</severity>
- </rule>
-
<!-- Aligned looks nicer, but causes too many warnings currently -->
<rule ref="Squiz.Arrays.ArrayDeclaration.DoubleArrowNotAligned">
<severity>0</severity>
| N2 | W1 |
When searching for "4 galoo"
Then results contain
- | ID | osm_type | osm_id | langaddress
- | 0 | N | 1 | 4, galoo, 12345
+ | ID | osm_type | osm_id | langaddress |
+ | 0 | N | 1 | 4, galoo, 12345 |
When searching for "5 galoo"
Then results contain
- | ID | osm_type | osm_id | langaddress
- | 0 | N | 2 | 5, galoo, 99999
+ | ID | osm_type | osm_id | langaddress |
+ | 0 | N | 2 | 5, galoo, 99999 |
Scenario: Address without tags, closest street
Given the scene roads-with-pois
n202 x0.0001 y0.0001
n203 x0.0001 y0
w2 Tref=45' Nn200,n201,n202,n203,n200
- r1 Ttype=multipolygon,tourism=hotel,name=XZ' Mw2@
+ r1 Ttype=multipolygon,tourism=hotel,name=XZ Mw2@
"""
Then place contains
- | object | class | type | name
- | R1 | tourism | hotel | 'name' : 'XZ'
+ | object | class | type | name |
+ | R1 | tourism | hotel | 'name' : 'XZ' |
When updating osm data
"""
r1 Ttype=multipolygon,tourism=hotel,name=XZ Mn1@
r1 Ttype=multipolygon,tourism=hotel,name=XZ Mw2@
"""
Then place contains
- | object | class | type | name
- | R1 | tourism | hotel | 'name' : 'XZ'
+ | object | class | type | name |
+ | R1 | tourism | hotel | 'name' : 'XZ' |
When updating osm data
"""
r1 Ttype=multipolygon,amenity=prison,name=XZ Mw2@
"""
Then place has no entry for R1:tourism
And place contains
- | object | class | type | name
- | R1 | amenity | prison | 'name' : 'XZ'
+ | object | class | type | name |
+ | R1 | amenity | prison | 'name' : 'XZ' |
Scenario: Change name of a relation
When loading osm data
r1 Ttype=multipolygon,tourism=hotel,name=AB Mw2@
"""
Then place contains
- | object | class | type | name
- | R1 | tourism | hotel | 'name' : 'AB'
+ | object | class | type | name |
+ | R1 | tourism | hotel | 'name' : 'AB' |
When updating osm data
"""
r1 Ttype=multipolygon,tourism=hotel,name=XY Mw2@
"""
Then place contains
- | object | class | type | name
- | R1 | tourism | hotel | 'name' : 'XZ'
+ | object | class | type | name |
+ | R1 | tourism | hotel | 'name' : 'XY' |
Scenario: Change type of a relation into something unknown
When loading osm data
r1 Ttype=multipolygon,tourism=hotel,name=XY Mw2@
"""
Then place contains
- | object | class | type | name
- | R1 | tourism | hotel | 'name' : 'XZ'
+ | object | class | type | name |
+ | R1 | tourism | hotel | 'name' : 'XY' |
When updating osm data
"""
r1 Ttype=multipolygon,amenities=prison,name=XY Mw2@
r1 Ttype=multipolygon,tourism=hotel,name=XY Mw2@
"""
Then place contains
- | object | class | type | name
- | R1 | tourism | hotel | 'name' : 'XZ'
+ | object | class | type | name |
+ | R1 | tourism | hotel | 'name' : 'XY' |
When updating osm data
"""
r1 Ttourism=hotel,name=XY Mw2@
r1 Ttype=multipolygon,tourism=hotel,name=XY Mw2@
"""
Then place contains
- | object | class | type | name
- | R1 | tourism | hotel | 'name' : 'XZ'
+ | object | class | type | name |
+ | R1 | tourism | hotel | 'name' : 'XY' |
When updating osm data
"""
r1 Ttype=multipolygonn,tourism=hotel,name=XY Mw2@
n2 Tplace=locality,name=spotty
"""
Then place contains
- | object | type | name
- | N1:tourism | hotel | 'name' : 'foo'
- | N1:amenity | restaurant | 'name' : 'foo'
- | N2:place | locality | 'name' : 'spotty'
+ | object | type | name+name |
+ | N1:tourism | hotel | foo |
+ | N1:amenity | restaurant | foo |
+ | N2:place | locality | spotty |
When updating osm data
"""
n1 dV Ttourism=hotel,name=foo
Then place has no entry for N1:amenity
And place has no entry for N2
And place contains
- | object | class | type | name
- | N1:tourism | tourism | hotel | 'name' : 'foo'
+ | object | class | type | name |
+ | N1:tourism | tourism | hotel | 'name' : 'foo' |
<?php
require_once 'SebastianBergmann/CodeCoverage/autoload.php';
+
function coverage_shutdown($oCoverage)
{
$oCoverage->stop();
register_shutdown_function('coverage_shutdown', $coverage);
include $_SERVER['COV_SCRIPT_FILENAME'];
-
-
class PhraseTest extends \PHPUnit_Framework_TestCase
{
+
+
private function serializeSets($aSets)
{
$aParts = array();
{
private $oCtx;
+
protected function setUp()
{
$this->oCtx = new SearchContext();