## 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
# Install Nominatim in a virtual machine for development and testing
-This document describes how you can install Nominatim inside a Ubuntu 14
+This document describes how you can install Nominatim inside a Ubuntu 16
virtual machine on your desktop/laptop (host machine). The goal is to give
you a development environment to easily edit code and run the test suite
without affecting the rest of your system.
-The installation can run largely unsupervised. You should expect 1-2h from
+The installation can run largely unsupervised. You should expect 1h from
start to finish depending on how fast your computer and download speed
is.
git clone --recursive https://github.com/openstreetmap/Nominatim.git
- If you haven't used `--recursive`, then you can load the submodules using
+ If you forgot `--recursive`, it you can later load the submodules using
git submodule init
git submodule update
vagrant ssh ubuntu
3. Import a small country (Monaco)
-
- You need to give the virtual machine more memory (2GB) for an import,
- see `Vagrantfile`. Otherwise 1GB is enough.
See the FAQ how to skip this step and point Nominatim to an existing database.
```
# inside the virtual machine:
- mkdir data
cd build
- wget --no-verbose --output-document=../data/monaco.osm.pbf http://download.geofabrik.de/europe/monaco-latest.osm.pbf
- ./utils/setup.php --osm-file ../data/monaco.osm.pbf --osm2pgsql-cache 1000 --all 2>&1 | tee monaco.$$.log
+ wget --no-verbose --output-document=/tmp/monaco.osm.pbf http://download.geofabrik.de/europe/monaco-latest.osm.pbf
+ ./utils/setup.php --osm-file /tmp/monaco.osm.pbf --osm2pgsql-cache 1000 --all 2>&1 | tee monaco.$$.log
```
To repeat an import you'd need to delete the database first
You edit code on your host machine in any editor you like. There is no need to
restart any software: just refresh your browser window.
+Note that the webserver uses files from the /build directory. If you change
+files in Nominatim/website or Nominatim/utils for example you first need to
+copy them into the /build directory by running the `cmake` step from the
+installation.
+
PHP errors are written to `/var/log/apache2/error.log`.
With `echo` and `var_dump()` you write into the output (HTML/XML/JSON) when
you either add `&debug=1` to the URL (preferred) or set
`@define('CONST_Debug', true);` in `settings/local.php`.
+In the Python BDD test you can use `logger.info()` for temporary debug
+statements.
+
+
+
+## Running unit tests
+
+ cd ~/Nominatim/tests/php
+ phpunit ./
+
+
+## Running PHP code style tests
+ cd ~/Nominatim
+ phpcs --colors .
## Running functional tests
To run the full test suite
- cd ~/Nominatim/tests
- NOMINATIM_SERVER=http://localhost:8089/nominatim lettuce features
+ cd ~/Nominatim/test/bdd
+ behave -DBUILDDIR=/home/vagrant/build/ db osm2pgsql
To run a single file
- NOMINATIM_SERVER=http://localhost:8089/nominatim lettuce features/api/reverse.feature
+ behave -DBUILDDIR=/home/vagrant/build/ features/api/reverse.feature
+
+Or a single test by line number
+
+ behave -DBUILDDIR=/home/vagrant/build/ features/api/reverse.feature:34
-To run specific tests you can add tags just before the `Scenario line`, e.g.
+To run specific groups of tests you can add tags just before the `Scenario line`, e.g.
@bug-34
Scenario: address lookup for non-existing or invalid node, way, relation
and then
- NOMINATIM_SERVER=http://localhost:8089/nominatim lettuce -t bug-34
-
-
-## Running unit tests
-
- cd ~/Nominatim/tests/php
- phpunit ./
+ behave -DBUILDDIR=/home/vagrant/build/ --tags @bug-34
Also this document skips the optional Wikipedia data import which affects ranking
of search results. See [Nominatim installation](http://nominatim.org/release-docs/latest/Installation) for details.
-##### Why Ubuntu and CentOS, can I test CentOS/CoreOS/FreeBSD?
+##### Why Ubuntu? Can I test CentOS/Fedora/CoreOS/FreeBSD?
-There is a Vagrant script for CentOS available. Simply start your box
-with `vagrant up centos` and then log in with `vagrant ssh centos`.
-In general Nominatim will also run in the other environments. The installation steps
+There is a Vagrant script for CentOS available, but the Nominatim directory
+isn't symlinked/mounted to the host which makes development trickier. We used
+it mainly for debugging installation with SELinux.
+
+In general Nominatim will run in the other environments. The installation steps
are slightly different, e.g. the name of the package manager, Apache2 package
name, location of files. We chose Ubuntu because that is closest to the
nominatim.openstreetmap.org production environment.
-You can configure/download other Vagrant boxes from [vagrantbox.es](http://www.vagrantbox.es/).
-
+You can configure/download other Vagrant boxes from [https://app.vagrantup.com/boxes/search](https://app.vagrantup.com/boxes/search).
##### How can I connect to an existing database?
pgsql://postgres@your-server.com:5432/nominatim_it
-No data import necessary, no restarting necessary.
+No data import necessary or restarting necessary.
If the Postgres installation is behind a firewall, you can try
inside the virtual machine. It will map the port to `localhost:9999` and then
you edit `settings/local.php` with
- pgsql://postgres@localhost:9999/nominatim_it
+ @define('CONST_Database_DSN', 'pgsql://postgres@localhost:9999/nominatim_it');
To access postgres directly remember to specify the hostname, e.g. `psql --host localhost --port 9999 nominatim_it`
##### My computer is slow and the import takes too long. Can I start the virtual machine "in the cloud"?
-Yes. It's possible to start the virtual machine on [Amazon AWS (plugin)](https://github.com/mitchellh/vagrant-aws) or [DigitalOcean (plugin)](https://github.com/smdahlen/vagrant-digitalocean).
+Yes. It's possible to start the virtual machine on [Amazon AWS (plugin)](https://github.com/mitchellh/vagrant-aws)
+or [DigitalOcean (plugin)](https://github.com/smdahlen/vagrant-digitalocean).
end
end
- config.vm.define "centos" do |sub|
- sub.vm.box = "bento/centos-7.2"
+ config.vm.define "centos" do |sub|
+ sub.vm.box = "centos/7"
sub.vm.provision :shell do |s|
s.path = "vagrant/Install-on-Centos-7.sh"
s.privileged = false
- s.args = [checkout]
+ s.args = "yes"
end
+ sub.vm.synced_folder ".", "/home/vagrant/Nominatim", disabled: true
+ sub.vm.synced_folder ".", "/vagrant", disabled: true
end
- # configure shared package cache if possible
- #if Vagrant.has_plugin?("vagrant-cachier")
- # config.cache.enable :apt
- # config.cache.scope = :box
- #end
-
-
config.vm.provider "virtualbox" do |vb|
vb.gui = false
- vb.customize ["modifyvm", :id, "--memory", "2048"]
+ vb.memory = 2048
+ vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate//vagrant","0"]
end
-
- # config.vm.provider :digital_ocean do |provider, override|
- # override.ssh.private_key_path = '~/.ssh/id_rsa'
- # override.vm.box = 'digital_ocean'
- # override.vm.box_url = "https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digital_ocean.box"
-
- # provider.token = ''
- # # provider.token = 'YOUR TOKEN'
- # provider.image = 'ubuntu-14-04-x64'
- # provider.region = 'nyc2'
- # provider.size = '512mb'
- # end
-
end
public function getInt($sName, $bDefault = false)
{
- if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
+ if (!isset($this->aParams[$sName])) {
return $bDefault;
}
public function getFloat($sName, $bDefault = false)
{
- if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) {
+ if (!isset($this->aParams[$sName])) {
return $bDefault;
}
$sValue = $this->getString($sName);
if ($sValue) {
- return explode(',', $sValue);
+ // removes all NULL, FALSE and Empty Strings but leaves 0 (zero) values
+ return array_values(array_filter(explode(',', $sValue), 'strlen'));
}
return $aDefault;
}
if (isset($aPlace['lat'])) $aFilteredPlaces['lat'] = $aPlace['lat'];
if (isset($aPlace['lon'])) $aFilteredPlaces['lon'] = $aPlace['lon'];
+
+ if ($sOutputFormat == 'jsonv2') {
+ $aFilteredPlaces['place_rank'] = $aPlace['rank_search'];
+
+ $aFilteredPlaces['category'] = $aPlace['class'];
+ $aFilteredPlaces['type'] = $aPlace['type'];
+
+ $aFilteredPlaces['importance'] = $aPlace['importance'];
+
+ $aFilteredPlaces['addresstype'] = strtolower($aPlace['addresstype']);
+
+ $aFilteredPlaces['name'] = $aPlace['placename'];
+ }
+
$aFilteredPlaces['display_name'] = $aPlace['langaddress'];
+
if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
+++ /dev/null
-<?php
-
-$aFilteredPlaces = array();
-
-if (!sizeof($aPlace)) {
- if (isset($sError))
- $aFilteredPlaces['error'] = $sError;
- 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';
- $sOSMType = formatOSMType($aPlace['osm_type']);
- if ($sOSMType) {
- $aFilteredPlaces['osm_type'] = $sOSMType;
- $aFilteredPlaces['osm_id'] = $aPlace['osm_id'];
- }
- if (isset($aPlace['lat'])) $aFilteredPlaces['lat'] = $aPlace['lat'];
- if (isset($aPlace['lon'])) $aFilteredPlaces['lon'] = $aPlace['lon'];
-
- $aFilteredPlaces['place_rank'] = $aPlace['rank_search'];
-
- $aFilteredPlaces['category'] = $aPlace['class'];
- $aFilteredPlaces['type'] = $aPlace['type'];
-
- $aFilteredPlaces['importance'] = $aPlace['importance'];
-
- $aFilteredPlaces['addresstype'] = strtolower($aPlace['addresstype']);
-
- $aFilteredPlaces['display_name'] = $aPlace['langaddress'];
- $aFilteredPlaces['name'] = $aPlace['placename'];
-
- if (isset($aPlace['aAddress'])) $aFilteredPlaces['address'] = $aPlace['aAddress'];
- if (isset($aPlace['sExtraTags'])) $aFilteredPlaces['extratags'] = $aPlace['sExtraTags'];
- if (isset($aPlace['sNameDetails'])) $aFilteredPlaces['namedetails'] = $aPlace['sNameDetails'];
-
- if (isset($aPlace['aBoundingBox'])) {
- $aFilteredPlaces['boundingbox'] = $aPlace['aBoundingBox'];
- }
-
- if (isset($aPlace['asgeojson'])) {
- $aFilteredPlaces['geojson'] = json_decode($aPlace['asgeojson']);
- }
-
- if (isset($aPlace['assvg'])) {
- $aFilteredPlaces['svg'] = $aPlace['assvg'];
- }
-
- if (isset($aPlace['astext'])) {
- $aFilteredPlaces['geotext'] = $aPlace['astext'];
- }
-
- if (isset($aPlace['askml'])) {
- $aFilteredPlaces['geokml'] = $aPlace['askml'];
- }
-}
-
-javascript_renderData($aFilteredPlaces);
<?php
-header('content-type: application/json; charset=UTF-8');
$aFilteredPlaces = array();
foreach ($aSearchResults as $iResNum => $aPointDetails) {
$aPlace = array(
'place_id'=>$aPointDetails['place_id'],
- 'licence'=>'Data © OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright',
+ 'licence'=>'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright',
);
$sOSMType = formatOSMType($aPointDetails['osm_type']);
$aPlace['lon'] = $aPointDetails['lon'];
$aPlace['display_name'] = $aPointDetails['name'];
- $aPlace['class'] = $aPointDetails['class'];
+ if ($sOutputFormat == 'jsonv2') {
+ $aPlace['place_rank'] = $aPointDetails['rank_search'];
+ $aPlace['category'] = $aPointDetails['class'];
+ } else {
+ $aPlace['class'] = $aPointDetails['class'];
+ }
$aPlace['type'] = $aPointDetails['type'];
$aPlace['importance'] = $aPointDetails['importance'];
$aPlace['icon'] = $aPointDetails['icon'];
}
- if (isset($aPointDetails['address'])) {
+ if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])) {
$aPlace['address'] = $aPointDetails['address'];
}
+++ /dev/null
-<?php
-
-$aFilteredPlaces = array();
-foreach ($aSearchResults as $iResNum => $aPointDetails) {
- $aPlace = array(
- 'place_id'=>$aPointDetails['place_id'],
- 'licence'=>'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright',
- );
-
- $sOSMType = formatOSMType($aPointDetails['osm_type']);
- if ($sOSMType) {
- $aPlace['osm_type'] = $sOSMType;
- $aPlace['osm_id'] = $aPointDetails['osm_id'];
- }
-
- if (isset($aPointDetails['aBoundingBox'])) {
- $aPlace['boundingbox'] = $aPointDetails['aBoundingBox'];
-
- if (isset($aPointDetails['aPolyPoints'])) {
- $aPlace['polygonpoints'] = $aPointDetails['aPolyPoints'];
- }
- }
-
- if (isset($aPointDetails['zoom'])) {
- $aPlace['zoom'] = $aPointDetails['zoom'];
- }
-
- $aPlace['lat'] = $aPointDetails['lat'];
- $aPlace['lon'] = $aPointDetails['lon'];
- $aPlace['display_name'] = $aPointDetails['name'];
- $aPlace['place_rank'] = $aPointDetails['rank_search'];
-
- $aPlace['category'] = $aPointDetails['class'];
- $aPlace['type'] = $aPointDetails['type'];
-
- $aPlace['importance'] = $aPointDetails['importance'];
-
- if (isset($aPointDetails['icon'])) {
- $aPlace['icon'] = $aPointDetails['icon'];
- }
-
- if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])>0) {
- $aPlace['address'] = $aPointDetails['address'];
- }
-
- if (isset($aPointDetails['asgeojson'])) {
- $aPlace['geojson'] = json_decode($aPointDetails['asgeojson']);
- }
-
- if (isset($aPointDetails['assvg'])) {
- $aPlace['svg'] = $aPointDetails['assvg'];
- }
-
- if (isset($aPointDetails['astext'])) {
- $aPlace['geotext'] = $aPointDetails['astext'];
- }
-
- if (isset($aPointDetails['askml'])) {
- $aPlace['geokml'] = $aPointDetails['askml'];
- }
-
- if (isset($aPointDetails['sExtraTags'])) $aPlace['extratags'] = $aPointDetails['sExtraTags'];
- if (isset($aPointDetails['sNameDetails'])) $aPlace['namedetails'] = $aPointDetails['sNameDetails'];
-
- $aFilteredPlaces[] = $aPlace;
-}
-
-javascript_renderData($aFilteredPlaces);
ST_Distance(centroid, point) as distance, null as isguess
FROM search_name_-partition-
WHERE name_vector @> isin_token
- AND ST_DWithin(centroid, point, 0.01)
+ AND ST_DWithin(centroid, point, 0.015)
AND search_rank between 26 and 27
ORDER BY distance ASC limit 1
LOOP
--- /dev/null
+<?php
+
+namespace Nominatim;
+
+use Exception;
+
+require_once('../../lib/ParameterParser.php');
+
+
+function userError($sError)
+{
+ throw new Exception($sError);
+}
+
+class ParameterParserTest extends \PHPUnit_Framework_TestCase
+{
+
+
+ public function testGetBool()
+ {
+ $oParams = new ParameterParser([
+ 'bool1' => '1',
+ 'bool2' => '0',
+ 'bool3' => 'true',
+ 'bool4' => 'false',
+ 'bool5' => ''
+ ]);
+
+ $this->assertSame(false, $oParams->getBool('non-exists'));
+ $this->assertSame(true, $oParams->getBool('non-exists', true));
+ $this->assertSame(true, $oParams->getBool('bool1'));
+ $this->assertSame(false, $oParams->getBool('bool2'));
+ $this->assertSame(true, $oParams->getBool('bool3'));
+ $this->assertSame(true, $oParams->getBool('bool4'));
+ $this->assertSame(false, $oParams->getBool('bool5'));
+ }
+
+
+ public function testGetInt()
+ {
+ $oParams = new ParameterParser([
+ 'int1' => '5',
+ 'int2' => '-1',
+ 'int3' => 0
+ ]);
+
+ $this->assertSame(false, $oParams->getInt('non-exists'));
+ $this->assertSame(999, $oParams->getInt('non-exists', 999));
+ $this->assertSame(5, $oParams->getInt('int1'));
+
+ $this->assertSame(-1, $oParams->getInt('int2'));
+ $this->assertSame(0, $oParams->getInt('int3'));
+ }
+
+
+ public function testGetIntWithNonNumber()
+ {
+ $this->setExpectedException(Exception::class, "Integer number expected for parameter 'int4'");
+ (new ParameterParser(['int4' => 'a']))->getInt('int4');
+ }
+
+
+ public function testGetIntWithEmpytString()
+ {
+ $this->setExpectedException(Exception::class, "Integer number expected for parameter 'int5'");
+ (new ParameterParser(['int5' => '']))->getInt('int5');
+ }
+
+
+ public function testGetFloat()
+ {
+
+ $oParams = new ParameterParser([
+ 'float1' => '1.0',
+ 'float2' => '-5',
+ 'float3' => 0
+ ]);
+
+ $this->assertSame(false, $oParams->getFloat('non-exists'));
+ $this->assertSame(999, $oParams->getFloat('non-exists', 999));
+ $this->assertSame(1.0, $oParams->getFloat('float1'));
+ $this->assertSame(-5.0, $oParams->getFloat('float2'));
+ $this->assertSame(0.0, $oParams->getFloat('float3'));
+ }
+
+ public function testGetFloatWithEmptyString()
+ {
+ $this->setExpectedException(Exception::class, "Floating-point number expected for parameter 'float4'");
+ (new ParameterParser(['float4' => '']))->getFloat('float4');
+ }
+
+ public function testGetFloatWithTextString()
+ {
+ $this->setExpectedException(Exception::class, "Floating-point number expected for parameter 'float5'");
+ (new ParameterParser(['float5' => 'a']))->getFloat('float5');
+ }
+
+
+ public function testGetFloatWithInvalidNumber()
+ {
+ $this->setExpectedException(Exception::class, "Floating-point number expected for parameter 'float6'");
+ (new ParameterParser(['float6' => '-55.']))->getFloat('float6');
+ }
+
+
+ public function testGetString()
+ {
+ $oParams = new ParameterParser([
+ 'str1' => 'abc',
+ 'str2' => '',
+ 'str3' => '0'
+ ]);
+
+ $this->assertSame(false, $oParams->getString('non-exists'));
+ $this->assertSame('default', $oParams->getString('non-exists', 'default'));
+ $this->assertSame('abc', $oParams->getString('str1'));
+ $this->assertSame(false, $oParams->getStringList('str2'));
+ $this->assertSame(false, $oParams->getStringList('str3')); // sadly PHP magic treats 0 as false when returned
+ }
+
+
+ public function testGetSet()
+ {
+ $oParams = new ParameterParser([
+ 'val1' => 'foo',
+ 'val2' => '',
+ 'val3' => 0
+ ]);
+
+ $this->assertSame(false, $oParams->getSet('non-exists', ['foo', 'bar']));
+ $this->assertSame('default', $oParams->getSet('non-exists', ['foo', 'bar'], 'default'));
+ $this->assertSame('foo', $oParams->getSet('val1', ['foo', 'bar']));
+
+ $this->assertSame(false, $oParams->getSet('val2', ['foo', 'bar']));
+ $this->assertSame(0, $oParams->getSet('val3', ['foo', 'bar']));
+ }
+
+
+ public function testGetSetWithValueNotInSet()
+ {
+ $this->setExpectedException(Exception::class, "Parameter 'val4' must be one of: foo, bar");
+ (new ParameterParser(['val4' => 'faz']))->getSet('val4', ['foo', 'bar']);
+ }
+
+
+ public function testGetStringList()
+ {
+ $oParams = new ParameterParser([
+ 'list1' => ',a,b,c,,c,d',
+ 'list2' => 'a',
+ 'list3' => '',
+ 'list4' => '0'
+ ]);
+
+ $this->assertSame(false, $oParams->getStringList('non-exists'));
+ $this->assertSame(['a', 'b'], $oParams->getStringList('non-exists', ['a', 'b']));
+ $this->assertSame(['a', 'b', 'c', 'c', 'd'], $oParams->getStringList('list1'));
+ $this->assertSame(['a'], $oParams->getStringList('list2'));
+ $this->assertSame(false, $oParams->getStringList('list3'));
+ $this->assertSame(false, $oParams->getStringList('list4'));
+ }
+
+
+ public function testGetPreferredLanguages()
+ {
+ $oParams = new ParameterParser(['accept-language' => '']);
+ $this->assertSame([
+ 'short_name:default' => 'short_name:default',
+ 'name:default' => 'name:default',
+ 'short_name' => 'short_name',
+ 'name' => 'name',
+ 'brand' => 'brand',
+ 'official_name:default' => 'official_name:default',
+ 'official_name' => 'official_name',
+ 'ref' => 'ref',
+ 'type' => 'type'
+ ], $oParams->getPreferredLanguages('default'));
+
+ $oParams = new ParameterParser(['accept-language' => 'de,en']);
+ $this->assertSame([
+ 'short_name:de' => 'short_name:de',
+ 'name:de' => 'name:de',
+ 'short_name:en' => 'short_name:en',
+ 'name:en' => 'name:en',
+ 'short_name' => 'short_name',
+ 'name' => 'name',
+ 'brand' => 'brand',
+ 'official_name:de' => 'official_name:de',
+ 'official_name:en' => 'official_name:en',
+ 'official_name' => 'official_name',
+ 'ref' => 'ref',
+ 'type' => 'type'
+ ], $oParams->getPreferredLanguages('default'));
+
+ $oParams = new ParameterParser(['accept-language' => 'fr-ca,fr;q=0.8,en-ca;q=0.5,en;q=0.3']);
+ $this->assertSame([
+ 'short_name:fr-ca' => 'short_name:fr-ca',
+ 'name:fr-ca' => 'name:fr-ca',
+ 'short_name:fr' => 'short_name:fr',
+ 'name:fr' => 'name:fr',
+ 'short_name:en-ca' => 'short_name:en-ca',
+ 'name:en-ca' => 'name:en-ca',
+ 'short_name:en' => 'short_name:en',
+ 'name:en' => 'name:en',
+ 'short_name' => 'short_name',
+ 'name' => 'name',
+ 'brand' => 'brand',
+ 'official_name:fr-ca' => 'official_name:fr-ca',
+ 'official_name:fr' => 'official_name:fr',
+ 'official_name:en-ca' => 'official_name:en-ca',
+ 'official_name:en' => 'official_name:en',
+ 'official_name' => 'official_name',
+ 'ref' => 'ref',
+ 'type' => 'type',
+ ], $oParams->getPreferredLanguages('default'));
+ }
+}
#DOCS: :::sh
sudo yum install -y postgresql-server postgresql-contrib postgresql-devel \
postgis postgis-utils \
- git cmake make gcc gcc-c++ libtool policycoreutils-python \
+ wget git cmake make gcc gcc-c++ libtool policycoreutils-python \
php-pgsql php php-pear php-pear-DB php-intl libpqxx-devel \
proj-epsg bzip2-devel proj-devel libxml2-devel boost-devel \
expat-devel zlib-devel
# we assume this user is called nominatim and the installation will be in
# /srv/nominatim. To create the user and directory run:
#
-# sudo useradd -d /srv/nominatim -s /bin/bash -m nominatim
+sudo mkdir -p /srv/nominatim #DOCS: sudo useradd -d /srv/nominatim -s /bin/bash -m nominatim
+sudo chown vagrant /srv/nominatim #DOCS:
#
# You may find a more suitable location if you wish.
#
# user name and home directory now like this:
#
export USERNAME=vagrant #DOCS: export USERNAME=nominatim
- export USERHOME=/home/vagrant #DOCS: export USERHOME=/srv/nominatim
+ export USERHOME=/srv/nominatim
#
# **Never, ever run the installation as a root user.** You have been warned.
#
#DOCS:```sh
sudo tee /etc/httpd/conf.d/nominatim.conf << EOFAPACHECONF
-<Directory "$USERHOME/build/website"> #DOCS:<Directory "$USERHOME/Nominatim/build/website">
+<Directory "$USERHOME/build/website">
Options FollowSymLinks MultiViews
AddType text/html .php
DirectoryIndex search.php
Require all granted
</Directory>
-Alias /nominatim $USERHOME/build/website #DOCS:Alias /nominatim $USERHOME/Nominatim/build/website
+Alias /nominatim $USERHOME/build/website
EOFAPACHECONF
#DOCS:```
# Then reload apache
#
+ sudo systemctl enable httpd
sudo systemctl restart httpd
-#
-# Adding SELinux Security Settings
-# --------------------------------
-#
-# It is a good idea to leave SELinux enabled and enforcing, particularly
-# with a web server accessible from the Internet. At a minimum the
-# following SELinux labeling should be done for Nominatim:
-
- sudo semanage fcontext -a -t httpd_sys_content_t "$USERHOME/Nominatim/(website|lib|settings)(/.*)?"
- sudo semanage fcontext -a -t lib_t "$USERHOME/Nominatim/module/nominatim.so"
- sudo restorecon -R -v $USERHOME/Nominatim
#
# Installing Nominatim
# The code must be built in a separate directory. Create this directory,
# then configure and build Nominatim in there:
- cd $USERHOME #DOCS: :::sh
+#DOCS: :::sh
+ cd $USERHOME
mkdir build
cd build
cmake $USERHOME/Nominatim
make
+#
+# Adding SELinux Security Settings
+# --------------------------------
+#
+# It is a good idea to leave SELinux enabled and enforcing, particularly
+# with a web server accessible from the Internet. At a minimum the
+# following SELinux labeling should be done for Nominatim:
+
+ sudo semanage fcontext -a -t httpd_sys_content_t "$USERHOME/Nominatim/(website|lib|settings)(/.*)?"
+ sudo semanage fcontext -a -t httpd_sys_content_t "$USERHOME/build/(website|lib|settings)(/.*)?"
+ sudo semanage fcontext -a -t lib_t "$USERHOME/build/module/nominatim.so"
+ sudo restorecon -R -v $USERHOME/Nominatim
+ sudo restorecon -R -v $USERHOME/build
+
+
# You need to create a minimal configuration file that tells nominatim
# the name of your webserver user and the URL of the website:
logEnd($oDB, $hLog, 1);
if ($sOutputFormat=='html') {
- $sSQL = "SELECT TO_CHAR(lastimportdate - '2 minutes'::interval,'YYYY/MM/DD HH24:MI')||' GMT' FROM import_status LIMIT 1";
+ $sSQL = "SELECT TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' FROM import_status LIMIT 1";
$sDataDate = chksql($oDB->getOne($sSQL));
$sTileURL = CONST_Map_Tile_URL;
$sTileAttribution = CONST_Map_Tile_Attribution;
}
if ($sOutputFormat == 'html') {
- $sDataDate = chksql($oDB->getOne("select TO_CHAR(lastimportdate - '2 minutes'::interval,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1"));
+ $sDataDate = chksql($oDB->getOne("select TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1"));
$sTileURL = CONST_Map_Tile_URL;
$sTileAttribution = CONST_Map_Tile_Attribution;
}
-include(CONST_BasePath.'/lib/template/address-'.$sOutputFormat.'.php');
+
+$sOutputTemplate = ($sOutputFormat=='jsonv2' ? 'json' : $sOutputFormat);
+include(CONST_BasePath.'/lib/template/address-'.$sOutputTemplate.'.php');
$aSearchResults = $oGeocode->lookup();
if ($sOutputFormat=='html') {
- $sDataDate = chksql($oDB->getOne("select TO_CHAR(lastimportdate - '2 minutes'::interval,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1"));
+ $sDataDate = chksql($oDB->getOne("select TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1"));
}
logEnd($oDB, $hLog, sizeof($aSearchResults));
if (CONST_Debug) exit;
-include(CONST_BasePath.'/lib/template/search-'.$sOutputFormat.'.php');
+$sOutputTemplate = ($sOutputFormat=='jsonv2' ? 'json' : $sOutputFormat);
+include(CONST_BasePath.'/lib/template/search-'.$sOutputTemplate.'.php');