]> git.openstreetmap.org Git - nominatim.git/commitdiff
Merge branch 'updatePHP' of https://github.com/ThomasBarris/Nominatim into ThomasBarr...
authorSarah Hoffmann <lonvia@denofr.de>
Tue, 2 Oct 2018 20:46:53 +0000 (22:46 +0200)
committerSarah Hoffmann <lonvia@denofr.de>
Tue, 2 Oct 2018 20:46:53 +0000 (22:46 +0200)
33 files changed:
AUTHORS
CMakeLists.txt
ChangeLog
README.md
Vagrantfile
docs/CMakeLists.txt
docs/admin/Faq.md
docs/admin/Installation.md
docs/admin/Migration.md
docs/api/Details.md
docs/api/Faq.md
docs/mkdocs.yml
lib/AddressDetails.php
lib/SearchDescription.php
lib/cmd.php
sql/tables.sql
test/README.md
test/bdd/api/reverse/language.feature
test/bdd/api/reverse/queries.feature
test/bdd/api/search/queries.feature
test/php/Nominatim/AddressDetailsTest.php [new file with mode: 0644]
test/php/Nominatim/ClassTypesTest.php [new file with mode: 0644]
test/php/Nominatim/DebugTest.php
test/php/Nominatim/LibTest.php
test/php/Nominatim/ParameterParserTest.php
test/php/Nominatim/PhraseTest.php
test/php/Nominatim/SearchContextTest.php
test/php/Nominatim/StatusTest.php
test/php/Nominatim/TokenListTest.php
test/php/bootstrap.php
test/php/fixtures/address_details_10_downing_street.json [new file with mode: 0644]
test/php/phpunit.xml [moved from phpunit.xml with 81% similarity]
vagrant/Install-on-Ubuntu-18.sh [new file with mode: 0755]

diff --git a/AUTHORS b/AUTHORS
index a94d288eed4f50dc01651f8d0d37fcf202ca00a2..fc28bf2e7fea28d8e32a4e484de14371cc4de1b8 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,16 +3,13 @@ Nominatim was written by:
   Brian Quinion
   Sarah Hoffmann
   Marc Tobias Metten
+
   markigail
+  gemo1011
   IrlJidel
   Frederik Ramm
-  Michael Spreng
-  Daniele Forsi
-  mfn
-  Grant Slater
-  Andree Klattenhoff
-  appelflap
-  b3nn0
-  Spin0us
-  Kurt Roeckx
-  Rodolphe Quiédeville
+
+and many more.
+
+For a full list of contributors see
+https://github.com/openstreetmap/Nominatim/graphs/contributors
index af6b9a92657e91bdfc22ac859821b39871a2a19b..a7c7b3951463441c95adf6ddb9a44c67a4c8c6b8 100755 (executable)
@@ -19,7 +19,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
 project(nominatim)
 
 set(NOMINATIM_VERSION_MAJOR 3)
-set(NOMINATIM_VERSION_MINOR 1)
+set(NOMINATIM_VERSION_MINOR 2)
 set(NOMINATIM_VERSION_PATCH 0)
 
 set(NOMINATIM_VERSION "${NOMINATIM_VERSION_MAJOR}.${NOMINATIM_VERSION_MINOR}.${NOMINATIM_VERSION_PATCH}")
index 3bd80bd5a2391a310787c2ac986960b03a20a010..31c5f2263926ec3eb89927110a2830537ee9599d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+3.2.0
+
+ * complete rewrite of reverse search algorithm
+ * add new geojson and geocodejson output formats
+ * add simple export script to exprot addresses to CSV
+ * remove is_in terms from address computation
+ * remove unused search_name_country tables
+ * various smaller fixes to query parsing
+ * convert Tokens and token types to class types
+ * correctly handle update when boundary object type is changed
+ * improve debug output for /search endpoint
+ * update to latest osm2pgsql and leaflet.js
+ * overhaul of /details endpoint:
+     * new class parameter when using osmtype/osmid parameters
+     * permalink to instance-independent osmtype/osmid parameter format
+     * new json output format
+ * update CentOS vagrant machine to use SELinux
+ * add vagrant scripts for Ubuntu 18.04
+ * fix build process for BSD
+ * enable running the database on a different host than the setup scripts
+ * allow to configure use of custom PHP binaries (PHP_BIN)
+ * extensive coding style improvements to PHP code
+ * more PHP unit tests for new classes
+ * increase coverage for API tests
+ * add documentation for API
+
 3.1.0
 
  * rework postcode handling and introduce location_postcode table
index 406f7c858a065a11ffa56c6d806680a94f471fce..dd900e3e91f434df9792174473eb9d2306f91538 100644 (file)
--- a/README.md
+++ b/README.md
@@ -47,11 +47,17 @@ License
 
 The source code is available under a GPLv2 license.
 
-Contact and Bug reports
-======================
+
+Contributing
+============
+
+Contributions are welcome. For details see [CONTRIBUTING.md](contribution guide).
+
+Both bug reports and pull requests are welcome.
+
+
+Mailing list
+============
 
 For questions you can join the geocoding mailinglist, see
 https://lists.openstreetmap.org/listinfo/geocoding
-
-Bugs may be reported on the github project site:
-https://github.com/openstreetmap/Nominatim
index 5c9563bd0ef0ced397584b24eb94bd6efa9ded25..bd610e7e756fda910b69da6838cc6a398907c80f 100644 (file)
@@ -15,6 +15,15 @@ Vagrant.configure("2") do |config|
   end
 
   config.vm.define "ubuntu", primary: true do |sub|
+      sub.vm.box = "bento/ubuntu-18.04"
+      sub.vm.provision :shell do |s|
+        s.path = "vagrant/Install-on-Ubuntu-18.sh"
+        s.privileged = false
+        s.args = [checkout]
+      end
+  end
+
+  config.vm.define "ubuntu16" do |sub|
       sub.vm.box = "bento/ubuntu-16.04"
       sub.vm.provision :shell do |s|
         s.path = "vagrant/Install-on-Ubuntu-16.sh"
index f50b38ab12f098f83d01243d07935695a8599626..cbe91b91d355e90416b0aa30be7d096cec010b25 100644 (file)
@@ -14,6 +14,7 @@ ADD_CUSTOM_TARGET(doc
    COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/extra.css ${CMAKE_CURRENT_BINARY_DIR}/extra.css
    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
+   COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bash2md.sh ${PROJECT_SOURCE_DIR}/vagrant/Install-on-Ubuntu-18.sh ${CMAKE_CURRENT_BINARY_DIR}/appendix/Install-on-Ubuntu-18.md
    COMMAND mkdocs build -d ${CMAKE_CURRENT_BINARY_DIR}/../site-html -f ${CMAKE_CURRENT_BINARY_DIR}/../mkdocs.yml
 )
 
index 46da7e21ba0b8384e9d3ff8c38804124a9cf6f3e..a0e1cafebc5849f328502a43f661f02b67ece61b 100644 (file)
@@ -93,6 +93,14 @@ However, you can solve this the quick and dirty way by commenting out that line
     sudo systemctl restart httpd
 
 
+### "must be an array or an object that implements Countable" warning in /usr/share/pear/DB.php
+
+As reported starting PHP 7.2. This external DB library is no longer maintained and will be replaced in future Nominatim versions. In the meantime you'd have to manually change the line near 774 from
+`if (!count($dsn)) {` to  `if (!$dsn && !count($dsn))`. [More details](https://github.com/openstreetmap/Nominatim/issues/1184)
+
+
+
+
 ### Website reports "DB Error: insufficient permissions"
 
 The user the webserver, e.g. Apache, runs under needs to have access to the Nominatim database. You can find the user like [this](https://serverfault.com/questions/125865/finding-out-what-user-apache-is-running-as), for default Ubuntu operating system for example it's `www-data`.
index 3d276c0615948ba8fa7aaf5ba88a8183f9e1f5e1..592c6cc19e0b85209da671a0cdfb8d5e0d1f308e 100644 (file)
@@ -4,6 +4,7 @@ This page contains generic installation instructions for Nominatim and its
 prerequisites. There are also step-by-step instructions available for
 the following operating systems:
 
+  * [Ubuntu 18.04](../appendix/Install-on-Ubuntu-18.md)
   * [Ubuntu 16.04](../appendix/Install-on-Ubuntu-16.md)
   * [CentOS 7.2](../appendix/Install-on-Centos-7.md)
 
index 0a522488473eb497fef821c1d866d835c7fb0b10..012c58b328eff4064ccff1e72b63c43b83952461 100644 (file)
@@ -6,6 +6,51 @@ to newer versions of Nominatim.
 SQL statements should be executed from the postgres commandline. Execute
 `psql nominiatim` to enter command line mode.
 
+## 3.1.0 -> 3.2.0
+
+### New reverse algorithm
+
+The reverse algorithm has changed and requires new indexes. Run the following
+SQL statements to create the indexes:
+
+```
+CREATE INDEX idx_placex_geometry_reverse_lookupPoint
+  ON placex USING gist (geometry)
+  WHERE (name is not null or housenumber is not null or rank_address between 26 and 27)
+    AND class not in ('railway','tunnel','bridge','man_made')
+    AND rank_address >= 26 AND indexed_status = 0 AND linked_place_id is null;
+CREATE INDEX idx_placex_geometry_reverse_lookupPolygon
+  ON placex USING gist (geometry)
+  WHERE St_GeometryType(geometry) in ('ST_Polygon', 'ST_MultiPolygon')
+    AND rank_address between 4 and 25 AND type != 'postcode'
+    AND name is not null AND indexed_status = 0 AND linked_place_id is null;
+CREATE INDEX idx_placex_geometry_reverse_placeNode
+  ON placex USING gist (geometry)
+  WHERE osm_type = 'N' AND rank_search between 5 and 25
+    AND class = 'place' AND type != 'postcode'
+    AND name is not null AND indexed_status = 0 AND linked_place_id is null;
+```
+
+You also need to grant the website user access to the `country_osm_grid` table:
+
+```
+GRANT SELECT ON table country_osm_grid to "www-user";
+```
+
+Replace the `www-user` with the user name of your website server if necessary.
+
+You can now drop the unused indexes:
+
+```
+DROP INDEX idx_placex_reverse_geometry;
+```
+
+Finally, update all SQL functions:
+
+```sh
+./utils/setup.php --create-functions --enable-diff-updates --create-partition-functions
+```
+
 ## 3.0.0 -> 3.1.0
 
 ### Postcode Table
index 66b52409b5b33d0848dcab8059e3f95ce198aebf..027138a9b73615869f4723bb3eb3a35ae9dcec34 100644 (file)
@@ -10,12 +10,18 @@ Lookup details about a single place by id. The default output is HTML for debugg
 The details API supports the following two request formats:
 
 ```
-  https://nominatim.openstreetmap.org/details?osmtype=[N|W|R]&osmid=<value>
+  https://nominatim.openstreetmap.org/details?osmtype=[N|W|R]&osmid=<value>&class=<value>
 ```
 
-Both parameters are required, the type is one of node(N), way(W) or relation(R).
-
-Or
+`osmtype` and `osmid` are required parameter. The type is one of node (N), way (W)
+or relation (R). The id must be a number. The `class` parameter is optional and
+allows to distinguish between entries, when the corresponding OSM object has more
+than one main tag. For example, when a place is tagged with `tourism=hotel` and
+`amenity=restaurant`, there will be two place entries in Nominatim, one for a
+restaurant, one for a hotel. You need to specify `class=tourism` or `class=amentity`
+to get exactly the one you want. If there are multiple places in the database
+but the `class` parameter is left out, then one of the places will be chosen
+at random and displayed.
 
 ```
   https://nominatim.openstreetmap.org/details?placeid=<value>
index cc6397d35c3eed9d6ee9e792fda552904be446a2..6bc5b5e831c4cb4adac8adca089aa8e283f7a32d 100644 (file)
@@ -41,3 +41,21 @@ border while the closest street is on the other. As the address details contain
 the address of the closest object found, you might sometimes get one result,
 sometimes the other for the closest point.
 
+#### 4. Can you return the continent?
+
+Nominatim assigns each map feature one country. Those outside any administrative
+boundaries are assigned a special no-country. Continents or other super-national
+administrations (e.g. European Union, NATO, Custom unions) are not supported, 
+see also [Administrative Boundary](https://wiki.openstreetmap.org/wiki/Tag:boundary%3Dadministrative#Super-national_administrations).
+
+#### 5. Can you return the timezone?
+
+See this separate OpenStreetMap-based project [Timezone Boundary Builder](https://github.com/evansiroky/timezone-boundary-builder)
+
+#### 6. I want to download a list of streets/restaurants of a city/region
+
+The [Overpass API](https://wiki.openstreetmap.org/wiki/Overpass_API) is more
+suited for these kinds of queries.
+
+That said if you installed your own Nominatim instance you can use the
+`/utils/export.php` PHP script as basis to return such lists.
index 219176f6219532f04c956c5aa97339fcb3ac4803..b620decf19bbed792e0aa9b15f4c450d5e7a4d69 100644 (file)
@@ -23,6 +23,7 @@ pages:
     - 'Appendix':
         - 'Installation on CentOS 7' : 'appendix/Install-on-Centos-7.md'
         - 'Installation on Ubuntu 16' : 'appendix/Install-on-Ubuntu-16.md'
+        - 'Installation on Ubuntu 18' : 'appendix/Install-on-Ubuntu-18.md'
 markdown_extensions:
     - codehilite:
         use_pygments: False
index badf868de8774ab5c568b1119a51594e8c987882..e6501b572d5b59b3632a0d61e14f711f5fa729c9 100644 (file)
@@ -22,9 +22,9 @@ class AddressDetails
         }
 
         $sSQL = 'SELECT *,';
-        $sSQL .= '  get_name_by_language(name,'.$mLangPref.') as localname';
+        $sSQL .= ' get_name_by_language(name,'.$mLangPref.') as localname';
         $sSQL .= ' FROM get_addressdata('.$iPlaceID.','.$sHousenumber.')';
-        $sSQL .= ' ORDER BY rank_address desc,isaddress DESC';
+        $sSQL .= ' ORDER BY rank_address DESC, isaddress DESC';
 
         $this->aAddressLines = chksql($oDB->getAll($sSQL));
     }
@@ -40,7 +40,7 @@ class AddressDetails
             return $this->aAddressLines;
         }
 
-        return array_filter($this->aAddressLines, 'AddressDetails::isAddress');
+        return array_filter($this->aAddressLines, array(__CLASS__, 'isAddress'));
     }
 
     public function getLocaleAddress()
index 079cb8a6e65d1c72d8dd8693e40d740569206d45..35424b529244c9071a89d808a2419e3dba00f0ab 100644 (file)
@@ -287,7 +287,7 @@ class SearchDescription
             if (!empty($this->aName) || !($bFirstPhrase || $sPhraseType == '')) {
                 if (($sPhraseType == '' || !$bFirstPhrase) && !$bHasPartial) {
                     $oSearch = clone $this;
-                    $oSearch->iSearchRank++;
+                    $oSearch->iSearchRank += 2;
                     $oSearch->aAddress[$iWordID] = $iWordID;
                     $aNewSearches[] = $oSearch;
                 } else {
index 101868109c8f2cd9cca82810583e6a9962799820..44923618723636b86aec3c17f9f3ae4df3742e83 100644 (file)
@@ -186,7 +186,7 @@ function runSQLScript($sScript, $bfatal = true, $bVerbose = false, $bIgnoreError
     }
 
     if (!$bVerbose) {
-        fwrite($ahPipes[0], "set client_min_messages to WARNING;");
+        fwrite($ahPipes[0], 'set client_min_messages to WARNING;');
     }
 
     while (strlen($sScript)) {
index 4a22a814feab17140a2af2b0f994fa9bfb0b1935..949dc6ffe1c8c26dc7e6bb48727b61c4a9443a42 100644 (file)
@@ -10,7 +10,7 @@ drop table if exists import_osmosis_log;
 CREATE TABLE import_osmosis_log (
   batchend timestamp,
   batchseq integer,
-  batchsize integer,
+  batchsize bigint,
   starttime timestamp,
   endtime timestamp,
   event text
index 0487fd404da664e8f3a5891f36306c509cc7ac40..9b777412d20830d77d19800ef2fcc798f3f32699 100644 (file)
@@ -72,12 +72,12 @@ The tests can be configured with a set of environment variables:
  * `TEMPLATE_DB` - name of template database used as a skeleton for
                    the test databases (db tests)
  * `TEST_DB` - name of test database (db tests)
- * `ABI_TEST_DB` - name of the database containing the API test data (api tests)
+ * `API_TEST_DB` - name of the database containing the API test data (api tests)
  * `DB_HOST` - (optional) hostname of database host
  * `DB_USER` - (optional) username of database login
  * `DB_PASS` - (optional) password for database login
  * `SERVER_MODULE_PATH` - (optional) path on the Postgres server to Nominatim
*                        module shared library file
                         module shared library file
  * `TEST_SETTINGS_TEMPLATE` - file to write temporary Nominatim settings to
  * `REMOVE_TEMPLATE` - if true, the template database will not be reused during
                        the next run. Reusing the base templates speeds up tests
@@ -117,8 +117,8 @@ planets are likely to work as well but you may see isolated test
 failures where the data has changed. To recreate the input data
 for the test database run:
 
-    wget https://free.nchc.org.tw/osm.planet/pbf/planet-160725.osm.pbf
-    osmconvert planet-160725.osm.pbf -B=test/testdb/testdb.polys -o=testdb.pbf
+    wget https://ftp5.gwdg.de/pub/misc/openstreetmap/planet.openstreetmap.org/pbf/planet-180924.osm.pbf
+    osmconvert planet-180924.osm.pbf -B=test/testdb/testdb.polys -o=testdb.pbf
 
 Before importing make sure to add the following to your local settings:
 
index 9bde2d4e7eafcf59862c052674adf93a24d14374..9ead4e020289399f0b9f9e2ce6125c2c87ec7a53 100644 (file)
@@ -5,7 +5,7 @@ Feature: Localization of reverse search results
         When sending json reverse coordinates 18.1147,-15.95
         Then result addresses contain
           | ID | country |
-          | 0  | Mauritanie موريتانيا |
+          | 0  | موريتانيا |
 
     Scenario: accept-language parameter
         When sending json reverse coordinates 18.1147,-15.95
index 88f3bccbc34756e3b7b8284a541d14d323012864..1973f0b94aea217d8bdd6a28e66e1dced07dd96b 100644 (file)
@@ -31,7 +31,7 @@ Feature: Reverse geocoding
           | way      | place    | house |
         And result addresses contain
           | house_number | road |
-          | 1410         | Juan Antonio Lavalleja |
+          | 1416         | Juan Antonio Lavalleja |
 
     Scenario: Address with non-numerical house number
         When sending jsonv2 reverse coordinates 53.579805460944,9.9475670458196
@@ -50,7 +50,7 @@ Feature: Reverse geocoding
         When sending jsonv2 reverse coordinates 54.046489113,8.5546870529
         Then results contain
          | display_name |
-         | Freie und Hansestadt Hamburg, Deutschland |
+         | Hamburg, Deutschland |
 
     Scenario: When slightly outside town, the town is not shown
         When sending jsonv2 reverse coordinates -32.122,-56.114
index 5ef8f7ed8bbf9139f4edfef88238089734fb5f87..832d888468a9bd8027dd4e3f249c47339ee3093f 100644 (file)
@@ -19,30 +19,32 @@ Feature: Search queries
           | accept-language |
           | de |
         Then address of result 0 is
-          | type         | value |
-          | house_number | 86 |
-          | road         | Schellingstraße |
-          | suburb       | Eilbek |
-          | postcode     | 22089 |
+          | type          | value |
+          | house_number  | 86 |
+          | road          | Schellingstraße |
+          | neighbourhood | Auenviertel |
+          | suburb        | Eilbek |
+          | postcode      | 22089 |
           | city_district | Wandsbek |
-          | state        | Hamburg |
-          | country      | Deutschland |
-          | country_code | de |
+          | state         | Hamburg |
+          | country       | Deutschland |
+          | country_code  | de |
 
     Scenario: House number interpolation odd
         When sending json search query "Schellingstr 73, Hamburg" with address
           | accept-language |
           | de |
         Then address of result 0 is
-          | type         | value |
-          | house_number | 73 |
-          | road         | Schellingstraße |
-          | suburb       | Eilbek |
-          | postcode     | 22089 |
+          | type          | value |
+          | house_number  | 73 |
+          | road          | Schellingstraße |
+          | neighbourhood | Auenviertel |
+          | suburb        | Eilbek |
+          | postcode      | 22089 |
           | city_district | Wandsbek |
-          | state        | Hamburg |
-          | country      | Deutschland |
-          | country_code | de |
+          | state         | Hamburg |
+          | country       | Deutschland |
+          | country_code  | de |
 
     Scenario: With missing housenumber search falls back to road
         When sending json search query "342 rocha, santa lucia" with address
diff --git a/test/php/Nominatim/AddressDetailsTest.php b/test/php/Nominatim/AddressDetailsTest.php
new file mode 100644 (file)
index 0000000..62faf1a
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+
+namespace Nominatim;
+
+require_once(CONST_BasePath.'/lib/AddressDetails.php');
+
+
+function chksql($oSql, $sMsg = 'Database request failed')
+{
+    return $oSql;
+}
+
+class AddressDetailsTest extends \PHPUnit\Framework\TestCase
+{
+
+    protected function setUp()
+    {
+        // How the fixture got created
+        //
+        // 1) search for '10 downing street'
+        // https://nominatim.openstreetmap.org/details.php?osmtype=R&osmid=1879842
+        //
+        // 2) find place_id in the local database
+        // SELECT place_id, name FROM placex WHERE osm_type='R' AND osm_id=1879842;
+        //
+        // 3) set postgresql to non-align output, e.g. psql -A or \a in the CLI
+        //
+        // 4) query
+        // SELECT row_to_json(row,true) FROM (
+        //   SELECT *, get_name_by_language(name, ARRAY['name:en']) as localname
+        //   FROM get_addressdata(194663412,10)
+        //   ORDER BY rank_address DESC, isaddress DESC
+        // ) AS row;
+        //
+        // 5) copy&paste into file. Add commas between records
+        //
+        $json = file_get_contents(CONST_BasePath.'/test/php/fixtures/address_details_10_downing_street.json');
+        $data = json_decode($json, true);
+
+        $this->oDbStub = $this->getMockBuilder(\DB::class)
+                              ->setMethods(array('getAll'))
+                              ->getMock();
+        $this->oDbStub->method('getAll')
+                      ->willReturn($data);
+    }
+
+    public function testGetLocaleAddress()
+    {
+        $oAD = new AddressDetails($this->oDbStub, 194663412, 10, 'en');
+        $expected = join(', ', array(
+            '10 Downing Street',
+            '10',
+            'Downing Street',
+            'St. James\'s',
+            'Covent Garden',
+            'Westminster',
+            'London',
+            'Greater London',
+            'England',
+            'SW1A 2AA',
+            'United Kingdom'
+        ));
+        $this->assertEquals($expected, $oAD->getLocaleAddress());
+    }
+
+    public function testGetAddressDetails()
+    {
+        $oAD = new AddressDetails($this->oDbStub, 194663412, 10, 'en');
+        $this->assertEquals(18, count($oAD->getAddressDetails(true)));
+        $this->assertEquals(12, count($oAD->getAddressDetails(false)));
+    }
+
+    public function testGetAddressNames()
+    {
+        $oAD = new AddressDetails($this->oDbStub, 194663412, 10, 'en');
+        $expected = array(
+                     'attraction' => '10 Downing Street',
+                     'house_number' => '10',
+                     'road' => 'Downing Street',
+                     'neighbourhood' => 'St. James\'s',
+                     'suburb' => 'Covent Garden',
+                     'city' => 'London',
+                     'state_district' => 'Greater London',
+                     'state' => 'England',
+                     'postcode' => 'SW1A 2AA',
+                     'country' => 'United Kingdom',
+                     'country_code' => 'gb'
+        );
+
+        $this->assertEquals($expected, $oAD->getAddressNames());
+    }
+
+    public function testGetAdminLevels()
+    {
+        $oAD = new AddressDetails($this->oDbStub, 194663412, 10, 'en');
+        $expected = array(
+                     'level8' => 'Westminster',
+                     'level6' => 'London',
+                     'level5' => 'Greater London',
+                     'level4' => 'England',
+                     'level2' => 'United Kingdom'
+        );
+        $this->assertEquals($expected, $oAD->getAdminLevels());
+    }
+
+    public function testDebugInfo()
+    {
+        $oAD = new AddressDetails($this->oDbStub, 194663412, 10, 'en');
+        $this->assertTrue(is_array($oAD->debugInfo()));
+        $this->assertEquals(18, count($oAD->debugInfo()));
+    }
+}
diff --git a/test/php/Nominatim/ClassTypesTest.php b/test/php/Nominatim/ClassTypesTest.php
new file mode 100644 (file)
index 0000000..8d8481f
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+
+namespace Nominatim;
+
+require_once(CONST_BasePath.'/lib/ClassTypes.php');
+
+class ClassTypesTest extends \PHPUnit\Framework\TestCase
+{
+    public function testGetInfo()
+    {
+        // 1) Admin level set
+        // city Dublin
+        // https://nominatim.openstreetmap.org/details.php?osmtype=R&osmid=1109531
+        $aPlace = array(
+                   'admin_level' => 7,
+                   'class' => 'boundary',
+                   'type' => 'administrative',
+                   'rank_address' => 14
+        );
+
+        $this->assertEquals('County', ClassTypes\getInfo($aPlace)['label']);
+        $this->assertEquals('County', ClassTypes\getFallbackInfo($aPlace)['label']);
+        $this->assertEquals('County', ClassTypes\getProperty($aPlace, 'label'));
+
+        // 2) No admin level
+        // Eiffel Tower
+        // https://nominatim.openstreetmap.org/details.php?osmtype=W&osmid=5013364
+        $aPlace = array(
+                   'class' => 'tourism',
+                   'type' => 'attraction',
+                   'rank_address' => 29
+        );
+        $this->assertEquals('Attraction', ClassTypes\getInfo($aPlace)['label']);
+        $this->assertEquals(array('simplelabel' => 'address29'), ClassTypes\getFallbackInfo($aPlace));
+        $this->assertEquals('Attraction', ClassTypes\getProperty($aPlace, 'label'));
+
+        // 3) Unknown type
+        // La Maison du Toutou, Paris
+        // https://nominatim.openstreetmap.org/details.php?osmtype=W&osmid=164011651
+        $aPlace = array(
+                   'class' => 'shop',
+                   'type' => 'pet_grooming',
+                   'rank_address' => 29
+        );
+        $this->assertEquals(false, ClassTypes\getInfo($aPlace));
+        $this->assertEquals(array('simplelabel' => 'address29'), ClassTypes\getFallbackInfo($aPlace));
+        $this->assertEquals(false, ClassTypes\getProperty($aPlace, 'label'));
+        $this->assertEquals('mydefault', ClassTypes\getProperty($aPlace, 'label', 'mydefault'));
+    }
+
+    public function testGetClassTypesWithImportance()
+    {
+        $aClasses = ClassTypes\getListWithImportance();
+
+        $this->assertGreaterThan(
+            200,
+            count($aClasses)
+        );
+
+        $this->assertEquals(
+            array(
+             'label' => 'Country',
+             'frequency' => 0,
+             'icon' => 'poi_boundary_administrative',
+             'defzoom' => 6,
+             'defdiameter' => 15,
+             'importance' => 3
+            ),
+            $aClasses['place:country']
+        );
+    }
+
+
+    public function testGetResultDiameter()
+    {
+        $aResult = array('class' => '', 'type' => '');
+        $this->assertEquals(
+            0.0001,
+            ClassTypes\getProperty($aResult, 'defdiameter', 0.0001)
+        );
+
+        $aResult = array('class' => 'place', 'type' => 'country');
+        $this->assertEquals(
+            15,
+            ClassTypes\getProperty($aResult, 'defdiameter', 0.0001)
+        );
+
+        $aResult = array('class' => 'boundary', 'type' => 'administrative', 'admin_level' => 6);
+        $this->assertEquals(
+            0.32,
+            ClassTypes\getProperty($aResult, 'defdiameter', 0.0001)
+        );
+    }
+}
index 6e0c25f3a22a150b4b4838c5ffeaba03713f09e5..7ef1dba336836be7f6f6626a75f36943e6edb472 100644 (file)
@@ -2,19 +2,23 @@
 
 namespace Nominatim;
 
-use Exception;
+require_once(CONST_BasePath.'/lib/DebugHtml.php');
 
-require_once('../../lib/DebugHtml.php');
-
-class DebugTest extends \PHPUnit_Framework_TestCase
+class DebugTest extends \PHPUnit\Framework\TestCase
 {
+
     protected function setUp()
     {
-        $this->oWithDebuginfo = $this->getMock(Geocode::class, array('debugInfo'));
+        $this->oWithDebuginfo = $this->getMockBuilder(\GeococdeMock::class)
+                                    ->setMethods(array('debugInfo'))
+                                    ->getMock();
         $this->oWithDebuginfo->method('debugInfo')
                   ->willReturn(array('key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3'));
 
-        $this->oWithToString = $this->getMock(Geocode::class, array('__toString'));
+
+        $this->oWithToString = $this->getMockBuilder(\SomeMock::class)
+                                    ->setMethods(array('__toString'))
+                                    ->getMock();
         $this->oWithToString->method('__toString')->willReturn('me as string');
     }
 
index 55ae1aaa055eaf93dfb4693bdf9c9b33edf77381..2891388d371b83976a8b50ae9dce379b916e47df 100644 (file)
@@ -2,55 +2,8 @@
 
 namespace Nominatim;
 
-require_once '../../lib/lib.php';
-require_once '../../lib/ClassTypes.php';
-
-class LibTest extends \PHPUnit_Framework_TestCase
+class LibTest extends \PHPUnit\Framework\TestCase
 {
-    public function testGetClassTypesWithImportance()
-    {
-        $aClasses = ClassTypes\getListWithImportance();
-
-        $this->assertGreaterThan(
-            200,
-            count($aClasses)
-        );
-
-        $this->assertEquals(
-            array(
-             'label' => 'Country',
-             'frequency' => 0,
-             'icon' => 'poi_boundary_administrative',
-             'defzoom' => 6,
-             'defdiameter' => 15,
-             'importance' => 3
-            ),
-            $aClasses['place:country']
-        );
-    }
-
-
-    public function testGetResultDiameter()
-    {
-        $aResult = array('class' => '', 'type' => '');
-        $this->assertEquals(
-            0.0001,
-            ClassTypes\getProperty($aResult, 'defdiameter', 0.0001)
-        );
-
-        $aResult = array('class' => 'place', 'type' => 'country');
-        $this->assertEquals(
-            15,
-            ClassTypes\getProperty($aResult, 'defdiameter', 0.0001)
-        );
-
-        $aResult = array('class' => 'boundary', 'type' => 'administrative', 'admin_level' => 6);
-        $this->assertEquals(
-            0.32,
-            ClassTypes\getProperty($aResult, 'defdiameter', 0.0001)
-        );
-    }
-
 
     public function testAddQuotes()
     {
index 0cbc60c545c5494b74d05493073ecbdc1b8d5008..9f51a629f09d99856a9d4bbf6b7748dfa9a27542 100644 (file)
@@ -2,17 +2,15 @@
 
 namespace Nominatim;
 
-use Exception;
-
-require_once('../../lib/ParameterParser.php');
+require_once(CONST_BasePath.'/lib/ParameterParser.php');
 
 
 function userError($sError)
 {
-    throw new Exception($sError);
+    throw new \Exception($sError);
 }
 
-class ParameterParserTest extends \PHPUnit_Framework_TestCase
+class ParameterParserTest extends \PHPUnit\Framework\TestCase
 {
 
 
@@ -55,14 +53,18 @@ class ParameterParserTest extends \PHPUnit_Framework_TestCase
 
     public function testGetIntWithNonNumber()
     {
-        $this->setExpectedException(Exception::class, "Integer number expected for parameter 'int4'");
+        $this->expectException(\Exception::class);
+        $this->expectExceptionMessage("Integer number expected for parameter 'int4'");
+
         (new ParameterParser(array('int4' => 'a')))->getInt('int4');
     }
 
 
     public function testGetIntWithEmpytString()
     {
-        $this->setExpectedException(Exception::class, "Integer number expected for parameter 'int5'");
+        $this->expectException(\Exception::class);
+        $this->expectExceptionMessage("Integer number expected for parameter 'int5'");
+
         (new ParameterParser(array('int5' => '')))->getInt('int5');
     }
 
@@ -85,20 +87,26 @@ class ParameterParserTest extends \PHPUnit_Framework_TestCase
 
     public function testGetFloatWithEmptyString()
     {
-        $this->setExpectedException(Exception::class, "Floating-point number expected for parameter 'float4'");
+        $this->expectException(\Exception::class);
+        $this->expectExceptionMessage("Floating-point number expected for parameter 'float4'");
+
         (new ParameterParser(array('float4' => '')))->getFloat('float4');
     }
 
     public function testGetFloatWithTextString()
     {
-        $this->setExpectedException(Exception::class, "Floating-point number expected for parameter 'float5'");
+        $this->expectException(\Exception::class);
+        $this->expectExceptionMessage("Floating-point number expected for parameter 'float5'");
+
         (new ParameterParser(array('float5' => 'a')))->getFloat('float5');
     }
 
 
     public function testGetFloatWithInvalidNumber()
     {
-        $this->setExpectedException(Exception::class, "Floating-point number expected for parameter 'float6'");
+        $this->expectException(\Exception::class);
+        $this->expectExceptionMessage("Floating-point number expected for parameter 'float6'");
+
         (new ParameterParser(array('float6' => '-55.')))->getFloat('float6');
     }
 
@@ -138,7 +146,9 @@ class ParameterParserTest extends \PHPUnit_Framework_TestCase
 
     public function testGetSetWithValueNotInSet()
     {
-        $this->setExpectedException(Exception::class, "Parameter 'val4' must be one of: foo, bar");
+        $this->expectException(\Exception::class);
+        $this->expectExceptionMessage("Parameter 'val4' must be one of: foo, bar");
+
         (new ParameterParser(array('val4' => 'faz')))->getSet('val4', array('foo', 'bar'));
     }
 
index b5e6c1bf6e666b0f3a6c631648f3bc24865566e6..cd74271543c7979300ea6026dd3109bb2c03a944 100644 (file)
@@ -2,9 +2,9 @@
 
 namespace Nominatim;
 
-require_once '../../lib/Phrase.php';
+require_once(CONST_BasePath.'/lib/Phrase.php');
 
-class PhraseTest extends \PHPUnit_Framework_TestCase
+class PhraseTest extends \PHPUnit\Framework\TestCase
 {
 
 
index db0b2dee1de20c4338f6cbd9d3ba1f6c42ec254a..166e6433d141d259007cbc5b7e17686149d49faf 100644 (file)
@@ -2,11 +2,9 @@
 
 namespace Nominatim;
 
-@define('CONST_BasePath', '../../');
+require_once(CONST_BasePath.'/lib/SearchContext.php');
 
-require_once '../../lib/SearchContext.php';
-
-class SearchContextTest extends \PHPUnit_Framework_TestCase
+class SearchContextTest extends \PHPUnit\Framework\TestCase
 {
     private $oCtx;
 
index 06823720c48e582a3c70f219822bce5303594a8d..4f21706ecaf9274ce74740d750025152dc2c133a 100644 (file)
@@ -2,18 +2,17 @@
 
 namespace Nominatim;
 
-require_once('../../lib/Status.php');
-require_once('DB.php');
+require_once(CONST_BasePath.'/lib/Status.php');
 
-use Exception;
 
-class StatusTest extends \PHPUnit_Framework_TestCase
+class StatusTest extends \PHPUnit\Framework\TestCase
 {
 
-
     public function testNoDatabaseGiven()
     {
-        $this->setExpectedException(Exception::class, 'No database', 700);
+        $this->expectException(\Exception::class);
+        $this->expectExceptionMessage('No database');
+        $this->expectExceptionCode(700);
 
         $oDB = null;
         $oStatus = new Status($oDB);
@@ -22,7 +21,9 @@ class StatusTest extends \PHPUnit_Framework_TestCase
 
     public function testNoDatabaseConnectionFail()
     {
-        $this->setExpectedException(Exception::class, 'No database', 700);
+        $this->expectException(\Exception::class);
+        $this->expectExceptionMessage('No database');
+        $this->expectExceptionCode(700);
 
         // causes 'Non-static method should not be called statically, assuming $this from incompatible context'
         // failure on travis
@@ -40,10 +41,14 @@ class StatusTest extends \PHPUnit_Framework_TestCase
 
     public function testModuleFail()
     {
-        $this->setExpectedException(Exception::class, 'Module call failed', 702);
+        $this->expectException(\Exception::class);
+        $this->expectExceptionMessage('Module call failed');
+        $this->expectExceptionCode(702);
 
         // stub has getOne method but doesn't return anything
-        $oDbStub = $this->getMock(\DB::class, array('getOne'));
+        $oDbStub = $this->getMockBuilder(\DB::class)
+                        ->setMethods(array('getOne'))
+                        ->getMock();
 
         $oStatus = new Status($oDbStub);
         $this->assertNull($oStatus->status());
@@ -52,9 +57,13 @@ class StatusTest extends \PHPUnit_Framework_TestCase
 
     public function testWordIdQueryFail()
     {
-        $this->setExpectedException(Exception::class, 'No value', 704);
+        $this->expectException(\Exception::class);
+        $this->expectExceptionMessage('No value');
+        $this->expectExceptionCode(704);
 
-        $oDbStub = $this->getMock(\DB::class, array('getOne'));
+        $oDbStub = $this->getMockBuilder(\DB::class)
+                        ->setMethods(array('getOne'))
+                        ->getMock();
 
         // return no word_id
         $oDbStub->method('getOne')
@@ -70,7 +79,9 @@ class StatusTest extends \PHPUnit_Framework_TestCase
 
     public function testOK()
     {
-        $oDbStub = $this->getMock(\DB::class, array('getOne'));
+        $oDbStub = $this->getMockBuilder(\DB::class)
+                        ->setMethods(array('getOne'))
+                        ->getMock();
 
         $oDbStub->method('getOne')
                 ->will($this->returnCallback(function ($sql) {
@@ -84,7 +95,9 @@ class StatusTest extends \PHPUnit_Framework_TestCase
 
     public function testDataDate()
     {
-        $oDbStub = $this->getMock(\DB::class, array('getOne'));
+        $oDbStub = $this->getMockBuilder(\DB::class)
+                        ->setMethods(array('getOne'))
+                        ->getMock();
      
         $oDbStub->method('getOne')
                 ->willReturn(1519430221);
index 38f13e184db8ea73ad8261b18b205d32d3b37085..fa1331e87b17d187fc0ebbd29b15e9c3b9567703 100644 (file)
@@ -2,17 +2,18 @@
 
 namespace Nominatim;
 
-@define('CONST_BasePath', '../../');
+require_once(CONST_BasePath.'/lib/db.php');
+require_once(CONST_BasePath.'/lib/cmd.php');
+require_once(CONST_BasePath.'/lib/TokenList.php');
 
-require_once '../../lib/db.php';
-require_once '../../lib/cmd.php';
-require_once '../../lib/TokenList.php';
 
-class TokenTest extends \PHPUnit_Framework_TestCase
+class TokenTest extends \PHPUnit\Framework\TestCase
 {
     protected function setUp()
     {
-        $this->oNormalizer = $this->getMock(\MockNormalizer::class, array('transliterate'));
+        $this->oNormalizer = $this->getMockBuilder(\MockNormalizer::class)
+                                  ->setMethods(array('transliterate'))
+                                  ->getMock();
         $this->oNormalizer->method('transliterate')
                           ->will($this->returnCallback(function ($text) {
                               return strtolower($text);
@@ -55,7 +56,9 @@ class TokenTest extends \PHPUnit_Framework_TestCase
     {
         $this->expectOutputRegex('/<p><tt>/');
 
-        $oDbStub = $this->getMock(\DB::class, array('getAll'));
+        $oDbStub = $this->getMockBuilder(\DB::class)
+                        ->setMethods(array('getAll'))
+                        ->getMock();
         $oDbStub->method('getAll')
                 ->will($this->returnCallback(function ($sql) {
                     $aResults = array();
index b3d9bbc7f3711e882119cd6b3af051245d859d04..0d4759622ff06f0ec8d6e4d09e2a673e4eb06a38 100644 (file)
@@ -1 +1,2 @@
 <?php
+    @define('CONST_BasePath', '../..');
diff --git a/test/php/fixtures/address_details_10_downing_street.json b/test/php/fixtures/address_details_10_downing_street.json
new file mode 100644 (file)
index 0000000..853a6c0
--- /dev/null
@@ -0,0 +1,217 @@
+[{"place_id":194663412,
+ "osm_type":null,
+ "osm_id":null,
+ "name":{"name": "10 Downing Street", "name:en": "10 Downing Street", "name:es": "10 de Downing Street", "name:he": "דאונינג 10", "name:ko": "다우닝 가 10번지", "name:zh": "唐寧街10號"},
+ "class":"tourism",
+ "type":"attraction",
+ "admin_level":null,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":29,
+ "distance":0,
+ "localname":"10 Downing Street"},
+{"place_id":194663412,
+ "osm_type":null,
+ "osm_id":null,
+ "name":{"ref": "10"},
+ "class":"place",
+ "type":"house_number",
+ "admin_level":null,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":28,
+ "distance":0,
+ "localname":"10"},
+{"place_id":68310941,
+ "osm_type":"W",
+ "osm_id":4244999,
+ "name":{"name": "Downing Street"},
+ "class":"highway",
+ "type":"residential",
+ "admin_level":15,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":26,
+ "distance":0,
+ "localname":"Downing Street"},
+{"place_id":16037318,
+ "osm_type":"N",
+ "osm_id":1653239257,
+ "name":{"name": "St. James's"},
+ "class":"place",
+ "type":"neighbourhood",
+ "admin_level":15,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":22,
+ "distance":0.00982435489434447,
+ "localname":"St. James's"},
+{"place_id":51691981,
+ "osm_type":"N",
+ "osm_id":3937587633,
+ "name":{"name": "St Clement Danes"},
+ "class":"place",
+ "type":"neighbourhood",
+ "admin_level":15,
+ "fromarea":true,
+ "isaddress":false,
+ "rank_address":22,
+ "distance":0.0128768181947227,
+ "localname":"St Clement Danes"},
+{"place_id":22208313,
+ "osm_type":"N",
+ "osm_id":2290086954,
+ "name":{"name": "Covent Garden"},
+ "class":"place",
+ "type":"suburb",
+ "admin_level":15,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":20,
+ "distance":0.00935748249317067,
+ "localname":"Covent Garden"},
+{"place_id":21742712,
+ "osm_type":"N",
+ "osm_id":2288030397,
+ "name":{"name": "Millbank"},
+ "class":"place",
+ "type":"suburb",
+ "admin_level":15,
+ "fromarea":true,
+ "isaddress":false,
+ "rank_address":20,
+ "distance":0.0106525181285902,
+ "localname":"Millbank"},
+{"place_id":122775,
+ "osm_type":"N",
+ "osm_id":26745371,
+ "name":{"name": "St Giles"},
+ "class":"place",
+ "type":"suburb",
+ "admin_level":15,
+ "fromarea":true,
+ "isaddress":false,
+ "rank_address":20,
+ "distance":0.0136188357358441,
+ "localname":"St Giles"},
+{"place_id":134882,
+ "osm_type":"N",
+ "osm_id":27553719,
+ "name":{"name": "Lambeth"},
+ "class":"place",
+ "type":"suburb",
+ "admin_level":15,
+ "fromarea":true,
+ "isaddress":false,
+ "rank_address":20,
+ "distance":0.0093308163978298,
+ "localname":"Lambeth"},
+{"place_id":194276676,
+ "osm_type":"R",
+ "osm_id":51781,
+ "name":{"name": "City of Westminster", "name:be": "Вэстмінстэр", "name:cy": "San Steffan", "name:en": "Westminster", "name:he": "וסטמינסטר", "name:ru": "Вестминстер"},
+ "class":"place",
+ "type":"city",
+ "admin_level":8,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":16,
+ "distance":0.0340909562148044,
+ "localname":"Westminster"},
+{"place_id":195398522,
+ "osm_type":"N",
+ "osm_id":107775,
+ "name":{"name": "London", "name:ab": "Лондан", "name:af": "Londen", "name:am": "ለንደን", "name:an": "Londres", "name:ar": "لندن", "name:ba": "Лондон", "name:be": "Лондан", "name:bg": "Лондон", "name:bn": "লন্ডন", "name:bo": "ལོན་ཊོན།", "name:br": "Londrez", "name:ca": "Londres", "name:co": "Londra", "name:cs": "Londýn", "name:cu": "Лондонъ", "name:cv": "Лондон", "name:cy": "Llundain", "name:de": "London", "name:el": "Λονδίνο", "name:en": "London", "name:eo": "Londono", "name:es": "Londres", "name:eu": "Londres", "name:fa": "لندن", "name:fi": "Lontoo", "name:fr": "Londres", "name:fy": "Londen", "name:ga": "Londain", "name:gd": "Lunnainn", "name:gl": "Londres - London", "name:gn": "Londye", "name:gu": "લંડન", "name:gv": "Lunnin", "name:he": "לונדון", "name:hi": "लंदन", "name:ht": "Lonn", "name:hu": "London", "name:hy": "Լոնդոն", "name:is": "Lundúnir", "name:it": "Londra", "name:ja": "ロンドン", "name:ka": "ლონდონი", "name:kk": "Лондон", "name:kn": "ಲಂಡನ್", "name:ko": "런던", "name:ku": "London", "name:kv": "Лондон", "name:kw": "Loundres", "name:ky": "Лондон", "name:la": "Londinium", "name:li": "Londe", "name:ln": "Londoni", "name:lo": "ລອນດອນ", "name:lt": "Londonas", "name:lv": "Londona", "name:mi": "Rānana", "name:mk": "Лондон", "name:ml": "ലണ്ടൻ", "name:mn": "Лондон", "name:mr": "लंडन", "name:mt": "Londra", "name:my": "လန်ဒန်မြို့", "name:ne": "लण्डन", "name:nl": "Londen", "name:no": "London", "name:oc": "Londres", "name:or": "ଲଣ୍ଡନ", "name:os": "Лондон", "name:pl": "Londyn", "name:ps": "لندن", "name:pt": "Londres", "name:rm": "Londra", "name:ro": "Londra", "name:ru": "Лондон", "name:sa": "लन्डन्", "name:sc": "Londra", "name:si": "ලන්ඩන්", "name:sk": "Londýn", "name:sq": "Londra", "name:sr": "Лондон", "name:sv": "London", "name:ta": "இலண்டன்", "name:te": "లండన్", "name:tg": "Лондон", "name:th": "ลอนดอน", "name:tl": "Londres", "name:tr": "Londra", "name:tt": "Лондон", "name:uk": "Лондон", "name:ur": "لندن", "name:vi": "Luân Đôn", "name:wo": "Londar", "name:yi": "לאנדאן", "name:yo": "Lọndọnu", "name:zh": "倫敦", "name:zu": "ILondon", "name:ang": "Lunden", "name:arc": "ܠܘܢܕܘܢ", "name:arz": "لندن", "name:ast": "Londres", "name:bcl": "Londres", "name:cdo": "Lùng-dŭng", "name:ckb": "لەندەن", "name:diq": "Londra", "name:eml": "Lòndra", "name:ext": "Londri", "name:frp": "Londres", "name:gan": "倫敦", "name:haw": "Lākana", "name:ilo": "Londres", "name:jbo": "london", "name:koi": "Лондон", "name:krc": "Лондон", "name:lad": "Londra", "name:lbe": "Лондон", "name:lez": "Лондон", "name:lij": "Londra", "name:lmo": "Lundra", "name:mhr": "Лондон", "name:mrj": "Лондон", "name:mwl": "Londres", "name:mzn": "لندن", "name:nah": "Londres", "name:nap": "Londra", "name:new": "लण्डन", "name:nrm": "Londres", "name:pcd": "Londe", "name:pms": "Londra", "name:pnb": "لندن", "name:pnt": "Λονδίνο", "name:rue": "Лондон", "name:sah": "Лондон", "name:scn": "Londra", "name:sco": "Lunnon", "name:szl": "Lůndůn", "name:tet": "Londres", "name:tpi": "Landen", "name:tzl": "Londra", "name:udm": "Лондон", "name:vec": "Łondra", "name:vls": "Londn", "name:wuu": "伦敦", "name:xmf": "ლონდონი", "name:yue": "倫敦", "name:zea": "Londen", "name:nds-nl": "Londen", "name:bat-smg": "Londons", "name:roa-rup": "Londra", "name:roa-tara": "Londre", "name:be-tarask": "Лёндан", "name:zh_pinyin": "Lúndūn", "name:zh-classical": "倫敦", "name:zh-simplified": "伦敦", "name:zh-traditional": "倫敦"},
+ "class":"place",
+ "type":"city",
+ "admin_level":2,
+ "fromarea":true,
+ "isaddress":false,
+ "rank_address":16,
+ "distance":0.00412384196971048,
+ "localname":"London"},
+{"place_id":193774423,
+ "osm_type":"R",
+ "osm_id":65606,
+ "name":{"name": "London", "name:be": "Лондан", "name:ca": "Londres", "name:el": "Λονδίνο", "name:en": "London", "name:eo": "Londono", "name:es": "Londres", "name:fa": "لندن", "name:fi": "Lontoo", "name:fr": "Londres", "name:fy": "Londen", "name:gl": "Londres", "name:hi": "लंदन", "name:lt": "Londonas", "name:nl": "Londen", "name:pl": "Londyn", "name:pt": "Londres", "name:ru": "Лондон", "name:uk": "Лондон", "name:vi": "Luân Đôn", "name:zh": "伦敦", "int_name": "London", "name:szl": "Lůndůn", "name:tzl": "Londra", "name:be-tarask": "Лёндан"},
+ "class":"place",
+ "type":"city",
+ "admin_level":6,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":12,
+ "distance":0.0172243361058611,
+ "localname":"London"},
+{"place_id":194000080,
+ "osm_type":"R",
+ "osm_id":175342,
+ "name":{"name": "Greater London", "name:be": "Вялікі Лондан", "name:de": "Groß-London", "name:en": "Greater London", "name:fr": "Grand Londres", "name:lt": "Didysis Londonas", "name:ru": "Большой Лондон", "name:uk": "Великий Лондон", "official_name": "Greater London (incl. City of London)", "name:be-tarask": "Вялікі Лёндан"},
+ "class":"boundary",
+ "type":"administrative",
+ "admin_level":5,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":10,
+ "distance":0.0172532381571105,
+ "localname":"Greater London"},
+{"place_id":194325361,
+ "osm_type":"R",
+ "osm_id":58447,
+ "name":{"name": "England", "name:be": "Англія", "name:br": "Bro-Saoz", "name:ca": "Anglaterra", "name:cs": "Anglie", "name:cy": "Lloegr", "name:de": "England", "name:el": "Αγγλία", "name:en": "England", "name:eo": "Anglujo", "name:es": "Inglaterra", "name:fi": "Englanti", "name:fr": "Angleterre", "name:fy": "Ingelân", "name:ga": "Sasana", "name:gd": "Sasainn", "name:gv": "Sostyn", "name:he": "אנגליה", "name:hu": "Anglia", "name:ia": "Anglaterra", "name:io": "Anglia", "name:it": "Inghilterra", "name:la": "Anglia", "name:lt": "Anglija", "name:nl": "Engeland", "name:pl": "Anglia", "name:pt": "Inglaterra", "name:ru": "Англия", "name:sk": "Anglicko", "name:sv": "England", "name:tr": "İngiltere", "name:uk": "Англія", "name:vi": "Anh", "name:vo": "Linglän", "name:zh": "英格蘭", "name:hsb": "Jendźelska", "name:nds": "England", "name:tok": "ma Inli", "name:tzl": "Anglatzara", "alt_name:eo": "Anglio", "alt_name:ia": "Anglia", "old_name:vi": "Anh Quốc", "alt_name:nds": "Ingland", "name:be-tarask": "Ангельшчына", "name:zh-classical": "英格蘭", "name:zh-simplified": "英格兰", "name:zh-traditional": "英格蘭"},
+ "class":"boundary",
+ "type":"administrative",
+ "admin_level":4,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":8,
+ "distance":1.75192967136328,
+ "localname":"England"},
+{"place_id":null,
+ "osm_type":null,
+ "osm_id":null,
+ "name":{"ref": "SW1A 2AA"},
+ "class":"place",
+ "type":"postcode",
+ "admin_level":null,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":5,
+ "distance":0,
+ "localname":"SW1A 2AA"},
+{"place_id":40715006,
+ "osm_type":"N",
+ "osm_id":3055075992,
+ "name":{"ref": "SW1A 2AQ"},
+ "class":"place",
+ "type":"postcode",
+ "admin_level":15,
+ "fromarea":true,
+ "isaddress":false,
+ "rank_address":5,
+ "distance":0.00172905579146705,
+ "localname":"SW1A 2AQ"},
+{"place_id":194354400,
+ "osm_type":"R",
+ "osm_id":62149,
+ "name":{"name": "United Kingdom", "name:ab": "Британиа Ду", "name:af": "Verenigde Koninkryk", "name:ak": "United Kingdom", "name:am": "ዩናይትድ ኪንግደም", "name:an": "Reino Unito", "name:ar": "المملكة المتحدة", "name:az": "Böyük Britaniya", "name:ba": "Бөйөк Британия", "name:be": "Вялікабрытанія", "name:bg": "Обединено кралство Великобритания и Северна Ирландия", "name:bi": "Unaeted Kingdom", "name:bm": "Angilɛtɛri", "name:bn": "যুক্তরাজ্য", "name:bo": "དབྱིན་ཇི་མཉམ་འབྲེལ།", "name:br": "Rouantelezh-Unanet", "name:bs": "Ujedinjeno Kraljevstvo Velike Britanije i Sjeverne Irske", "name:ca": "Regne Unit", "name:ce": "Йоккха Британи", "name:co": "Regnu Unitu", "name:cs": "Spojené království", "name:cu": "Вєлика Британїꙗ", "name:cv": "Аслă Британи", "name:cy": "Deyrnas Unedig", "name:da": "Storbritannien", "name:de": "Vereinigtes Königreich", "name:dv": "ޔުނައިޓެޑް ކިންގްޑަމް", "name:dz": "ཡུ་ནའི་ཊེཊ་ཀིང་ཌམ", "name:ee": "United Kingdom", "name:el": "Ηνωμένο Βασίλειο", "name:en": "United Kingdom", "name:eo": "Britujo", "name:es": "Reino Unido", "name:et": "Suurbritannia", "name:eu": "Erresuma Batua", "name:fa": "بریتانیا", "name:ff": "Laamateeri Rentundi", "name:fi": "Yhdistynyt kuningaskunta", "name:fo": "Stóra Bretland", "name:fr": "Royaume-Uni", "name:fy": "Feriene Keninkryk", "name:ga": "An Ríocht Aontaithe", "name:gd": "An Rìoghachd Aonaichte", "name:gl": "Reino Unido", "name:gn": "Tavetã Joaju", "name:gu": "યુનાઇટેડ કિંગડમ", "name:gv": "Reeriaght Unnaneysit", "name:ha": "Birtaniya", "name:he": "הממלכה המאוחדת", "name:hi": "यूनाइटेड किंगडम", "name:hr": "Ujedinjeno Kraljevstvo", "name:ht": "Wayòm Ini", "name:hu": "Egyesült Királyság", "name:hy": "Միացյալ Թագավորություն", "name:ia": "Regno Unite", "name:id": "Britania Raya", "name:ie": "Reyatu Unit", "name:ig": "Obodoézè Nà Ofú", "name:ii": "ꑱꇩ", "name:io": "Unionita Rejio", "name:is": "Bretland", "name:it": "Regno Unito", "name:ja": "イギリス", "name:jv": "Britania Raya", "name:ka": "გაერთიანებული სამეფო", "name:kg": "Royaume-Uni", "name:ki": "Ngeretha", "name:kk": "Ұлыбритания", "name:kl": "Tuluit Nunaat", "name:km": "រាជាណាចក្ររួម", "name:kn": "ಯುನೈಟೆಡ್ ಕಿಂಗ್ಡಂ", "name:ko": "영국", "name:ks": "یُنایٹِڑ کِنٛگڈَم", "name:ku": "Keyaniya Yekbûyî", "name:kv": "Ыджыд Британия", "name:kw": "Ruwvaneth Unys", "name:ky": "Улуу Британия жана Түндүк Ирландия", "name:la": "Britanniarum Regnum", "name:lb": "Groussbritannien an Nordirland", "name:lg": "Bungereza", "name:li": "Vereineg Keuninkriek", "name:ln": "Ingɛlɛ́tɛlɛ", "name:lo": "ສະຫະລາດຊະອານາຈັກ", "name:lt": "Jungtinė Karalystė", "name:lv": "Apvienotā Karaliste", "name:mg": "Fanjakana Mitambatra", "name:mi": "Kīngitanga Kotahi", "name:mk": "Обединето Кралство", "name:ml": "യുണൈറ്റഡ് കിങ്ഡം", "name:mn": "Их Британи", "name:mr": "युनायटेड किंग्डम", "name:ms": "United Kingdom", "name:mt": "Renju Unit", "name:my": "ယူနိုက်တက်ကင်းဒမ်းနိုင်ငံ", "name:na": "Ingerand", "name:ne": "संयुक्त अधिराज्य", "name:nl": "Verenigd Koninkrijk", "name:nn": "Storbritannia", "name:no": "Storbritannia", "name:nv": "Tótaʼ Dinéʼiʼ Bikéyah", "name:oc": "Reialme Unit", "name:or": "ଯୁକ୍ତରାଜ୍ୟ", "name:os": "Стыр Британи", "name:pa": "ਸੰਯੁਕਤ ਬਾਦਸ਼ਾਹੀ", "name:pl": "Wielka Brytania", "name:ps": "بريتانيا", "name:pt": "Reino Unido", "name:qu": "Hukllachasqa Qhapaq Suyu", "name:rm": "Reginavel Unì", "name:rn": "Ubwongereza", "name:ro": "Regatul Unit al Marii Britanii și al Irlandei de Nord", "name:ru": "Великобритания", "name:rw": "Ubwongereza", "name:sa": "संयुक्त अधिराज्य", "name:sc": "Rennu Auniadu", "name:se": "Ovttastuvvan gonagasriika", "name:sg": "Ködörögbïä--Ôko", "name:sh": "Ujedinjeno Kraljevstvo", "name:si": "එක්සත් රාජධානිය", "name:sk": "Spojené kráľovstvo", "name:sl": "Združeno kraljestvo Velike Britanije in Severne Irske", "name:sn": "United Kingdom", "name:so": "Midowga boqortooyada Britan", "name:sq": "Mbretëria e Bashkuar e Britanisë dhe Irlandës së Veriut", "name:sr": "Уједињено Краљевство", "name:ss": "United Kingdom", "name:su": "Britania", "name:sv": "Storbritannien", "name:sw": "Ufalme wa Muungano", "name:ta": "ஐக்கிய இராச்சியம்", "name:te": "యునైటెడ్ కింగ్డమ్", "name:tg": "Подшоҳии Муттаҳида", "name:th": "สหราชอาณาจักร", "name:ti": "እንግሊዝ", "name:tl": "Nagkakaisang Kaharian", "name:to": "Pilitānia", "name:tr": "Birleşik Krallık", "name:tt": "Бөекбритания", "name:tw": "United Kingdom", "name:ty": "Paratāne", "name:ug": "بۈيۈك بېرىتانىيە", "name:uk": "Велика Британія", "name:ur": "برطانیہ", "name:uz": "Birlashgan Qirollik", "name:vi": "Vương quốc Anh", "name:vo": "Regän Pebalöl", "name:wo": "Nguur-Yu-Bennoo", "name:yi": "פאראייניגטע קעניגרייך", "name:yo": "Ilẹ̀ọba Aṣọ̀kan", "name:za": "Yinghgoz", "name:zh": "英國", "name:zu": "Umbuso Ohlangeneyo", "alt_name": "United Kingdom; UK; Britain; Great Britain", "int_name": "United Kingdom", "name:als": "Vereinigtes Königreich", "name:ang": "Geāned Cynerīce", "name:arc": "ܡܠܟܘܬܐ ܡܚܝܕܬܐ", "name:arz": "المملكه المتحده", "name:ast": "Reinu Xuníu", "name:bar": "Vaeinigts Kinireich", "name:bcl": "Reyno Unido", "name:bjn": "Britania Raya", "name:bpy": "তিলপারাজ্য", "name:bug": "United Kingdom", "name:bxr": "Нэгдсэн Вант Улс", "name:cdo": "Ĭng-guók", "name:ceb": "Hiniusang Gingharian", "name:chr": "ᎡᎵᏏᎯ", "name:chy": "United Kingdom", "name:ckb": "شانشینی یەکگرتوو", "name:crh": "Büyük Britaniya", "name:csb": "Wiôlgô Britanijô", "name:diq": "Qraliya Yewbiyayiye", "name:dsb": "Wjelika Britaniska", "name:eml": "Régn Unî", "name:ext": "Réinu Uniu", "name:frp": "Royômo-Uni", "name:frr": "Feriind Kiningrik", "name:fur": "Ream Unît", "name:gag": "Büük Britaniya", "name:gan": "英國", "name:hak": "Yîn-koet", "name:haw": "Aupuni Mōʻī Hui Pū ʻia", "name:hif": "United Kingdom", "name:hsb": "Zjednoćene kralestwo", "name:ilo": "Nagkaykaysa a Pagarian", "name:jbo": "ritygu'e", "name:kab": "Legliz", "name:kbd": "Британиэшхуэ", "name:koi": "Ыджыт Бритму", "name:krc": "Уллу Британия", "name:ksh": "Jrußbritannie", "name:lad": "Reyno Unido", "name:lez": "ЧIехибритания", "name:lfn": "Rena Unida", "name:lij": "Regno Unïo", "name:lmo": "Regn Ünì", "name:ltg": "Lelbrytaneja", "name:mhr": "Ушымо Королевстве", "name:mrj": "Кого Британи", "name:mwl": "Reino Ounido", "name:mzn": "بریتانیا", "name:nah": "Tlacetilīlli Huēyitlahtohcāyōtl", "name:nap": "Gran Vretagna", "name:nds": "Vereenigt Königriek vun Grootbritannien un Noordirland", "name:nov": "Unionati Regia", "name:nrm": "Rouoyaume Unni", "name:pag": "Reino Unido", "name:pam": "Pisanmetung a Ka-arian", "name:pap": "Reino Uni", "name:pcd": "Roéyôme-Uni", "name:pih": "Yunitid Kingdum", "name:pms": "Regn Unì", "name:pnb": "برطانیہ", "name:pnt": "Ηνωμένο Βασίλειο", "name:rmy": "Phandlo Thagaripen la Bare Britaniyako thai le Nordutne Irlandesko", "name:rue": "Велика Брітанія", "name:sah": "Холбоhуктаах Хоруоллук", "name:scn": "Regnu Unitu", "name:sco": "Unitit Kinrick", "name:srn": "Ingriskondre", "name:stq": "Fereeniged Köönichriek fon Groot-Britannien un Noudirlound", "name:szl": "Wjelgo Brytańijo", "name:tet": "Reinu Naklibur", "name:tok": "ma Juke", "name:tpi": "Yunaitet Kingdom", "name:tzl": "Regipäts Viensiçat", "name:udm": "Великобритания", "name:vec": "Regno Unìo", "name:vep": "Sur' Britanii", "name:vls": "Verênigd Keunienkryk", "name:war": "Reino Unido", "name:wuu": "英国", "name:xal": "Ик Бритишин болн Ар Гәәлгүдин Ниицәтә Нутг", "name:xmf": "გოართოიანაფილი ომაფე", "name:yue": "英國", "name:zea": "Vereênigd Konienkriek", "name:zh_py": "Yingguo", "short_name": "UK", "alt_name:eo": "Britio", "alt_name:sr": "УК;У.К.", "alt_name:vi": "Vương quốc Liên hiệp Anh", "name:nds-nl": "Verienigd Keuninkriek", "name:zh_pyt": "Yīngguó", "name:bat-smg": "Jongtėnė Karalīstė", "name:cbk-zam": "Reinos Unidos de Gran Britania y Norte Irelandia", "name:fiu-vro": "Ütiskuningriik", "name:roa-rup": "Britania Mari", "name:roa-tara": "Regne Aunìte", "official_name": "United Kingdom of Great Britain and Northern Ireland", "short_name:el": "ΗΒ", "short_name:vo": "Britän", "name:be-tarask": "Вялікабрытанія", "name:zh-min-nan": "Liân-ha̍p Ông-kok", "official_name:be": "Злучанае Каралеўства Вялікабрытаніі і Паўночнай Ірландыі", "official_name:br": "Rouantelezh Unanet Breizh-Veur ha Norzhiwerzhon", "official_name:ca": "Regne Unit de Gran Bretanya i Irlanda del Nord", "official_name:cs": "Spojené království Velké Británie a Severního Irska", "official_name:de": "Vereinigtes Königreich Großbritannien und Nordirland", "official_name:el": "Ηνωμένο Βασίλειο της Μεγάλης Βρετανίας και της Βόρειας Ιρλανδίας", "official_name:en": "United Kingdom of Great Britain and Northern Ireland", "official_name:eo": "Unuiĝinta Reĝlando de Granda Britujo kaj Nord-Irlando", "official_name:es": "Reino Unido de Gran Bretaña", "official_name:et": "Suurbritannia ja Põhja-Iiri Ühendkuningriik", "official_name:fr": "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord", "official_name:hr": "Ujedinjeno Kraljevstvo Velike Britanije i Sjeverne Irske", "official_name:id": "Perserikatan Kerajaan Britania Raya dan Irlandia Utara", "official_name:it": "Regno Unito di Gran Bretagna e Irlanda del Nord", "official_name:ja": "グレートブリテン及び北アイルランド連合王国", "official_name:ku": "Keyaniya Yekbûyî ya Brîtaniya Mezin û Bakurê Îrlandê", "official_name:lb": "Vereenegt Kinnekräich vu Groussbritannien an Nordirland", "official_name:no": "Det forente kongeriket Storbritannia og Nord-Irland", "official_name:pl": "Zjednoczone Królestwo Wielkiej Brytanii i Irlandii Północnej", "official_name:pt": "Reino Unido da Grã-Bretanha e Irlanda do Norte", "official_name:ru": "Соединённое королевство Великобритании и Северной Ирландии", "official_name:sk": "Spojené kráľovstvo Veľkej Británie a Severného Írska", "official_name:sl": "Združeno kraljestvo Velike Britanije in Severne Irske", "official_name:sr": "Уједињено Краљевство Велике Британије и Северне Ирске", "official_name:sv": "Förenade konungariket Storbritannien och Nordirland", "official_name:vi": "Vương quốc Liên hiệp Anh và Bắc Ireland", "name:abbreviation": "UK", "name:zh-classical": "英國", "official_name:scn": "Regnu Unitu di Gran Britagna e Irlanna dû Nord", "name:zh-simplified": "英国", "name:zh-traditional": "英國"},
+ "class":"place",
+ "type":"country",
+ "admin_level":2,
+ "fromarea":true,
+ "isaddress":true,
+ "rank_address":4,
+ "distance":4.56060933645498,
+ "localname":"United Kingdom"},
+{"place_id":null,
+ "osm_type":null,
+ "osm_id":null,
+ "name":{"ref": "gb"},
+ "class":"place",
+ "type":"country_code",
+ "admin_level":null,
+ "fromarea":true,
+ "isaddress":false,
+ "rank_address":4,
+ "distance":0,
+ "localname":"gb"}
+]
\ No newline at end of file
similarity index 81%
rename from phpunit.xml
rename to test/php/phpunit.xml
index addce5ce37154a96df2e505c800bd1bbe193e9f3..1fc95795c1d0b86b3704488e10956f493f0b1d26 100644 (file)
@@ -8,13 +8,14 @@
     processIsolation="false"
     stopOnFailure="false"
     syntaxCheck="true"
-    bootstrap="test/php/bootstrap.php"
+    bootstrap="./bootstrap.php"
+    beStrictAboutTestsThatDoNotTestAnything="true"
     >
     <php>
     </php>
     <testsuites>
         <testsuite name="Nominatim PHP Test Suite">
-            <directory>./test/php/Nominatim</directory>
+            <directory>./Nominatim</directory>
         </testsuite>
     </testsuites>
     <filter>
diff --git a/vagrant/Install-on-Ubuntu-18.sh b/vagrant/Install-on-Ubuntu-18.sh
new file mode 100755 (executable)
index 0000000..4162f15
--- /dev/null
@@ -0,0 +1,171 @@
+#!/bin/bash
+#
+# hacks for broken vagrant box      #DOCS:
+sudo rm -f /var/lib/dpkg/lock       #DOCS:
+sudo update-locale LANG=en_US.UTF-8 #DOCS:
+export APT_LISTCHANGES_FRONTEND=none #DOCS:
+export DEBIAN_FRONTEND=noninteractive #DOCS:
+
+#
+# *Note:* these installation instructions are also available in executable
+#         form for use with vagrant under vagrant/Install-on-Ubuntu-18.sh.
+#
+# Installing the Required Software
+# ================================
+#
+# These instructions expect that you have a freshly installed Ubuntu 18.04.
+#
+# Make sure all packages are are up-to-date by running:
+#
+
+#DOCS:    :::sh
+    sudo apt-get -o DPkg::options::="--force-confdef" -o DPkg::options::="--force-confold" --force-yes -fuy install grub-pc #DOCS:
+    sudo apt-get update -qq
+
+# Now you can install all packages needed for Nominatim:
+
+    sudo apt-get install -y build-essential cmake g++ libboost-dev libboost-system-dev \
+                            libboost-filesystem-dev libexpat1-dev zlib1g-dev libxml2-dev \
+                            libbz2-dev libpq-dev libproj-dev \
+                            postgresql-server-dev-10 postgresql-10-postgis-2.4 \
+                            postgresql-contrib-10 postgresql-10-postgis-scripts \
+                            apache2 php php-pgsql libapache2-mod-php php-pear php-db \
+                            php-intl git
+
+# If you want to run the test suite, you need to install the following
+# additional packages:
+
+    sudo apt-get install -y python3-setuptools python3-dev python3-pip \
+                            python3-psycopg2 python3-tidylib phpunit php-cgi
+
+    pip3 install --user behave nose
+    sudo pear install PHP_CodeSniffer
+
+#
+# System Configuration
+# ====================
+#
+# The following steps are meant to configure a fresh Ubuntu installation
+# for use with Nominatim. You may skip some of the steps if you have your
+# OS already configured.
+#
+# Creating Dedicated User Accounts
+# --------------------------------
+#
+# Nominatim will run as a global service on your machine. It is therefore
+# best to install it under its own separate user account. In the following
+# 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
+#
+# You may find a more suitable location if you wish.
+#
+# To be able to copy and paste instructions from this manual, export
+# user name and home directory now like this:
+#
+    export USERNAME=vagrant        #DOCS:    export USERNAME=nominatim
+    export USERHOME=/home/vagrant  #DOCS:    export USERHOME=/srv/nominatim
+#
+# **Never, ever run the installation as a root user.** You have been warned.
+#
+# Make sure that system servers can read from the home directory:
+
+    chmod a+x $USERHOME
+
+# Setting up PostgreSQL
+# ---------------------
+#
+# Tune the postgresql configuration, which is located in 
+# `/etc/postgresql/10/main/postgresql.conf`. See section *Postgres Tuning* in
+# [the installation page](../admin/Installation.md#postgresql-tuning)
+# for the parameters to change.
+#
+# Restart the postgresql service after updating this config file.
+
+    sudo systemctl restart postgresql
+
+#
+# Finally, we need to add two postgres users: one for the user that does
+# the import and another for the webserver which should access the database
+# for reading only:
+#
+
+    sudo -u postgres createuser -s $USERNAME
+    sudo -u postgres createuser www-data
+
+#
+# Setting up the Apache Webserver
+# -------------------------------
+#
+# You need to create an alias to the website directory in your apache
+# configuration. Add a separate nominatim configuration to your webserver:
+
+#DOCS:```sh
+sudo tee /etc/apache2/conf-available/nominatim.conf << EOFAPACHECONF
+<Directory "$USERHOME/build/website"> #DOCS:<Directory "$USERHOME/Nominatim/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
+EOFAPACHECONF
+#DOCS:```
+
+sudo sed -i 's:#.*::' /etc/apache2/conf-available/nominatim.conf #DOCS:
+
+#
+# Then enable the configuration and restart apache
+#
+
+    sudo a2enconf nominatim
+    sudo systemctl restart apache2
+
+#
+# Installing Nominatim
+# ====================
+#
+# Building and Configuration
+# --------------------------
+#
+# Get the source code from Github and change into the source directory
+#
+if [ "x$1" == "xyes" ]; then  #DOCS:    :::sh
+    cd $USERHOME
+    git clone --recursive git://github.com/openstreetmap/Nominatim.git
+    cd Nominatim
+else                               #DOCS:
+    cd $USERHOME/Nominatim         #DOCS:
+fi                                 #DOCS:
+
+# When installing the latest source from github, you also need to
+# download the country grid:
+
+if [ ! -f data/country_osm_grid.sql.gz ]; then       #DOCS:    :::sh
+    wget -O data/country_osm_grid.sql.gz https://www.nominatim.org/data/country_grid.sql.gz
+fi                                 #DOCS:
+
+# The code must be built in a separate directory. Create this directory,
+# then configure and build Nominatim in there:
+
+    cd $USERHOME                   #DOCS:    :::sh
+    mkdir build
+    cd build
+    cmake $USERHOME/Nominatim
+    make
+
+# You need to create a minimal configuration file that tells nominatim
+# where it is located on the webserver:
+
+#DOCS:```sh
+tee settings/local.php << EOF
+<?php
+ @define('CONST_Website_BaseURL', '/nominatim/');
+EOF
+#DOCS:```
+
+
+# Nominatim is now ready to use. Continue with
+# [importing a database from OSM data](../admin/Import-and-Update.md).